Skip to content

Commit cdefecd

Browse files
committed
fix: remove TEST_INLINE_ATTRIBUTES, group by FQN instead
DATA_ATTRIBUTES share one explicit group. Other attributes (TestInline, Bench) are grouped by matching FQN — same attribute type = same group. Test attribute remains ungrouped (marker only). https://claude.ai/code/session_01TmFvjfMtoxTvddQRBzsbPN
1 parent af0c0fc commit cdefecd

6 files changed

Lines changed: 48 additions & 39 deletions

File tree

CLAUDE.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ The plugin recognizes PHP attributes defined in `TestoClasses.kt`. Constants are
144144
| Group (array) | Attributes (FQN) |
145145
|--------------------------|-----------------------------------------------------------------------------------|
146146
| `TEST_ATTRIBUTES` | `\Testo\Test`, `\Testo\Inline\TestInline` |
147-
| `TEST_INLINE_ATTRIBUTES` | `\Testo\Inline\TestInline` |
148147
| `DATA_ATTRIBUTES` | `\Testo\Data\DataProvider`, `\Testo\Data\DataSet`, `\Testo\Data\DataUnion`, `\Testo\Data\DataCross`, `\Testo\Data\DataZip` |
149148
| `BENCH_ATTRIBUTES` | `\Testo\Bench` |
150149

@@ -154,13 +153,13 @@ These arrays are spread into `RUNNABLE_ATTRIBUTES` (line markers) and `MEANINGFU
154153

155154
### Attribute Group Numbering
156155

157-
Attributes on a function/method are numbered **within their own group**, not globally. Each group has independent 0-based indexing. The groups are defined in `PsiUtil.ATTRIBUTE_GROUPS`:
156+
Attributes on a function/method are numbered **within their own group**, not globally. Each group has independent 0-based indexing:
158157

159-
| Group | Source array | Used for |
160-
|-------------------|---------------------------|-----------------------------------------------|
161-
| test data | `DATA_ATTRIBUTES` | Data providers for `#[Test]` methods |
162-
| inline | `TEST_INLINE_ATTRIBUTES` | Inline test cases (`#[TestInline]`) |
163-
| bench | `BENCH_ATTRIBUTES` | Benchmark data (`#[Bench]`) |
158+
- **test data** group: all `DATA_ATTRIBUTES` (DataProvider, DataSet, DataUnion, DataCross, DataZip) share one group — numbered together
159+
- **inline** group: each `TestInline` is numbered among other `TestInline` attributes (same FQN)
160+
- **bench** group: each `Bench` is numbered among other `Bench` attributes (same FQN)
161+
162+
Explicit multi-attribute groups are defined in `PsiUtil.ATTRIBUTE_GROUPS` (currently only `DATA_ATTRIBUTES`). All other meaningful attributes (except `Test`) are grouped by their own FQN — attributes with the same FQN form a group automatically.
164163

165164
The `#[Test]` attribute itself is **not numbered** — it is a marker only. The method/function name already gets its own gutter line marker.
166165

