K1 IrProperty.startOffset includes leading modifiers (private, abstract,
lateinit, annotations) in the span start; K2 already starts at val/var.
Walk the PSI tree from p.startOffset to the enclosing KtProperty, then use
valOrVarKeyword.startOffset as the declaration start, giving a consistent
start in both K1 and K2.
Two related but distinct locations are derived from the KtProperty:
- The property itself spans val/var through the end of the full
declaration (KtProperty.endOffset), including an explicit getter/setter
body on a following line. This is getPsiBasedLocation(IrProperty).
- Synthesised accessors (DEFAULT_PROPERTY_ACCESSOR origin) span val/var
through the end of the property name (KtProperty.nameIdentifier.endOffset)
via getPsiBasedAccessorLocation, applied through accessorOverride().
Explicit getter/setter bodies keep their own independently computed
location.
This makes K1 accessor locations match K2 and gives each synthesised
accessor a precise span, rather than the property's full declaration span.
Example (properties.kt line 3, "var modifiableInt = 1"):
property modifiableInt -> 3:5:3:25 (val/var .. end of "= 1")
accessor getModifiableInt -> 3:5:3:21 (val/var .. end of name)
accessor setModifiableInt -> 3:5:3:21
Because accessor locations appear wherever accessors are reported, this
refinement updates many expected files (property listings, modifiers,
methods, reflection, control-flow and expression dumps). Every change is a
location-coordinate change only: no result tuple is added or removed.
The PSI-based location is restricted to unspecialised extractions
(classTypeArgsIncludingOuterClasses.isNullOrEmpty()). Specialised generic
instances (e.g. C<String>.prop) continue to use the binary whole-file
location returned by getLocation(p, typeArgs), preserving the existing
behaviour that keeps them absent from fromSource() queries.
The visibility merge in extractFunction is extended to accept an
overriddenAttributes parameter from the caller; the internal fake-override
visibility adjustment (DescriptorVisibilities.PUBLIC for Java binary Object
methods) is merged with any caller-supplied attributes so that neither
overrides the other silently.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
In K1 mode, IrVariable.startOffset points to the name identifier and
IrVariable.endOffset is also at the name end, giving a location that
covers only the variable name (e.g. "local1") rather than the full
declaration ("val local1 = 2 + 3").
In K2 mode the IR offsets already point from the val/var keyword to the
end of the initializer, matching the intuitive source span.
Fix this for K1 by adding an IrVariable-specific overload of
getPsiBasedLocation that:
1. finds the leaf PSI element at v.startOffset (the name identifier)
2. walks up to the enclosing KtVariableDeclaration (KtProperty)
3. uses the val/var keyword position as the start offset to exclude
any leading annotations from the span
This matches the K2 IR behavior and gives a more complete location for
variable declarations when used in CodeQL queries.
The fix applies to both K1 and K2 since the overload is unconditional;
for K2 the walk-up gives the same result as before.
Expected updates in test-kotlin1:
- variables: local variable locations now span from val/var to initializer
- exprs, stmts, methods, modifiers, reflection: same local variable span
- controlflow/basic: CFG node references updated for new variable spans
(the "var ...;" node now starts at the val/var keyword)
Class member and top-level properties (IrProperty, not IrVariable) are
not affected by this change and retain their existing location behaviour.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
In K1 mode, the IrCall node for the !! operator stores startOffset at
the '!' character rather than at the start of the operand. This means
that x!! was previously reported as spanning from '!' to the end of the
expression, omitting the operand from the location.
Fix this by computing the NotNullExpr location from the value argument's
startOffset (the operand) to c.endOffset. This matches the K2 behaviour
where the IrCall.startOffset already points at the operand.
The fix guards against invalid (< 0) offsets on either side and falls
back to the default IrCall location in those cases.
Updated expected files in test-kotlin1:
- exprs/unaryOp.expected: !! locations now start at operand column
- exprs/exprs.expected: same (NotNullExpr entries corrected)
- exprs/binop.expected: !! child locations now correct (parent binop
location for s!!.plus(5) still differs due to a separate K1 IR
limitation where the enclosing call inherits the wrong receiver offset)
- controlflow/basic/bbStmts.expected: CFG references to !! now use the
improved location
- controlflow/basic/getASuccessor.expected: same
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
K1 and K2 IR backends compute source locations differently. K1 uses the IR
node's synthetic startOffset/endOffset, while K2 reconstructs source positions
from PSI. For expression-level nodes this causes location differences across
the two language modes.
Introduce PSI-backed location lookup as the preferred source for spans wherever
PSI is available:
getPsiBasedLocation(element) ?: tw.getLocation(element)
getPsiBasedLocation() resolves the PSI element for the IR node via
psi2Ir.findPsiElement() and builds a location from its startOffset..endOffset.
currentIrFile is tracked in extractFileContents so the PSI lookup has the
file context it needs.
Applied to expression-level nodes (both K1 and K2 modes):
- local variable declarations (extractVariable, extractVariableExpr)
- IrLocalDelegatedProperty blocks
- IrWhen expressions and when-branches
- IrGetValue (varaccess) expressions
- IrFunctionExpression (lambda) nodes
- Block statements (extractBlock)
- this/super access expressions (extractThisAccess)
- String literals
Declaration-level nodes (class, function, property) are guarded with
if (usesK2) to avoid a regression in K1 mode where the PSI lookup causes
parameterised type instantiations to appear as fromSource(), inflating
generic-type query results. The K1 IR frontend does not map all declaration
nodes cleanly to source PSI elements; for these nodes we keep the original
IR-based location in K1 mode.
Expected output changes (both suites):
- controlflow/basic/bbStmts, bbStrictDominance, bbSuccessor, getASuccessor,
strictDominance: when-branch and varaccess location improvements
- java-kotlin-collection-type-generic-methods/test: new stdlib entries from
JDK update (AbstractCollection<Runnable> methods)
- annotation_classes/PrintAst: variable access location improvement in K1
- classes/genericExprTypes: location improvement in K1
- compilation-units/cus: removed two internal JDK inner-class entries (stdlib
version change)
- reflection/reflection: removed a few external-class entries (stdlib version)
Verified: all 285 tests pass for both test-kotlin1 (kotlinc 2.3.20 / K1) and
test-kotlin2 (kotlinc 2.4.0 / K2).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
In K2 mode the frontend emits `-123L` as IrCall(unaryMinus, IrConst(123L))
rather than IrConst(-123L) as in K1. Queries that search for negative numeric
literals therefore need to match both a UnaryMinusExpr wrapping a literal and a
plain literal, depending on language mode.
Fix: when extractCallExpression encounters an isNumericFunction(unaryMinus) call
whose dispatchReceiver is already an IrConst, fold the negation into the constant
before extracting. The resulting literal node is identical to what K1 emits.
Location: extend the span one character to the left to cover the `-` sign.
In K2 the IrCall's startOffset equals the receiver's startOffset, so we recover
the minus by subtracting one from the receiver offset.
K1 is unaffected: the K1 frontend folds the sign into the constant before IR
generation, so this new branch never triggers when compiling with -language 1.9.
Expected output changes:
- test-kotlin2/library-tests/literals/literals.expected: negative long, float and
double literals now appear as plain typed literals instead of as UnaryMinus nodes.
The file is now byte-identical to test-kotlin1/library-tests/literals/literals.expected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update documentation to only claim support for 2.4.0x
* Python test code; remove newlines between imports.
* Sync comments between kotlin 1.8 and 1.9
* Update code comments to attach where actually relevant,
and improve comments on IrMemberAccessExpression<*>.extensionReceiverParameterIndex()
Add the Kotlin 2.4.0 compiler plugin variant (component registrar,
IR compatibility shims, and version-specific utilities), bundle the
2.4.0 compiler dependencies, and update the build wiring, supported
version metadata and the too-new diagnostic bound.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Accept test changes from Kotlin 2.3.0 update
Updates expected test outputs for kotlin2 library tests to match
actual compiler output. Changes include:
- Location adjustments for properties/methods (now point to identifiers)
- CastExpr -> ImplicitCastExpr for implicit type casts
- Removed duplicate BlockStmt entries in loop ASTs
- Super constructor call location changes
Note that in Kotlin 2.3.0 super constructor calls now have locations spanning
entire class declarations instead of the actual super call site.
This change rolls up all files from v1_6_0, v1_6_20, v1_7_0 and v_1_7_20.
In addition, versioned files that are not overridden by any later Kotlin versions (i.e. files that only have one copy under utils/versions) are inlined and removed to simplify list of changes.
List of removed/inlined files:
allOverriddenIncludingSelf.kt
copyTo.kt
ExperimentalCompilerApi.kt
getFileClassFqName.kt
IsUnderscoreParameter.kt
ReferenceEntity.kt
SyntheticBodyKind.kt
Types.kt
withHasQuestionMark.kt