@shapeshift-labs/frontier-lang-compiler 0.2.32 → 0.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -336,8 +336,10 @@ import {
336
336
  createCSharpRoslynNativeImporterAdapter,
337
337
  createGoAstNativeImporterAdapter,
338
338
  createJavaAstNativeImporterAdapter,
339
+ createKotlinPsiNativeImporterAdapter,
339
340
  createPythonAstNativeImporterAdapter,
340
341
  createRustSynNativeImporterAdapter,
342
+ createSwiftSyntaxNativeImporterAdapter,
341
343
  importNativeProject,
342
344
  runNativeImporterAdapter
343
345
  } from '@shapeshift-labs/frontier-lang-compiler';
@@ -366,6 +368,11 @@ const javaAstAdapter = createJavaAstNativeImporterAdapter({
366
368
  javaVersion: '21',
367
369
  sourceLevel: '21'
368
370
  });
371
+ const kotlinPsiAdapter = createKotlinPsiNativeImporterAdapter({
372
+ parserModule: hostKotlinPsiParser,
373
+ kotlinVersion: '2.1',
374
+ analysisApiEvidence: { hash: kotlinAnalysisApiIndexHash }
375
+ });
369
376
  const csharpRoslynAdapter = createCSharpRoslynNativeImporterAdapter({
370
377
  parserModule: hostRoslynParser,
371
378
  languageVersion: '12',
@@ -384,7 +391,7 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
384
391
 
385
392
  const project = await importNativeProject({
386
393
  projectRoot: 'src',
387
- adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter, javaAstAdapter, csharpRoslynAdapter, swiftSyntaxAdapter],
394
+ adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter, javaAstAdapter, kotlinPsiAdapter, csharpRoslynAdapter, swiftSyntaxAdapter],
388
395
  sources: [
389
396
  { language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
390
397
  { language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource },
@@ -392,6 +399,7 @@ const project = await importNativeProject({
392
399
  { language: 'c', adapter: clangAstAdapter.id, sourcePath: 'native/todo.c', sourceText: cSource },
393
400
  { language: 'go', adapter: goAstAdapter.id, sourcePath: 'cmd/todo/main.go', sourceText: goSource },
394
401
  { language: 'java', adapter: javaAstAdapter.id, sourcePath: 'src/main/java/Todo.java', sourceText: javaSource },
402
+ { language: 'kotlin', adapter: kotlinPsiAdapter.id, sourcePath: 'src/main/kotlin/Todo.kt', sourceText: kotlinSource },
395
403
  { language: 'csharp', adapter: csharpRoslynAdapter.id, sourcePath: 'src/Todo.cs', sourceText: csharpSource },
396
404
  { language: 'swift', adapter: swiftSyntaxAdapter.id, sourcePath: 'Sources/Todo.swift', sourceText: swiftSource }
397
405
  ]
@@ -417,6 +425,7 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
417
425
  - `createClangAstNativeImporterAdapter`
418
426
  - `createGoAstNativeImporterAdapter`
419
427
  - `createJavaAstNativeImporterAdapter`
428
+ - `createKotlinPsiNativeImporterAdapter`
420
429
  - `createCSharpRoslynNativeImporterAdapter`
421
430
  - `createSwiftSyntaxNativeImporterAdapter`
422
431
  - `createTreeSitterNativeImporterAdapter`
@@ -466,6 +475,7 @@ The published Frontier package family is generated from one shared package catal
466
475
  - [`@shapeshift-labs/frontier-lang-rust`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-rust): Rust projection adapter for Frontier Lang semantic documents, including structs, aliases, and action stubs.
467
476
  - [`@shapeshift-labs/frontier-lang-python`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-python): Python projection adapter for Frontier Lang semantic documents, including dataclasses, typed patch records, and action stubs.
468
477
  - [`@shapeshift-labs/frontier-lang-c`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-c): C header projection adapter for Frontier Lang semantic documents, including structs and action prototypes.
478
+ - [`@shapeshift-labs/frontier-lang-swift`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-swift): Swift source-language importer package for Frontier Lang semantic documents, including package-level metadata, SwiftSyntax adapter helpers, native import results, and semantic sidecar generation for SwiftSyntax/SwiftParser-shaped syntax trees.
469
479
  - [`@shapeshift-labs/frontier-lang-java`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-java): Java source-language importer package for Frontier Lang semantic documents, including package-level metadata, Java AST adapter helpers, native import results, and semantic sidecar generation for javac/JDT/JavaParser-shaped ASTs.
470
480
  - [`@shapeshift-labs/frontier-lang-go`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-go): Go source-language importer package for Frontier Lang semantic documents, including package-level metadata, Go AST adapter helpers, native import results, and semantic sidecar generation for go/ast File or Package trees.
471
481
  - [`@shapeshift-labs/frontier-lang-csharp`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-csharp): C# Roslyn source-language importer package for Frontier Lang semantic documents, including package-level metadata, Roslyn adapter helpers, native import results, and semantic sidecar generation for SyntaxTree/SyntaxNode-shaped ASTs.
@@ -557,6 +567,7 @@ Package source repositories:
557
567
  - [`siliconjungle/-shapeshift-labs-frontier-lang-python`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-python)
558
568
  - [`siliconjungle/-shapeshift-labs-frontier-lang-c`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-c)
559
569
  - [`siliconjungle/-shapeshift-labs-frontier-lang-compiler`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-compiler)
570
+ - [`siliconjungle/-shapeshift-labs-frontier-lang-swift`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-swift)
560
571
  - [`siliconjungle/-shapeshift-labs-frontier-lang-java`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-java)
561
572
  - [`siliconjungle/-shapeshift-labs-frontier-lang-go`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-go)
562
573
  - [`siliconjungle/-shapeshift-labs-frontier-lang-csharp`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-csharp)
package/bench/smoke.mjs CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  createEstreeNativeImporterAdapter,
8
8
  createGoAstNativeImporterAdapter,
9
9
  createJavaAstNativeImporterAdapter,
10
+ createKotlinPsiNativeImporterAdapter,
10
11
  createNativeImportCoverageMatrix,
11
12
  createNativeParserAstFormatMatrix,
12
13
  createProjectionTargetLossMatrix,
@@ -48,6 +49,7 @@ const compileDurationMs = performance.now() - start;
48
49
 
49
50
  const importStart = performance.now();
50
51
  const estreeAdapter = createEstreeNativeImporterAdapter();
52
+ const kotlinPsiAdapter = createKotlinPsiNativeImporterAdapter();
51
53
  let nativeSymbols = 0;
52
54
  const nativeImportResults = [];
53
55
  for (let index = 0; index < 150; index += 1) {
@@ -75,6 +77,37 @@ for (let index = 0; index < 150; index += 1) {
75
77
  nativeSymbols += imported.semanticIndex?.symbols?.length ?? 0;
76
78
  nativeImportResults.push(imported);
77
79
  }
80
+ for (let index = 0; index < 50; index += 1) {
81
+ const imported = await runNativeImporterAdapter(kotlinPsiAdapter, {
82
+ sourcePath: `src/bench-${index}.kt`,
83
+ sourceText: `package bench\nclass BenchKotlin${index}(val title: String) { fun render${index}() = title }\n`,
84
+ adapterOptions: {
85
+ ast: {
86
+ kind: 'KtFile',
87
+ packageDirective: { kind: 'KtPackageDirective', fqName: 'bench' },
88
+ declarations: [{
89
+ kind: 'KtClass',
90
+ name: `BenchKotlin${index}`,
91
+ declarations: [{
92
+ kind: 'KtPrimaryConstructor',
93
+ parameters: [{
94
+ kind: 'KtParameter',
95
+ name: 'title',
96
+ typeReference: { text: 'String' },
97
+ valOrVarKeyword: 'val'
98
+ }]
99
+ }, {
100
+ kind: 'KtNamedFunction',
101
+ name: `render${index}`,
102
+ bodyExpression: { kind: 'KtBlockExpression' }
103
+ }]
104
+ }]
105
+ }
106
+ }
107
+ });
108
+ nativeSymbols += imported.semanticIndex?.symbols?.length ?? 0;
109
+ nativeImportResults.push(imported);
110
+ }
78
111
  const importDurationMs = performance.now() - importStart;
79
112
 
80
113
  const matrixStart = performance.now();
@@ -84,7 +117,7 @@ const matrixDurationMs = performance.now() - matrixStart;
84
117
  const parserFormatMatrixStart = performance.now();
85
118
  const parserFormatMatrix = createNativeParserAstFormatMatrix({
86
119
  imports: nativeImportResults,
87
- adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter(), createGoAstNativeImporterAdapter(), createJavaAstNativeImporterAdapter(), createCSharpRoslynNativeImporterAdapter(), createSwiftSyntaxNativeImporterAdapter()]
120
+ adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter(), createGoAstNativeImporterAdapter(), createJavaAstNativeImporterAdapter(), kotlinPsiAdapter, createCSharpRoslynNativeImporterAdapter(), createSwiftSyntaxNativeImporterAdapter()]
88
121
  });
89
122
  const parserFormatMatrixDurationMs = performance.now() - parserFormatMatrixStart;
90
123
 
@@ -233,7 +266,7 @@ console.log(JSON.stringify({
233
266
  compiles: 250,
234
267
  bytes,
235
268
  compileDurationMs: Number(compileDurationMs.toFixed(2)),
236
- nativeImports: 150,
269
+ nativeImports: nativeImportResults.length,
237
270
  nativeSymbols,
238
271
  nativeImportDurationMs: Number(importDurationMs.toFixed(2)),
239
272
  coverageMatrixLanguages: coverageMatrix.summary.languages,
package/dist/index.d.ts CHANGED
@@ -1497,6 +1497,45 @@ export interface JavaAstNativeImporterAdapterOptions {
1497
1497
  readonly maxNodes?: number;
1498
1498
  }
1499
1499
 
1500
+ export interface KotlinPsiNativeImporterAdapterOptions {
1501
+ readonly id?: string;
1502
+ readonly language?: FrontierSourceLanguage;
1503
+ readonly parser?: string;
1504
+ readonly version?: string;
1505
+ readonly capabilities?: readonly string[];
1506
+ readonly coverage?: NativeImporterAdapterCoverageInput;
1507
+ readonly supportedExtensions?: readonly string[];
1508
+ readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
1509
+ readonly ast?: unknown;
1510
+ readonly nativeAst?: unknown;
1511
+ readonly ktFile?: unknown;
1512
+ readonly file?: unknown;
1513
+ readonly sourceFile?: unknown;
1514
+ readonly root?: unknown;
1515
+ readonly parse?: (sourceText: string, options: Record<string, unknown>) => unknown;
1516
+ readonly parserModule?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
1517
+ readonly kotlinPsi?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
1518
+ readonly kotlinCompiler?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
1519
+ readonly intellijPsi?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
1520
+ readonly parserOptions?: Record<string, unknown>;
1521
+ readonly kotlinVersion?: string;
1522
+ readonly languageVersion?: string;
1523
+ readonly apiVersion?: string;
1524
+ readonly script?: boolean;
1525
+ readonly generated?: boolean;
1526
+ readonly analysisApiEvidence?: unknown;
1527
+ readonly firEvidence?: unknown;
1528
+ readonly compilerPluginEvidence?: unknown;
1529
+ readonly kspEvidence?: unknown;
1530
+ readonly kaptEvidence?: unknown;
1531
+ readonly multiplatformEvidence?: unknown;
1532
+ readonly buildVariantEvidence?: unknown;
1533
+ readonly positionResolver?: (position: unknown) => unknown;
1534
+ readonly lineMap?: unknown;
1535
+ readonly includeAnnotations?: boolean;
1536
+ readonly maxNodes?: number;
1537
+ }
1538
+
1500
1539
  export interface CSharpRoslynNativeImporterAdapterOptions {
1501
1540
  readonly id?: string;
1502
1541
  readonly language?: FrontierSourceLanguage;
@@ -1938,6 +1977,7 @@ export declare function createRustSynNativeImporterAdapter(options?: RustSynNati
1938
1977
  export declare function createClangAstNativeImporterAdapter(options?: ClangAstNativeImporterAdapterOptions): NativeImporterAdapter;
1939
1978
  export declare function createGoAstNativeImporterAdapter(options?: GoAstNativeImporterAdapterOptions): NativeImporterAdapter;
1940
1979
  export declare function createJavaAstNativeImporterAdapter(options?: JavaAstNativeImporterAdapterOptions): NativeImporterAdapter;
1980
+ export declare function createKotlinPsiNativeImporterAdapter(options?: KotlinPsiNativeImporterAdapterOptions): NativeImporterAdapter;
1941
1981
  export declare function createCSharpRoslynNativeImporterAdapter(options?: CSharpRoslynNativeImporterAdapterOptions): NativeImporterAdapter;
1942
1982
  export declare function createSwiftSyntaxNativeImporterAdapter(options?: SwiftSyntaxNativeImporterAdapterOptions): NativeImporterAdapter;
1943
1983
  export declare function createTreeSitterNativeImporterAdapter(options?: TreeSitterNativeImporterAdapterOptions): NativeImporterAdapter;
package/dist/index.js CHANGED
@@ -439,6 +439,18 @@ export const NativeParserAstFormatProfiles = Object.freeze([
439
439
  supportsErrorRecovery: true,
440
440
  notes: ['Java compiler/parser ASTs expose package/import/type/member declarations and source ranges; classpath/module-path, bindings, annotation processors, generated sources, Lombok expansion, comments/trivia, and control-flow evidence remain host-owned.']
441
441
  }),
442
+ nativeParserAstFormatProfile('kotlin-psi', {
443
+ aliases: ['kotlin-compiler', 'kotlin-compiler-psi', 'intellij-psi', 'kt-psi', 'kotlin-ast'],
444
+ kind: 'compiler-ast',
445
+ languages: ['kotlin'],
446
+ parserAdapters: ['kotlin-compiler', 'kotlin-psi', 'intellij-psi'],
447
+ exactness: 'exact-parser-ast',
448
+ sourceRangeModel: 'text-range-line-column',
449
+ preservesTokens: true,
450
+ preservesTrivia: true,
451
+ supportsErrorRecovery: true,
452
+ notes: ['Kotlin PSI exposes source syntax and IntelliJ parser errors; Analysis API symbols, FIR/K2 types, expect/actual matching, compiler plugins, generated sources, scripts, and build variants remain host-owned evidence.']
453
+ }),
442
454
  nativeParserAstFormatProfile('roslyn-csharp', {
443
455
  aliases: ['roslyn', 'csharp-roslyn', 'c#-roslyn', 'microsoft-codeanalysis-csharp', 'csharp-syntax'],
444
456
  kind: 'compiler-ast',
@@ -2958,6 +2970,78 @@ export function createJavaAstNativeImporterAdapter(options = {}) {
2958
2970
  };
2959
2971
  }
2960
2972
 
2973
+ export function createKotlinPsiNativeImporterAdapter(options = {}) {
2974
+ return {
2975
+ id: options.id ?? 'frontier.kotlin-psi-native-importer',
2976
+ language: options.language ?? 'kotlin',
2977
+ parser: options.parser ?? 'kotlin-psi',
2978
+ version: options.version,
2979
+ capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
2980
+ coverage: nativeImporterAdapterCoverage({
2981
+ exactness: 'exact-parser-ast',
2982
+ exactAst: true,
2983
+ tokens: true,
2984
+ trivia: true,
2985
+ diagnostics: true,
2986
+ sourceRanges: true,
2987
+ generatedRanges: false,
2988
+ semanticCoverage: declarationSemanticCoverage(),
2989
+ notes: [
2990
+ 'Normalizes caller-owned Kotlin PSI/KtFile-shaped syntax trees into native AST nodes and declaration-level semantic index records.',
2991
+ 'Kotlin PSI imports do not resolve Analysis API symbols, FIR/K2 types, overloads, nullability flow, expect/actual matching, compiler-plugin generated declarations, KSP/KAPT output, scripts, build variants, or control flow by themselves; attach host evidence for those claims.'
2992
+ ]
2993
+ }, options.coverage),
2994
+ supportedExtensions: options.supportedExtensions ?? ['.kt', '.kts'],
2995
+ diagnostics: options.diagnostics,
2996
+ parse(input) {
2997
+ const parsed = input.options?.ast
2998
+ ?? input.options?.nativeAst
2999
+ ?? input.options?.ktFile
3000
+ ?? input.options?.file
3001
+ ?? input.options?.sourceFile
3002
+ ?? input.options?.root
3003
+ ?? options.ast
3004
+ ?? options.ktFile
3005
+ ?? options.file
3006
+ ?? options.sourceFile
3007
+ ?? options.root
3008
+ ?? parseKotlinPsiSource(input, options);
3009
+ const root = kotlinPsiRoot(parsed);
3010
+ if (!root) {
3011
+ return missingInjectedParserResult(input, {
3012
+ parser: options.parser ?? 'kotlin-psi',
3013
+ adapterId: options.id ?? 'frontier.kotlin-psi-native-importer',
3014
+ message: 'createKotlinPsiNativeImporterAdapter requires an injected Kotlin PSI KtFile-shaped object, parserModule.parse function, parse function, or adapterOptions.ast.'
3015
+ });
3016
+ }
3017
+ const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics ?? parsed?.parseDiagnostics, input, {
3018
+ parser: options.parser ?? 'kotlin-psi'
3019
+ });
3020
+ return createNativeImportFromKotlinPsi(root, input, {
3021
+ parser: options.parser ?? 'kotlin-psi',
3022
+ astFormat: 'kotlin-psi',
3023
+ maxNodes: options.maxNodes,
3024
+ diagnostics: parseDiagnostics,
3025
+ kotlinVersion: options.kotlinVersion ?? input.options?.kotlinVersion ?? parsed?.kotlinVersion,
3026
+ languageVersion: options.languageVersion ?? input.options?.languageVersion ?? parsed?.languageVersion,
3027
+ apiVersion: options.apiVersion ?? input.options?.apiVersion ?? parsed?.apiVersion,
3028
+ script: input.options?.script ?? options.script ?? parsed?.script ?? /\.kts$/i.test(input.sourcePath ?? ''),
3029
+ generated: input.options?.generated ?? options.generated ?? parsed?.generated ?? kotlinGeneratedSourcePath(input.sourcePath),
3030
+ analysisApiEvidence: input.options?.analysisApiEvidence ?? options.analysisApiEvidence ?? parsed?.analysisApiEvidence,
3031
+ firEvidence: input.options?.firEvidence ?? options.firEvidence ?? parsed?.firEvidence,
3032
+ compilerPluginEvidence: input.options?.compilerPluginEvidence ?? options.compilerPluginEvidence ?? parsed?.compilerPluginEvidence,
3033
+ kspEvidence: input.options?.kspEvidence ?? options.kspEvidence ?? parsed?.kspEvidence,
3034
+ kaptEvidence: input.options?.kaptEvidence ?? options.kaptEvidence ?? parsed?.kaptEvidence,
3035
+ multiplatformEvidence: input.options?.multiplatformEvidence ?? options.multiplatformEvidence ?? parsed?.multiplatformEvidence,
3036
+ buildVariantEvidence: input.options?.buildVariantEvidence ?? options.buildVariantEvidence ?? parsed?.buildVariantEvidence,
3037
+ positionResolver: input.options?.positionResolver ?? options.positionResolver,
3038
+ lineMap: input.options?.lineMap ?? options.lineMap ?? parsed?.lineMap,
3039
+ includeAnnotations: options.includeAnnotations ?? input.options?.includeAnnotations
3040
+ });
3041
+ }
3042
+ };
3043
+ }
3044
+
2961
3045
  export function createCSharpRoslynNativeImporterAdapter(options = {}) {
2962
3046
  return {
2963
3047
  id: options.id ?? 'frontier.csharp-roslyn-native-importer',
@@ -7529,6 +7613,7 @@ function parserAstFormatIdForParser(parser) {
7529
7613
  if (text.includes('clang') || text.includes('libclang')) return 'clang-ast-json';
7530
7614
  if (text === 'go' || text.includes('go-parser') || text.includes('go-ast') || text.includes('go/parser') || text.includes('go/ast')) return 'go-ast';
7531
7615
  if (text === 'java' || text.includes('javac') || text.includes('jdt') || text.includes('javaparser') || text.includes('java-parser') || text.includes('java-ast')) return 'java-ast';
7616
+ if (text === 'kotlin' || text === 'kt' || text.includes('kotlin-psi') || text.includes('kotlin-compiler') || text.includes('intellij-psi') || text.includes('kt-psi')) return 'kotlin-psi';
7532
7617
  if (text === 'csharp' || text === 'c#' || text === 'cs' || text.includes('roslyn') || text.includes('microsoft-codeanalysis-csharp') || text.includes('csharp-syntax')) return 'roslyn-csharp';
7533
7618
  if (text.includes('swift-syntax') || text.includes('swiftsyntax') || text.includes('swiftparser') || text.includes('swift-parser')) return 'swift-syntax';
7534
7619
  if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
@@ -8629,6 +8714,23 @@ function parseJavaAstSource(input, options) {
8629
8714
  return parse(input.sourceText, parserOptions);
8630
8715
  }
8631
8716
 
8717
+ function parseKotlinPsiSource(input, options) {
8718
+ const parse = options.parse ?? options.parserModule?.parse ?? options.kotlinPsi?.parse ?? options.kotlinCompiler?.parse ?? options.intellijPsi?.parse;
8719
+ if (typeof parse !== 'function') return undefined;
8720
+ const parserOptions = {
8721
+ sourcePath: input.sourcePath,
8722
+ filename: input.sourcePath,
8723
+ kotlinVersion: options.kotlinVersion ?? input.options?.kotlinVersion,
8724
+ languageVersion: options.languageVersion ?? input.options?.languageVersion,
8725
+ apiVersion: options.apiVersion ?? input.options?.apiVersion,
8726
+ script: options.script ?? input.options?.script ?? /\.kts$/i.test(input.sourcePath ?? ''),
8727
+ includeAnnotations: options.includeAnnotations ?? input.options?.includeAnnotations,
8728
+ ...(options.parserOptions ?? {}),
8729
+ ...(input.options?.parserOptions ?? {})
8730
+ };
8731
+ return parse(input.sourceText, parserOptions);
8732
+ }
8733
+
8632
8734
  function parseCSharpRoslynSource(input, options) {
8633
8735
  const parse = options.parse ?? options.parserModule?.parse ?? options.roslyn?.parse ?? options.csharpRoslyn?.parse;
8634
8736
  if (typeof parse !== 'function') return undefined;
@@ -8891,6 +8993,53 @@ function createNativeImportFromJavaAst(root, input, options) {
8891
8993
  };
8892
8994
  }
8893
8995
 
8996
+ function createNativeImportFromKotlinPsi(root, input, options) {
8997
+ const context = createAstNormalizationContext(input, options);
8998
+ visitKotlinPsiNode(root, context, 'root');
8999
+ if (context.truncated) {
9000
+ context.losses.push(truncatedAstLoss(input, context, options));
9001
+ }
9002
+ if (options.generated && !context.losses.some((loss) => loss.kind === 'generatedCode')) {
9003
+ context.losses.push(kotlinGeneratedCodeLoss(input, context.rootId, undefined, options));
9004
+ }
9005
+ if (options.script && !context.losses.some((loss) => loss.metadata?.script === true)) {
9006
+ context.losses.push(kotlinScriptLoss(input, context.rootId, undefined, options));
9007
+ }
9008
+ const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
9009
+ return {
9010
+ rootId: context.rootId,
9011
+ nodes: context.nodes,
9012
+ semanticIndex: semantic.semanticIndex,
9013
+ mappings: semantic.mappings,
9014
+ losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
9015
+ id: input.adapterId,
9016
+ version: input.adapterVersion
9017
+ }, input)) ?? []),
9018
+ evidence: semantic.evidence,
9019
+ diagnostics: options.diagnostics,
9020
+ metadata: {
9021
+ astFormat: options.astFormat,
9022
+ parser: options.parser,
9023
+ kotlinVersion: options.kotlinVersion,
9024
+ languageVersion: options.languageVersion,
9025
+ apiVersion: options.apiVersion,
9026
+ script: Boolean(options.script),
9027
+ generated: options.generated,
9028
+ analysisApiEvidence: kotlinEvidenceSummary(options.analysisApiEvidence),
9029
+ firEvidence: kotlinEvidenceSummary(options.firEvidence),
9030
+ compilerPluginEvidence: kotlinEvidenceSummary(options.compilerPluginEvidence),
9031
+ kspEvidence: kotlinEvidenceSummary(options.kspEvidence),
9032
+ kaptEvidence: kotlinEvidenceSummary(options.kaptEvidence),
9033
+ multiplatformEvidence: kotlinEvidenceSummary(options.multiplatformEvidence),
9034
+ buildVariantEvidence: kotlinEvidenceSummary(options.buildVariantEvidence),
9035
+ includeAnnotations: Boolean(options.includeAnnotations),
9036
+ normalizedNodeCount: Object.keys(context.nodes).length,
9037
+ declarationCount: context.declarations.length,
9038
+ truncated: context.truncated
9039
+ }
9040
+ };
9041
+ }
9042
+
8894
9043
  function createNativeImportFromCSharpRoslyn(root, input, options) {
8895
9044
  const context = createAstNormalizationContext(input, options);
8896
9045
  visitCSharpRoslynNode(root, context, 'root');
@@ -12348,6 +12497,658 @@ function javaBindingEvidenceSummary(value) {
12348
12497
  return Object.keys(summary).length ? summary : { present: true };
12349
12498
  }
12350
12499
 
12500
+ function kotlinPsiRoot(value) {
12501
+ if (!value || typeof value !== 'object') return undefined;
12502
+ if (isKotlinPsiNode(value)) return value;
12503
+ if (isKotlinPsiNode(value.ast)) return value.ast;
12504
+ if (isKotlinPsiNode(value.root)) return value.root;
12505
+ if (isKotlinPsiNode(value.rootNode)) return value.rootNode;
12506
+ if (isKotlinPsiNode(value.ktFile)) return value.ktFile;
12507
+ if (isKotlinPsiNode(value.file)) return value.file;
12508
+ if (isKotlinPsiNode(value.sourceFile)) return value.sourceFile;
12509
+ if (Array.isArray(value.declarations) || Array.isArray(value.imports) || value.packageDirective) {
12510
+ return { kind: 'KtFile', ...value };
12511
+ }
12512
+ return undefined;
12513
+ }
12514
+
12515
+ function isKotlinPsiNode(value) {
12516
+ return Boolean(value && typeof value === 'object' && typeof kotlinPsiKind(value) === 'string');
12517
+ }
12518
+
12519
+ function kotlinPsiKind(node) {
12520
+ if (!node || typeof node !== 'object') return undefined;
12521
+ const declared = node.kind ?? node.nodeType ?? node.elementType ?? node.psiKind ?? node._type ?? node.type;
12522
+ if (typeof declared === 'string') return normalizeKotlinPsiKind(declared);
12523
+ if (Array.isArray(node.declarations) || Array.isArray(node.imports) || node.packageDirective) return 'KtFile';
12524
+ if (node.fqName || node.packageFqName) return 'KtPackageDirective';
12525
+ if (node.importedFqName || node.importedReference) return 'KtImportDirective';
12526
+ if (node.classKind || node.primaryConstructor || node.superTypeListEntries) return 'KtClass';
12527
+ if (node.funKeyword || node.valueParameters || node.bodyExpression) return 'KtNamedFunction';
12528
+ if (node.valOrVarKeyword || node.delegateExpression || node.initializer) return 'KtProperty';
12529
+ return undefined;
12530
+ }
12531
+
12532
+ function normalizeKotlinPsiKind(kind) {
12533
+ const text = String(kind)
12534
+ .replace(/^org\.jetbrains\.kotlin\.psi\./, '')
12535
+ .replace(/^KtNodeTypes\./, '')
12536
+ .replace(/ElementType$/, '');
12537
+ const compact = text.replace(/[_\s.-]+/g, '').toLowerCase();
12538
+ const known = {
12539
+ kotlinfile: 'KtFile',
12540
+ ktfile: 'KtFile',
12541
+ file: 'KtFile',
12542
+ script: 'KtScript',
12543
+ ktscript: 'KtScript',
12544
+ packagedirective: 'KtPackageDirective',
12545
+ ktpackagedirective: 'KtPackageDirective',
12546
+ importdirective: 'KtImportDirective',
12547
+ ktimportdirective: 'KtImportDirective',
12548
+ class: 'KtClass',
12549
+ ktclass: 'KtClass',
12550
+ classorobject: 'KtClassOrObject',
12551
+ ktclassorobject: 'KtClassOrObject',
12552
+ objectdeclaration: 'KtObjectDeclaration',
12553
+ ktobjectdeclaration: 'KtObjectDeclaration',
12554
+ enumentry: 'KtEnumEntry',
12555
+ ktenumentry: 'KtEnumEntry',
12556
+ namedfunction: 'KtNamedFunction',
12557
+ ktnamedfunction: 'KtNamedFunction',
12558
+ function: 'KtNamedFunction',
12559
+ property: 'KtProperty',
12560
+ ktproperty: 'KtProperty',
12561
+ typealias: 'KtTypeAlias',
12562
+ kttypealias: 'KtTypeAlias',
12563
+ parameter: 'KtParameter',
12564
+ ktparameter: 'KtParameter',
12565
+ primaryconstructor: 'KtPrimaryConstructor',
12566
+ ktprimaryconstructor: 'KtPrimaryConstructor',
12567
+ secondaryconstructor: 'KtSecondaryConstructor',
12568
+ ktsecondaryconstructor: 'KtSecondaryConstructor',
12569
+ classinitializer: 'KtClassInitializer',
12570
+ ktclassinitializer: 'KtClassInitializer',
12571
+ annotationentry: 'KtAnnotationEntry',
12572
+ ktannotationentry: 'KtAnnotationEntry',
12573
+ contracteffect: 'KtContractEffect',
12574
+ ktcontracteffect: 'KtContractEffect',
12575
+ contractdescription: 'KtContractDescription',
12576
+ ktcontractdescription: 'KtContractDescription',
12577
+ error: 'PsiErrorElement',
12578
+ psierror: 'PsiErrorElement',
12579
+ psierrorelement: 'PsiErrorElement'
12580
+ };
12581
+ if (known[compact]) return known[compact];
12582
+ if (/^[A-Z0-9_]+$/.test(text)) return text.toLowerCase().split('_').map(upperFirst).join('');
12583
+ return text;
12584
+ }
12585
+
12586
+ function ignoredKotlinPsiField(key) {
12587
+ return key === '_type'
12588
+ || key === 'type'
12589
+ || key === 'kind'
12590
+ || key === 'nodeType'
12591
+ || key === 'elementType'
12592
+ || key === 'psiKind'
12593
+ || key === 'parent'
12594
+ || key === 'parentKind'
12595
+ || key === 'parentField'
12596
+ || key === 'textRange'
12597
+ || key === 'range'
12598
+ || key === 'span'
12599
+ || key === 'location'
12600
+ || key === 'name'
12601
+ || key === 'nameIdentifier'
12602
+ || key === 'identifier'
12603
+ || key === 'fqName'
12604
+ || key === 'packageFqName'
12605
+ || key === 'analysisSymbol'
12606
+ || key === 'symbol'
12607
+ || key === 'typeInfo'
12608
+ || key === 'bindingContext'
12609
+ || key === 'fir'
12610
+ || key === 'ir';
12611
+ }
12612
+
12613
+ function visitKotlinPsiNode(node, context, propertyPath) {
12614
+ if (!isKotlinPsiNode(node) || context.truncated) return undefined;
12615
+ if (context.objectIds.has(node)) return context.objectIds.get(node);
12616
+ if (context.counter >= context.maxNodes) {
12617
+ context.truncated = true;
12618
+ return undefined;
12619
+ }
12620
+ const kind = kotlinPsiKind(node);
12621
+ const span = spanFromKotlinPsiNode(node, context.input, context.options);
12622
+ const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
12623
+ context.objectIds.set(node, id);
12624
+ if (!context.rootId) context.rootId = id;
12625
+ const children = [];
12626
+ for (const [field, value] of kotlinPsiChildEntries(node, kind)) {
12627
+ if (Array.isArray(value)) {
12628
+ value.forEach((entry, index) => {
12629
+ const childId = visitKotlinPsiNode(entry, context, `${propertyPath}.${field}[${index}]`);
12630
+ if (childId) children.push(childId);
12631
+ });
12632
+ } else {
12633
+ const childId = visitKotlinPsiNode(value, context, `${propertyPath}.${field}`);
12634
+ if (childId) children.push(childId);
12635
+ }
12636
+ }
12637
+ const declarations = kotlinPsiDeclarations(node, kind, id, context.input);
12638
+ const declaration = declarations[0];
12639
+ const nativeNode = {
12640
+ id,
12641
+ kind,
12642
+ languageKind: `${context.input.language}.${kind}`,
12643
+ span,
12644
+ value: declaration?.name ?? kotlinPsiNodeValue(node),
12645
+ fields: primitiveKotlinPsiFields(node, kind),
12646
+ children,
12647
+ metadata: {
12648
+ astFormat: context.options.astFormat,
12649
+ propertyPath,
12650
+ positionKind: kotlinPsiPositionKind(node),
12651
+ parser: context.options.parser
12652
+ }
12653
+ };
12654
+ context.nodes[id] = nativeNode;
12655
+ for (const entry of declarations) {
12656
+ context.declarations.push({ ...entry, nativeNode });
12657
+ }
12658
+ if (kotlinPsiRecoveredKind(kind) || kotlinPsiProblemNode(node, kind)) {
12659
+ context.losses.push({
12660
+ id: `loss_${idFragment(id)}_kotlin_psi_recovered_node`,
12661
+ severity: 'error',
12662
+ phase: 'parse',
12663
+ sourceFormat: context.input.language,
12664
+ kind: 'unsupportedSyntax',
12665
+ message: 'Kotlin PSI reported an error or recovered syntax node; semantic import is partial until syntax errors are resolved.',
12666
+ span,
12667
+ nodeId: id,
12668
+ metadata: {
12669
+ parser: context.options.parser,
12670
+ astFormat: context.options.astFormat,
12671
+ nodeKind: kind
12672
+ }
12673
+ });
12674
+ }
12675
+ if (kotlinExpectActualNode(node, kind)) {
12676
+ context.losses.push(kotlinUnsupportedSemanticLoss(context.input, id, span, context.options, {
12677
+ nodeKind: kind,
12678
+ feature: 'expect-actual',
12679
+ message: 'Kotlin expect/actual syntax was imported; matching platform declarations requires multiplatform build evidence.'
12680
+ }));
12681
+ }
12682
+ if (kotlinCoroutineNode(node, kind)) {
12683
+ context.losses.push(kotlinUnsupportedSemanticLoss(context.input, id, span, context.options, {
12684
+ nodeKind: kind,
12685
+ feature: 'coroutine',
12686
+ message: 'Kotlin coroutine syntax was imported; suspend lowering, scheduling, and effect semantics require host compiler/runtime evidence.'
12687
+ }));
12688
+ }
12689
+ if (kotlinContractNode(kind)) {
12690
+ context.losses.push(kotlinUnsupportedSemanticLoss(context.input, id, span, context.options, {
12691
+ nodeKind: kind,
12692
+ feature: 'contract',
12693
+ message: 'Kotlin contract syntax was imported; data-flow effects require Analysis API or compiler evidence.'
12694
+ }));
12695
+ }
12696
+ if (kotlinCompilerPluginAnnotationNode(node, kind) && !context.options.compilerPluginEvidence) {
12697
+ context.losses.push({
12698
+ id: `loss_${idFragment(id)}_kotlin_compiler_plugin_semantics`,
12699
+ severity: 'warning',
12700
+ phase: 'parse',
12701
+ sourceFormat: context.input.language,
12702
+ kind: 'metaprogramming',
12703
+ message: 'Kotlin compiler-plugin-style annotation was imported; generated declarations and transformed semantics require compiler plugin evidence.',
12704
+ span,
12705
+ nodeId: id,
12706
+ metadata: {
12707
+ parser: context.options.parser,
12708
+ astFormat: context.options.astFormat,
12709
+ nodeKind: kind,
12710
+ annotations: kotlinPsiAnnotationNames(node)
12711
+ }
12712
+ });
12713
+ }
12714
+ if (kotlinGeneratedCodeMarker(node, kind)) {
12715
+ context.losses.push(kotlinGeneratedCodeLoss(context.input, id, span, context.options, { nodeKind: kind }));
12716
+ }
12717
+ return id;
12718
+ }
12719
+
12720
+ function primitiveKotlinPsiFields(node, kind) {
12721
+ const fields = { kind };
12722
+ const name = kotlinPsiDeclarationName(node, kind);
12723
+ if (name) fields.name = name;
12724
+ const importPath = kotlinPsiImportPath(node);
12725
+ if (importPath) fields.importPath = importPath;
12726
+ const packageName = kotlinPsiPackageName(node);
12727
+ if (packageName) fields.packageName = packageName;
12728
+ const type = kotlinPsiTypeName(node.typeReference ?? node.returnTypeRef ?? node.returnType ?? node.type);
12729
+ if (type) fields.type = type;
12730
+ const receiver = kotlinPsiTypeName(node.receiverTypeReference ?? node.receiverTypeRef);
12731
+ if (receiver) fields.receiverType = receiver;
12732
+ const modifiers = kotlinPsiModifiers(node);
12733
+ if (modifiers.length) fields.modifiers = modifiers.join(',');
12734
+ const annotations = kotlinPsiAnnotationNames(node);
12735
+ if (annotations.length) fields.annotations = annotations.join(',');
12736
+ if (node.generated === true || node.isGenerated === true) fields.generated = true;
12737
+ if (node.isScript === true || kind === 'KtScript') fields.script = true;
12738
+ if (Array.isArray(node.typeParameters ?? node.typeParameterList?.parameters)) fields.typeParameterCount = (node.typeParameters ?? node.typeParameterList?.parameters).length;
12739
+ if (Array.isArray(node.valueParameters ?? node.valueParameterList?.parameters ?? node.parameters)) fields.parameterCount = (node.valueParameters ?? node.valueParameterList?.parameters ?? node.parameters).length;
12740
+ if (Array.isArray(node.superTypeListEntries ?? node.superTypes)) fields.superTypeCount = (node.superTypeListEntries ?? node.superTypes).length;
12741
+ return fields;
12742
+ }
12743
+
12744
+ function spanFromKotlinPsiNode(node, input, options = {}) {
12745
+ const direct = spanFromKotlinLineFields(node, input);
12746
+ if (direct) return direct;
12747
+ const range = node.sourceRange ?? node.range ?? node.span ?? node.textRange;
12748
+ const fromRange = spanFromKotlinRange(range, input);
12749
+ if (fromRange) return fromRange;
12750
+ const start = kotlinPsiPosition(node.start ?? node.startOffset ?? range?.startOffset ?? range?.start, options);
12751
+ const end = kotlinPsiPosition(node.end ?? node.endOffset ?? range?.endOffset ?? range?.end, options);
12752
+ if (!start) return undefined;
12753
+ return {
12754
+ sourceId: input.sourceHash,
12755
+ path: start.path ?? end?.path ?? input.sourcePath,
12756
+ startLine: start.line,
12757
+ startColumn: start.column,
12758
+ endLine: end?.line,
12759
+ endColumn: end?.column
12760
+ };
12761
+ }
12762
+
12763
+ function spanFromKotlinLineFields(node, input) {
12764
+ const startLine = node.startLine ?? node.line ?? node.beginLine;
12765
+ if (typeof startLine !== 'number') return undefined;
12766
+ return {
12767
+ sourceId: input.sourceHash,
12768
+ path: node.path ?? node.filePath ?? node.file ?? input.sourcePath,
12769
+ startLine,
12770
+ startColumn: node.startColumn ?? node.column ?? node.beginColumn,
12771
+ endLine: node.endLine,
12772
+ endColumn: node.endColumn
12773
+ };
12774
+ }
12775
+
12776
+ function spanFromKotlinRange(range, input) {
12777
+ if (!range || typeof range !== 'object') return undefined;
12778
+ const start = range.start ?? range.startPosition ?? range.lowerBound ?? range.begin;
12779
+ const end = range.end ?? range.endPosition ?? range.upperBound;
12780
+ const line = start?.line ?? start?.Line;
12781
+ if (typeof line !== 'number') return undefined;
12782
+ const column = start.column ?? start.character ?? start.offset ?? start.Column;
12783
+ const endLine = end?.line ?? end?.Line;
12784
+ const endColumn = end?.column ?? end?.character ?? end?.offset ?? end?.Column;
12785
+ return {
12786
+ sourceId: input.sourceHash,
12787
+ path: range.path ?? range.filePath ?? range.file ?? input.sourcePath,
12788
+ startLine: line,
12789
+ startColumn: typeof column === 'number' ? column : undefined,
12790
+ endLine: typeof endLine === 'number' ? endLine : undefined,
12791
+ endColumn: typeof endColumn === 'number' ? endColumn : undefined
12792
+ };
12793
+ }
12794
+
12795
+ function kotlinPsiPosition(value, options = {}) {
12796
+ if (value === undefined || value === null) return undefined;
12797
+ if (typeof value === 'object') {
12798
+ const position = value.position ?? value.location ?? value;
12799
+ const line = position.line ?? position.Line;
12800
+ const column = position.column ?? position.character ?? position.Column;
12801
+ if (typeof line === 'number') {
12802
+ return {
12803
+ path: position.path ?? position.filePath ?? position.file,
12804
+ line,
12805
+ column: typeof column === 'number' ? column : undefined
12806
+ };
12807
+ }
12808
+ }
12809
+ const resolver = typeof options.positionResolver === 'function'
12810
+ ? options.positionResolver
12811
+ : typeof options.lineMap?.position === 'function'
12812
+ ? options.lineMap.position.bind(options.lineMap)
12813
+ : typeof options.lineMap?.getLineAndColumn === 'function'
12814
+ ? options.lineMap.getLineAndColumn.bind(options.lineMap)
12815
+ : undefined;
12816
+ if (resolver) {
12817
+ const resolved = resolver(value);
12818
+ if (resolved !== value) return kotlinPsiPosition(resolved, options);
12819
+ }
12820
+ return undefined;
12821
+ }
12822
+
12823
+ function kotlinPsiPositionKind(node) {
12824
+ if (node.textRange || node.range) return 'text-range';
12825
+ if (typeof node.startOffset === 'number') return 'offset';
12826
+ if (typeof node.startLine === 'number' || typeof node.line === 'number') return 'line-column-fields';
12827
+ return undefined;
12828
+ }
12829
+
12830
+ function kotlinPsiDeclarations(node, kind, nativeNodeId, input) {
12831
+ if (kind === 'KtPackageDirective') {
12832
+ const name = kotlinPsiPackageName(node);
12833
+ return name ? [declarationRecord(input, nativeNodeId, name, 'namespace', 'definition')] : [];
12834
+ }
12835
+ if (kind === 'KtImportDirective') {
12836
+ const name = kotlinPsiImportPath(node);
12837
+ return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'import')] : [];
12838
+ }
12839
+ if (kotlinPsiTypeDeclarationKind(kind)) {
12840
+ const name = kotlinPsiDeclarationName(node, kind);
12841
+ return name ? [declarationRecord(input, nativeNodeId, name, kotlinPsiTypeDeclarationSymbolKind(node, kind), 'definition')] : [];
12842
+ }
12843
+ if (kind === 'KtTypeAlias') {
12844
+ const name = kotlinPsiDeclarationName(node, kind);
12845
+ return name ? [declarationRecord(input, nativeNodeId, name, 'type', 'definition')] : [];
12846
+ }
12847
+ if (kind === 'KtNamedFunction') {
12848
+ const name = kotlinPsiDeclarationName(node, kind);
12849
+ return name ? [declarationRecord(input, nativeNodeId, name, node.parentKind && kotlinPsiTypeDeclarationKind(node.parentKind) ? 'method' : 'function', kotlinPsiHasBody(node) ? 'definition' : 'declaration')] : [];
12850
+ }
12851
+ if (kind === 'KtProperty') {
12852
+ return kotlinPsiVariableNames(node).map((name) => declarationRecord(input, nativeNodeId, name, 'property', 'definition'));
12853
+ }
12854
+ if (kind === 'KtParameter' && node.parentKind === 'KtPrimaryConstructor') {
12855
+ return kotlinPsiVariableNames(node).map((name) => declarationRecord(input, nativeNodeId, name, 'property', 'definition'));
12856
+ }
12857
+ if (kind === 'KtPrimaryConstructor' || kind === 'KtSecondaryConstructor') {
12858
+ return [declarationRecord(input, nativeNodeId, kotlinPsiDeclarationName(node, kind) ?? 'constructor', 'method', 'definition')];
12859
+ }
12860
+ if (kind === 'KtEnumEntry') {
12861
+ const name = kotlinPsiDeclarationName(node, kind);
12862
+ return name ? [declarationRecord(input, nativeNodeId, name, 'enumMember', 'definition')] : [];
12863
+ }
12864
+ return [];
12865
+ }
12866
+
12867
+ function kotlinPsiChildEntries(node, kind = kotlinPsiKind(node)) {
12868
+ const fieldNames = Object.keys(node).filter((key) => !ignoredKotlinPsiField(key));
12869
+ const entries = [];
12870
+ for (const field of fieldNames) {
12871
+ const value = node[field];
12872
+ if (Array.isArray(value)) {
12873
+ entries.push([field, value.map((entry) => kotlinPsiChildWithParent(entry, kind, field))]);
12874
+ continue;
12875
+ }
12876
+ if (value && typeof value === 'object') {
12877
+ entries.push([field, kotlinPsiChildWithParent(value, kind, field)]);
12878
+ }
12879
+ }
12880
+ return entries.filter(([, value]) => Array.isArray(value)
12881
+ ? value.some(isKotlinPsiNode)
12882
+ : isKotlinPsiNode(value));
12883
+ }
12884
+
12885
+ function kotlinPsiChildWithParent(entry, parentKind, parentField) {
12886
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return entry;
12887
+ if (!isKotlinPsiNode(entry)) return entry;
12888
+ return { parentKind, parentField, ...entry };
12889
+ }
12890
+
12891
+ function kotlinPsiNodeValue(node) {
12892
+ return kotlinPsiDeclarationName(node, kotlinPsiKind(node))
12893
+ ?? kotlinPsiImportPath(node)
12894
+ ?? kotlinPsiPackageName(node)
12895
+ ?? kotlinPsiTypeName(node.typeReference ?? node.returnTypeRef ?? node.type);
12896
+ }
12897
+
12898
+ function kotlinPsiDeclarationName(node, kind = kotlinPsiKind(node)) {
12899
+ if (!node || typeof node !== 'object') return undefined;
12900
+ if (kind === 'KtPrimaryConstructor' || kind === 'KtSecondaryConstructor') return 'constructor';
12901
+ if (kind === 'KtClassInitializer') return 'init';
12902
+ if (kind === 'KtObjectDeclaration' && node.isCompanion === true && !node.name && !node.nameIdentifier) return 'companion object';
12903
+ for (const key of ['nameIdentifier', 'identifier', 'name', 'simpleName', 'classId', 'fqName', 'id']) {
12904
+ const name = kotlinPsiName(node[key]);
12905
+ if (name) return name;
12906
+ }
12907
+ const variable = kotlinPsiVariableNames(node)[0];
12908
+ if (variable) return variable;
12909
+ return undefined;
12910
+ }
12911
+
12912
+ function kotlinPsiName(value) {
12913
+ if (!value) return undefined;
12914
+ if (typeof value === 'string') return value;
12915
+ if (typeof value.asString === 'string') return value.asString;
12916
+ if (typeof value.identifier === 'string') return value.identifier;
12917
+ if (typeof value.name === 'string') return value.name;
12918
+ if (typeof value.text === 'string') return value.text;
12919
+ if (typeof value.value === 'string') return value.value;
12920
+ if (typeof value.fqName === 'string') return value.fqName;
12921
+ if (value.shortName && value.shortName !== value) return kotlinPsiName(value.shortName);
12922
+ if (value.name && value.name !== value) return kotlinPsiName(value.name);
12923
+ if (value.identifier && value.identifier !== value) return kotlinPsiName(value.identifier);
12924
+ return undefined;
12925
+ }
12926
+
12927
+ function kotlinPsiImportPath(node) {
12928
+ if (!node || typeof node !== 'object') return undefined;
12929
+ const path = node.importedFqName ?? node.importedReference ?? node.importPath ?? node.path ?? node.name;
12930
+ if (typeof path === 'string') return path;
12931
+ if (path && typeof path === 'object') return kotlinPsiName(path.fqName ?? path.name ?? path);
12932
+ return undefined;
12933
+ }
12934
+
12935
+ function kotlinPsiPackageName(node) {
12936
+ if (!node || typeof node !== 'object') return undefined;
12937
+ const value = node.packageFqName ?? node.fqName ?? node.qualifiedName ?? node.packageName;
12938
+ if (typeof value === 'string') return value;
12939
+ if (value && typeof value === 'object') return kotlinPsiName(value);
12940
+ return undefined;
12941
+ }
12942
+
12943
+ function kotlinPsiVariableNames(node) {
12944
+ const variables = node.variables ?? node.entries ?? node.declarations;
12945
+ if (Array.isArray(variables)) return variables.map(kotlinPsiDeclarationName).filter(Boolean);
12946
+ const name = kotlinPsiName(node.nameIdentifier ?? node.identifier ?? node.name);
12947
+ return name ? [name] : [];
12948
+ }
12949
+
12950
+ function kotlinPsiTypeName(value) {
12951
+ if (!value) return undefined;
12952
+ if (typeof value === 'string') return value;
12953
+ if (typeof value.text === 'string') return value.text.trim();
12954
+ if (typeof value.name === 'string') return value.name;
12955
+ if (typeof value.fqName === 'string') return value.fqName;
12956
+ if (value.typeElement) return kotlinPsiTypeName(value.typeElement);
12957
+ if (value.typeReference) return kotlinPsiTypeName(value.typeReference);
12958
+ if (value.referencedName) return kotlinPsiName(value.referencedName);
12959
+ if (value.constructorReferenceExpression) return kotlinPsiTypeName(value.constructorReferenceExpression);
12960
+ if (Array.isArray(value.typeArguments) || Array.isArray(value.arguments)) {
12961
+ const base = kotlinPsiName(value.name ?? value.referencedName ?? value.constructorReferenceExpression);
12962
+ const args = (value.typeArguments ?? value.arguments).map((entry) => kotlinPsiTypeName(entry.typeReference ?? entry)).filter(Boolean);
12963
+ return base ? `${base}<${args.join(', ')}>` : undefined;
12964
+ }
12965
+ return kotlinPsiName(value);
12966
+ }
12967
+
12968
+ function kotlinPsiModifiers(node) {
12969
+ const raw = node.modifiers ?? node.modifierList?.modifiers ?? node.modifierList?.children;
12970
+ const names = [];
12971
+ if (Array.isArray(raw)) {
12972
+ for (const entry of raw) {
12973
+ const name = typeof entry === 'string' ? entry : kotlinPsiName(entry) ?? entry?.keyword ?? entry?.tokenType ?? entry?.text;
12974
+ if (name) names.push(String(name).toLowerCase());
12975
+ }
12976
+ } else if (typeof raw === 'string') {
12977
+ names.push(...raw.split(/\s+/).filter(Boolean).map((entry) => entry.toLowerCase()));
12978
+ } else if (raw && typeof raw === 'object') {
12979
+ for (const [key, enabled] of Object.entries(raw)) {
12980
+ if (enabled === true) names.push(key.toLowerCase());
12981
+ }
12982
+ }
12983
+ for (const key of ['suspend', 'expect', 'actual', 'inline', 'operator', 'infix', 'tailrec', 'external', 'override', 'data', 'sealed', 'value']) {
12984
+ if (node[key] === true || node[`is${upperFirst(key)}`] === true) names.push(key);
12985
+ }
12986
+ return uniqueStrings(names.map((entry) => entry.replace(/keyword$/i, '').replace(/_keyword$/i, '').replace(/[_\s-]+/g, '').toLowerCase()).filter(Boolean));
12987
+ }
12988
+
12989
+ function kotlinPsiAnnotationNames(node) {
12990
+ const entries = node.annotationEntries ?? node.annotations ?? node.modifierList?.annotationEntries;
12991
+ if (!entries) return [];
12992
+ if (Array.isArray(entries)) {
12993
+ return uniqueStrings(entries.map((entry) => typeof entry === 'string' ? entry : kotlinPsiName(entry.shortName ?? entry.calleeExpression ?? entry.typeReference ?? entry.name ?? entry)).filter(Boolean));
12994
+ }
12995
+ return [];
12996
+ }
12997
+
12998
+ function kotlinPsiTypeDeclarationKind(kind) {
12999
+ return kind === 'KtClass'
13000
+ || kind === 'KtClassOrObject'
13001
+ || kind === 'KtObjectDeclaration';
13002
+ }
13003
+
13004
+ function kotlinPsiTypeDeclarationSymbolKind(node, kind) {
13005
+ const classKind = String(node.classKind ?? node.kindKeyword ?? '').toLowerCase();
13006
+ if (kind === 'KtObjectDeclaration') return 'class';
13007
+ if (classKind.includes('interface')) return 'interface';
13008
+ if (classKind.includes('enum')) return 'enum';
13009
+ if (classKind.includes('annotation')) return 'type';
13010
+ return 'class';
13011
+ }
13012
+
13013
+ function kotlinPsiHasBody(node) {
13014
+ return Boolean(node.bodyExpression || node.bodyBlockExpression || node.body || Array.isArray(node.statements));
13015
+ }
13016
+
13017
+ function kotlinPsiRecoveredKind(kind) {
13018
+ return kind === 'PsiErrorElement'
13019
+ || kind === 'KtErrorElement'
13020
+ || /Error|Recovery|Incomplete|Missing|Skipped/.test(String(kind));
13021
+ }
13022
+
13023
+ function kotlinPsiProblemNode(node, kind) {
13024
+ return Boolean(
13025
+ node.hasError
13026
+ || node.containsDiagnostics
13027
+ || node.containsSkippedText
13028
+ || node.isMissing
13029
+ || kind === 'PsiErrorElement'
13030
+ || kind === 'KtErrorElement'
13031
+ );
13032
+ }
13033
+
13034
+ function kotlinExpectActualNode(node) {
13035
+ const modifiers = kotlinPsiModifiers(node);
13036
+ return modifiers.includes('expect') || modifiers.includes('actual');
13037
+ }
13038
+
13039
+ function kotlinCoroutineNode(node, kind) {
13040
+ const modifiers = kotlinPsiModifiers(node);
13041
+ return modifiers.includes('suspend')
13042
+ || /Coroutine|Suspend/i.test(String(kind))
13043
+ || node.isSuspend === true
13044
+ || node.suspend === true;
13045
+ }
13046
+
13047
+ function kotlinContractNode(kind) {
13048
+ return /Contract/i.test(String(kind));
13049
+ }
13050
+
13051
+ function kotlinCompilerPluginAnnotationNode(node) {
13052
+ const names = kotlinPsiAnnotationNames(node);
13053
+ return names.some((name) => /^(Composable|Serializable|Parcelize|Entity|Immutable|Stable|AutoService|AssistedInject|Hilt|Inject|Room|KSerializable)$/i.test(name.replace(/^.*\./, '')));
13054
+ }
13055
+
13056
+ function kotlinGeneratedCodeMarker(node) {
13057
+ if (node.generated || node.isGenerated) return true;
13058
+ const path = String(node.filePath ?? node.path ?? node.sourcePath ?? '');
13059
+ return kotlinGeneratedSourcePath(path);
13060
+ }
13061
+
13062
+ function kotlinGeneratedSourcePath(path) {
13063
+ return typeof path === 'string' && (/(\.g|\.generated)\.kts?$/i.test(path) || /[\/\\](build|generated|ksp|kapt)[\/\\]/i.test(path));
13064
+ }
13065
+
13066
+ function kotlinGeneratedCodeLoss(input, nodeId, span, options = {}, metadata = {}) {
13067
+ return {
13068
+ id: `loss_${idFragment(nodeId ?? input.sourcePath ?? 'kotlin')}_kotlin_generated_code`,
13069
+ severity: 'warning',
13070
+ phase: 'parse',
13071
+ sourceFormat: input.language,
13072
+ kind: 'generatedCode',
13073
+ message: 'Kotlin generated-source marker was imported; generated member provenance and source ownership require host evidence.',
13074
+ span,
13075
+ nodeId,
13076
+ metadata: {
13077
+ parser: options.parser,
13078
+ astFormat: options.astFormat,
13079
+ kspEvidence: kotlinEvidenceSummary(options.kspEvidence),
13080
+ kaptEvidence: kotlinEvidenceSummary(options.kaptEvidence),
13081
+ compilerPluginEvidence: kotlinEvidenceSummary(options.compilerPluginEvidence),
13082
+ ...metadata
13083
+ }
13084
+ };
13085
+ }
13086
+
13087
+ function kotlinScriptLoss(input, nodeId, span, options = {}) {
13088
+ return {
13089
+ id: `loss_${idFragment(nodeId ?? input.sourcePath ?? 'kotlin')}_kotlin_script_semantics`,
13090
+ severity: 'warning',
13091
+ phase: 'parse',
13092
+ sourceFormat: input.language,
13093
+ kind: 'unsupportedSemantic',
13094
+ message: 'Kotlin script source was imported; script templates, implicit receivers, dependencies, and host execution environment require build/runtime evidence.',
13095
+ span,
13096
+ nodeId,
13097
+ metadata: {
13098
+ parser: options.parser,
13099
+ astFormat: options.astFormat,
13100
+ feature: 'script',
13101
+ unsupportedSemanticKind: 'kotlin.scriptContext',
13102
+ script: true,
13103
+ buildVariantEvidence: kotlinEvidenceSummary(options.buildVariantEvidence)
13104
+ }
13105
+ };
13106
+ }
13107
+
13108
+ function kotlinUnsupportedSemanticLoss(input, nodeId, span, options = {}, metadata = {}) {
13109
+ return {
13110
+ id: `loss_${idFragment(nodeId ?? input.sourcePath ?? 'kotlin')}_kotlin_${idFragment(metadata.feature ?? 'semantic')}`,
13111
+ severity: 'warning',
13112
+ phase: 'parse',
13113
+ sourceFormat: input.language,
13114
+ kind: 'unsupportedSemantic',
13115
+ message: metadata.message ?? 'Kotlin semantic feature requires host compiler evidence.',
13116
+ span,
13117
+ nodeId,
13118
+ metadata: {
13119
+ parser: options.parser,
13120
+ astFormat: options.astFormat,
13121
+ unsupportedSemanticKind: metadata.unsupportedSemanticKind ?? `kotlin.${idFragment(metadata.feature ?? 'semantic')}`,
13122
+ analysisApiEvidence: kotlinEvidenceSummary(options.analysisApiEvidence),
13123
+ firEvidence: kotlinEvidenceSummary(options.firEvidence),
13124
+ multiplatformEvidence: kotlinEvidenceSummary(options.multiplatformEvidence),
13125
+ ...metadata
13126
+ }
13127
+ };
13128
+ }
13129
+
13130
+ function kotlinEvidenceSummary(value) {
13131
+ if (!value) return undefined;
13132
+ if (Array.isArray(value)) return { entryCount: value.length };
13133
+ if (typeof value === 'string') return { value };
13134
+ if (typeof value === 'object') {
13135
+ const summary = {};
13136
+ if (typeof value.hash === 'string') summary.hash = value.hash;
13137
+ if (typeof value.solver === 'string') summary.solver = value.solver;
13138
+ if (Array.isArray(value.entries)) summary.entryCount = value.entries.length;
13139
+ if (Array.isArray(value.symbols)) summary.symbolCount = value.symbols.length;
13140
+ if (Array.isArray(value.references)) summary.referenceCount = value.references.length;
13141
+ if (Array.isArray(value.types)) summary.typeCount = value.types.length;
13142
+ if (Array.isArray(value.diagnostics)) summary.diagnosticCount = value.diagnostics.length;
13143
+ if (Array.isArray(value.plugins)) summary.pluginCount = value.plugins.length;
13144
+ if (Array.isArray(value.generatedSources)) summary.generatedSourceCount = value.generatedSources.length;
13145
+ if (Array.isArray(value.platforms)) summary.platformCount = value.platforms.length;
13146
+ if (Array.isArray(value.variants)) summary.variantCount = value.variants.length;
13147
+ return Object.keys(summary).length ? summary : { present: true };
13148
+ }
13149
+ return { present: true };
13150
+ }
13151
+
12351
13152
  function csharpRoslynRoot(value) {
12352
13153
  if (!value || typeof value !== 'object') return undefined;
12353
13154
  if (isCSharpRoslynNode(value)) return value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.32",
3
+ "version": "0.2.33",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",