@@ -178,13 +177,13 @@ Example for a function `foo` with multiple attributes:
178177
#[Bench(...)] → type=bench, foo:1
179178
```
180179

181-
`RUNNABLE_ATTRIBUTES` (used for gutter line markers) contains `TEST_INLINE_ATTRIBUTES + BENCH_ATTRIBUTES + DATA_ATTRIBUTES` — it does **not** include `Test` since the method already gets a run marker via `getLocationInfo`.
180+
`RUNNABLE_ATTRIBUTES` (used for gutter line markers) contains `TestInline + BENCH_ATTRIBUTES + DATA_ATTRIBUTES` — it does **not** include `Test` since the method already gets a run marker via `getLocationInfo`.
182181

183182
### Test Detection Logic (mixin.kt)
184183

185184
A PHP element is recognized as a Testo test when:
186-
- **Method:** public + name starts with `test`, OR has any `TEST_ATTRIBUTES` / `TEST_INLINE_ATTRIBUTES`
187-
- **Function:** has any `TEST_ATTRIBUTES` / `TEST_INLINE_ATTRIBUTES` (standalone test functions)
185+
- **Method:** public + name starts with `test`, OR has any `TEST_ATTRIBUTES`
186+
- **Function:** has any `TEST_ATTRIBUTES` (standalone test functions)
188187
- **Benchmark:** has any `BENCH_ATTRIBUTES`
189188
- **Class:** name ends with `Test` or `TestBase`, OR contains test/bench methods
190189
- **File:** filename matches test class pattern, OR contains test classes/functions/benchmarks

src/main/kotlin/com/github/xepozz/testo/TestoClasses.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ object TestoClasses {
3030
TEST,
3131
TEST_INLINE,
3232
)
33-
val TEST_INLINE_ATTRIBUTES = arrayOf(
34-
TEST_INLINE,
35-
)
3633
val BENCH_ATTRIBUTES = arrayOf(
3734
BENCH,
3835
)

src/main/kotlin/com/github/xepozz/testo/tests/TestoTestRunLineMarkerProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class TestoTestRunLineMarkerProvider : RunLineMarkerContributor() {
9696

9797
companion object Companion {
9898
val RUNNABLE_ATTRIBUTES = arrayOf(
99-
*TestoClasses.TEST_INLINE_ATTRIBUTES,
99+
TestoClasses.TEST_INLINE,
100100
*TestoClasses.BENCH_ATTRIBUTES,
101101
*TestoClasses.DATA_ATTRIBUTES,
102102
)

src/main/kotlin/com/github/xepozz/testo/util/PsiUtil.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,19 @@ object PsiUtil {
1515

1616
val ATTRIBUTE_GROUPS: Array<Array<String>> = arrayOf(
1717
TestoClasses.DATA_ATTRIBUTES,
18-
TestoClasses.TEST_INLINE_ATTRIBUTES,
19-
TestoClasses.BENCH_ATTRIBUTES,
2018
)
2119

22-
fun getAttributeGroup(fqn: String?): Array<String>? =
23-
ATTRIBUTE_GROUPS.firstOrNull { fqn in it }
20+
fun getAttributeGroup(fqn: String?): Array<String>? {
21+
if (fqn == null) return null
22+
val group = ATTRIBUTE_GROUPS.firstOrNull { fqn in it }
23+
if (group != null) return group
24+
if (fqn in MEANINGFUL_ATTRIBUTES && fqn != TestoClasses.TEST) return arrayOf(fqn)
25+
return null
26+
}
2427

2528
fun getAttributeOrder(attribute: PhpAttribute, owner: PhpAttributesOwner): Int {
26-
val group = getAttributeGroup(attribute.fqn) ?: return -1
29+
val fqn = attribute.fqn ?: return -1
30+
val group = getAttributeGroup(fqn) ?: return -1
2731
return owner.attributes
2832
.filter { it.fqn in group }
2933
.indexOf(attribute)

src/test/kotlin/com/github/xepozz/testo/PsiUtilTest.kt

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ class PsiUtilTest : TestCase() {
6363
assertSame(TestoClasses.DATA_ATTRIBUTES, group)
6464
}
6565

66-
fun testGetAttributeGroup_testInlineInInlineGroup() {
66+
fun testGetAttributeGroup_testInlineHasGroup() {
6767
val group = PsiUtil.getAttributeGroup(TestoClasses.TEST_INLINE)
6868
assertNotNull("TestInline should have a group", group)
69-
assertSame(TestoClasses.TEST_INLINE_ATTRIBUTES, group)
69+
assertTrue(group!!.contains(TestoClasses.TEST_INLINE))
7070
}
7171

72-
fun testGetAttributeGroup_benchInBenchGroup() {
72+
fun testGetAttributeGroup_benchHasGroup() {
7373
val group = PsiUtil.getAttributeGroup(TestoClasses.BENCH)
7474
assertNotNull("Bench should have a group", group)
75-
assertSame(TestoClasses.BENCH_ATTRIBUTES, group)
75+
assertTrue(group!!.contains(TestoClasses.BENCH))
7676
}
7777

7878
fun testGetAttributeGroup_testHasNoGroup() {
@@ -88,7 +88,26 @@ class PsiUtilTest : TestCase() {
8888
assertNull(PsiUtil.getAttributeGroup("\\Some\\Unknown\\Attribute"))
8989
}
9090

91-
fun testAttributeGroups_allGroupedAttributesAreInMeaningful() {
91+
fun testGetAttributeGroup_allDataAttributesShareSameGroup() {
92+
val groups = TestoClasses.DATA_ATTRIBUTES.map { PsiUtil.getAttributeGroup(it) }
93+
val first = groups.first()
94+
for (group in groups) {
95+
assertSame("All data attributes should share the same group instance", first, group)
96+
}
97+
}
98+
99+
fun testGetAttributeGroup_inlineAndBenchAreSeparateGroups() {
100+
val inlineGroup = PsiUtil.getAttributeGroup(TestoClasses.TEST_INLINE)
101+
val benchGroup = PsiUtil.getAttributeGroup(TestoClasses.BENCH)
102+
assertNotNull(inlineGroup)
103+
assertNotNull(benchGroup)
104+
assertFalse(
105+
"Inline and bench groups should not overlap",
106+
inlineGroup!!.toSet().intersect(benchGroup!!.toSet()).isNotEmpty()
107+
)
108+
}
109+
110+
fun testAttributeGroups_allExplicitGroupsAreInMeaningful() {
92111
val meaningful = PsiUtil.MEANINGFUL_ATTRIBUTES.toSet()
93112
for (group in PsiUtil.ATTRIBUTE_GROUPS) {
94113
for (attr in group) {
@@ -97,7 +116,7 @@ class PsiUtilTest : TestCase() {
97116
}
98117
}
99118

100-
fun testAttributeGroups_noOverlapBetweenGroups() {
119+
fun testAttributeGroups_noOverlapBetweenExplicitGroups() {
101120
val groups = PsiUtil.ATTRIBUTE_GROUPS
102121
for (i in groups.indices) {
103122
for (j in i + 1 until groups.size) {
@@ -106,12 +125,4 @@ class PsiUtilTest : TestCase() {
106125
}
107126
}
108127
}
109-
110-
fun testAttributeGroups_totalCount() {
111-
val totalGrouped = PsiUtil.ATTRIBUTE_GROUPS.sumOf { it.size }
112-
val expectedGrouped = TestoClasses.DATA_ATTRIBUTES.size +
113-
TestoClasses.TEST_INLINE_ATTRIBUTES.size +
114-
TestoClasses.BENCH_ATTRIBUTES.size
115-
assertEquals(expectedGrouped, totalGrouped)
116-
}
117128
}

src/test/kotlin/com/github/xepozz/testo/TestoLineMarkerCompanionTest.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ class TestoLineMarkerCompanionTest : TestCase() {
2424
assertTrue("Should contain \\Testo\\Bench", runnable.contains(TestoClasses.BENCH))
2525
}
2626

27-
fun testRunnableAttributes_containsTestInlineAttributes() {
27+
fun testRunnableAttributes_containsTestInline() {
2828
val runnable = TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.toSet()
29-
for (attr in TestoClasses.TEST_INLINE_ATTRIBUTES) {
30-
assertTrue("Missing test inline attribute: $attr", runnable.contains(attr))
31-
}
29+
assertTrue("Missing TestInline attribute", runnable.contains(TestoClasses.TEST_INLINE))
3230
}
3331

3432
fun testRunnableAttributes_doesNotContainPlainTestAttribute() {
@@ -38,8 +36,8 @@ class TestoLineMarkerCompanionTest : TestCase() {
3836

3937
fun testRunnableAttributes_totalCount() {
4038
val expected = TestoClasses.DATA_ATTRIBUTES.size +
41-
TestoClasses.TEST_INLINE_ATTRIBUTES.size +
42-
TestoClasses.BENCH_ATTRIBUTES.size
39+
TestoClasses.BENCH_ATTRIBUTES.size +
40+
1 // TestInline
4341
assertEquals(expected, TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.size)
4442
}
4543
}

0 commit comments

Comments
 (0)