The synthesised body of a delegated-property accessor (`get`/`getValue`/
`setValue`/`invoke` calls, the `<prop>$delegate` access, associated type
accesses and property-reference classes) carries the source range of the
whole `KtPropertyDelegate` node. The K1 frontend's range starts at the
`by` keyword; K2 starts at the delegate expression itself
(e.g. `lazy { ... }`), three columns later. The `by` keyword is syntactic
glue in the property declaration, not part of the expression being
evaluated, so K2's narrower range is the more intuitive one. Adopt it for
both frontends. Example:
get / getValue / invoke ... 6:24:9:9 -> 6:27:9:9
Add a scoped offset remap on `FileTrapWriter`: while extracting a
`DELEGATED_PROPERTY_ACCESSOR` body, any location whose offsets exactly
equal the `by`-inclusive delegate range is emitted with the delegate
expression's range instead. The range is recovered from the enclosing
`KtProperty`'s PSI (`delegate.expression`), which is available under K1;
under K2 there is no PSI so the remap is inactive and the raw offsets
already exclude `by`. Matching the full delegate range exactly means only
these synthesised body expressions are affected.
Updates test-kotlin1 expected only (test-kotlin2 unchanged).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The K1 and K2 frontends record different source locations for the
compiler-synthesised primary constructor of a class that declares no primary
constructor in source. K2 uses the class declaration's raw IR offsets, which
include any leading modifier keywords, while K1's raw offsets start at the
`class` keyword and omit the modifiers.
Since K1 (unlike K2) retains the PSI, we recover the modifier-inclusive span
from the enclosing KtClassOrObject so K1 matches the K2-native span.
Example, for `open class C0<V> {}` on line 11 (the `open` modifier is at
column 1, the `class` keyword at column 6):
before (K1): generics.kt:11:6:11:19 | C0 | C0()
after (K1): generics.kt:11:1:11:19 | C0 | C0() (matches K2)
The fix is deliberately narrow and leaves all other constructors untouched:
- explicit primary constructors (`class C1(val t: T)`, `class C2()`) keep
their own parameter-list location, which both frontends already agree on;
- explicit secondary constructors keep their own location (only the
`isPrimary` constructor is adjusted);
- specialised/parameterised copies of a generic constructor
(`typeSubstitution != null`) are excluded, so they do not gain a spurious
source location and appear in source-filtered queries.
Relearned test-kotlin1 (K1) and test-kotlin2 (K2): all 3333 tests pass with
database-consistency checks. Only test-kotlin1 expected files change (K2 output
is unchanged, as K2 already emits these spans natively). No previously matching
row diverges; net K1-vs-K2 divergence decreases on every affected file, with
generics, generic-inner-classes and modifiers now fully identical.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>