@soundscript/soundscript 0.1.15 → 0.1.17
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/decode.d.ts +2 -2
- package/decode.js.map +1 -1
- package/json.js +1 -1
- package/numerics.js +4 -4
- package/package.json +6 -6
- package/project-transform/src/checker/rules/flow.js +16 -3
- package/project-transform/src/checker/rules/flow.ts +20 -3
- package/project-transform/src/checker/rules/flow_invalidation.js +18 -21
- package/project-transform/src/checker/rules/flow_invalidation.ts +25 -20
- package/project-transform/src/checker/rules/relations.js +157 -3
- package/project-transform/src/checker/rules/relations.ts +207 -1
- package/project-transform/src/checker/rules/unsound_syntax.js +0 -3
- package/project-transform/src/checker/rules/unsound_syntax.ts +0 -4
- package/project-transform/src/cli.js +1 -1
- package/project-transform/src/cli.ts +1 -1
- package/project-transform/src/compiler/compile_project.js +75 -9
- package/project-transform/src/compiler/compile_project.ts +121 -7
- package/project-transform/src/compiler/ir.ts +19 -1
- package/project-transform/src/compiler/lower.js +10335 -1477
- package/project-transform/src/compiler/lower.ts +16826 -4074
- package/project-transform/src/compiler/toolchain.js +36 -4
- package/project-transform/src/compiler/toolchain.ts +36 -4
- package/project-transform/src/compiler/wasm_js_host_runtime.js +134 -0
- package/project-transform/src/compiler/wasm_js_host_runtime.ts +146 -0
- package/project-transform/src/compiler/wat_arrays.js +4 -1
- package/project-transform/src/compiler/wat_arrays.ts +5 -1
- package/project-transform/src/compiler/wat_emitter.js +1497 -311
- package/project-transform/src/compiler/wat_emitter.ts +2971 -1017
- package/project-transform/src/compiler/wat_tagged.js +5 -0
- package/project-transform/src/compiler/wat_tagged.ts +5 -0
- package/project-transform/src/compiler_generator_runner.js +2139 -19
- package/project-transform/src/compiler_generator_runner.ts +2143 -20
- package/project-transform/src/compiler_promise_runner.js +4615 -636
- package/project-transform/src/compiler_promise_runner.ts +4703 -659
- package/project-transform/src/compiler_test_helpers.js +0 -579
- package/project-transform/src/compiler_test_helpers.ts +0 -648
- package/project-transform/src/frontend/macro_expander.js +4 -6
- package/project-transform/src/frontend/macro_expander.ts +4 -6
- package/project-transform/src/frontend/macro_operand_semantics.js +124 -1
- package/project-transform/src/frontend/macro_operand_semantics.ts +230 -6
- package/project-transform/src/frontend/macro_resolver.js +2 -2
- package/project-transform/src/frontend/macro_resolver.ts +2 -1
- package/project-transform/src/frontend/project_macro_support.js +29 -5
- package/project-transform/src/frontend/project_macro_support.ts +46 -10
- package/project-transform/src/stdlib/decode.d.ts +2 -2
- package/project-transform/src/stdlib/decode.ts +2 -2
- package/soundscript/decode.sts +2 -2
|
@@ -99,6 +99,8 @@ interface TargetNewtypeIdentitySet {
|
|
|
99
99
|
mode: 'intersection' | 'single' | 'union';
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
type CanonicalResultClassFamily = 'option' | 'result';
|
|
103
|
+
|
|
102
104
|
type NominalIdentityLike = { symbol: ts.Symbol; typeArguments: readonly ts.Type[] };
|
|
103
105
|
type NominalIdentitySet<TIdentity extends NominalIdentityLike> = {
|
|
104
106
|
identities: readonly TIdentity[];
|
|
@@ -2513,7 +2515,8 @@ function isInstalledSoundStdlibSourceFile(sourceFile: ts.SourceFile): boolean {
|
|
|
2513
2515
|
return normalizedFileName.includes('/node_modules/@soundscript/soundscript/') &&
|
|
2514
2516
|
(
|
|
2515
2517
|
normalizedFileName.endsWith('.d.ts') ||
|
|
2516
|
-
normalizedFileName.endsWith('.sts')
|
|
2518
|
+
normalizedFileName.endsWith('.sts') ||
|
|
2519
|
+
normalizedFileName.endsWith('.sts.ts')
|
|
2517
2520
|
);
|
|
2518
2521
|
}
|
|
2519
2522
|
|
|
@@ -5609,10 +5612,24 @@ function classifyCurrentTypeNodeNominalClassRelation(
|
|
|
5609
5612
|
sourceExpression?: ts.Expression,
|
|
5610
5613
|
sourceTypeNode?: ts.TypeNode,
|
|
5611
5614
|
): RelationMismatch | undefined {
|
|
5615
|
+
if (
|
|
5616
|
+
sharesCanonicalResultClassFamily(context, sourceType, targetType) ||
|
|
5617
|
+
sharesGenericAliasRelationFamily(context, sourceType, targetType) ||
|
|
5618
|
+
sharesExactGenericClassIdentityFamilies(context, sourceType, targetType) ||
|
|
5619
|
+
sharesEquivalentTargetClassIdentitySets(context, sourceType, targetType)
|
|
5620
|
+
) {
|
|
5621
|
+
return undefined;
|
|
5622
|
+
}
|
|
5623
|
+
|
|
5612
5624
|
const targetIdentitySet = getDeclaredClassIdentitySetFromTypeNode(context, targetTypeNode);
|
|
5613
5625
|
if (!targetIdentitySet) {
|
|
5614
5626
|
return undefined;
|
|
5615
5627
|
}
|
|
5628
|
+
const sourceFamily = getCanonicalResultClassFamilyForType(context, sourceType);
|
|
5629
|
+
const targetFamily = getCanonicalResultClassFamilyForTargetIdentitySet(targetIdentitySet);
|
|
5630
|
+
if (sourceFamily !== undefined && sourceFamily === targetFamily) {
|
|
5631
|
+
return undefined;
|
|
5632
|
+
}
|
|
5616
5633
|
|
|
5617
5634
|
const sourceIdentitySet = getDeclaredClassIdentitySetFromTypeNode(context, sourceTypeNode) ??
|
|
5618
5635
|
getDeclaredClassIdentitySetFromExpression(context, sourceExpression);
|
|
@@ -6019,6 +6036,12 @@ function classifySourceTypeAgainstTargetClassIdentitySet(
|
|
|
6019
6036
|
targetType: ts.Type,
|
|
6020
6037
|
targetIdentitySet: TargetClassIdentitySet,
|
|
6021
6038
|
): RelationMismatch | undefined {
|
|
6039
|
+
const sourceFamily = getCanonicalResultClassFamilyForType(context, sourceType);
|
|
6040
|
+
const targetFamily = getCanonicalResultClassFamilyForTargetIdentitySet(targetIdentitySet);
|
|
6041
|
+
if (sourceFamily !== undefined && sourceFamily === targetFamily) {
|
|
6042
|
+
return undefined;
|
|
6043
|
+
}
|
|
6044
|
+
|
|
6022
6045
|
if (targetIdentitySet.mode === 'union') {
|
|
6023
6046
|
const normalizedSourceType = getSafeNonNullableRelationType(context, sourceType);
|
|
6024
6047
|
if ((normalizedSourceType.flags & ts.TypeFlags.Never) !== 0) {
|
|
@@ -6098,6 +6121,7 @@ function classifyUnsoundNominalClassRelation(
|
|
|
6098
6121
|
targetType: ts.Type,
|
|
6099
6122
|
): RelationMismatch | undefined {
|
|
6100
6123
|
if (
|
|
6124
|
+
sharesCanonicalResultClassFamily(context, sourceType, targetType) ||
|
|
6101
6125
|
sharesGenericAliasRelationFamily(context, sourceType, targetType) ||
|
|
6102
6126
|
sharesExactGenericClassIdentityFamilies(context, sourceType, targetType) ||
|
|
6103
6127
|
sharesEquivalentTargetClassIdentitySets(context, sourceType, targetType)
|
|
@@ -6194,6 +6218,7 @@ function classifyUnsoundGenericClassInstanceRelation(
|
|
|
6194
6218
|
targetType: ts.Type,
|
|
6195
6219
|
): RelationMismatch | undefined {
|
|
6196
6220
|
if (
|
|
6221
|
+
sharesCanonicalResultClassFamily(context, sourceType, targetType) ||
|
|
6197
6222
|
sharesGenericAliasRelationFamily(context, sourceType, targetType) ||
|
|
6198
6223
|
sharesExactGenericClassIdentityFamilies(context, sourceType, targetType) ||
|
|
6199
6224
|
sharesEquivalentTargetClassIdentitySets(context, sourceType, targetType)
|
|
@@ -6312,6 +6337,187 @@ function sharesEquivalentTargetClassIdentitySets(
|
|
|
6312
6337
|
);
|
|
6313
6338
|
}
|
|
6314
6339
|
|
|
6340
|
+
function isTrustedResultStdlibSourceFileName(fileName: string): boolean {
|
|
6341
|
+
return /(?:^|[\\/])(?:index|result)(?:\.sts)?(?:\.d)?\.ts$/.test(fileName);
|
|
6342
|
+
}
|
|
6343
|
+
|
|
6344
|
+
function getCanonicalResultClassFamilyForName(
|
|
6345
|
+
name: string,
|
|
6346
|
+
): CanonicalResultClassFamily | undefined {
|
|
6347
|
+
switch (name) {
|
|
6348
|
+
case 'Err':
|
|
6349
|
+
case 'Ok':
|
|
6350
|
+
case 'Result':
|
|
6351
|
+
return 'result';
|
|
6352
|
+
case 'None':
|
|
6353
|
+
case 'Option':
|
|
6354
|
+
case 'Some':
|
|
6355
|
+
return 'option';
|
|
6356
|
+
default:
|
|
6357
|
+
return undefined;
|
|
6358
|
+
}
|
|
6359
|
+
}
|
|
6360
|
+
|
|
6361
|
+
function getCanonicalResultClassFamilyForGenericRelationInfo(
|
|
6362
|
+
info: GenericRelationTypeInfo,
|
|
6363
|
+
): CanonicalResultClassFamily | undefined {
|
|
6364
|
+
const declarations = info.symbol.getDeclarations() ?? [];
|
|
6365
|
+
if (!declarations.some((declaration) =>
|
|
6366
|
+
isTrustedSoundLibSourceFile(declaration.getSourceFile()) &&
|
|
6367
|
+
isTrustedResultStdlibSourceFileName(declaration.getSourceFile().fileName)
|
|
6368
|
+
)) {
|
|
6369
|
+
return undefined;
|
|
6370
|
+
}
|
|
6371
|
+
|
|
6372
|
+
return getCanonicalResultClassFamilyForName(info.name);
|
|
6373
|
+
}
|
|
6374
|
+
|
|
6375
|
+
function getCanonicalResultClassFamilyForIdentity(
|
|
6376
|
+
identity: GenericClassIdentity,
|
|
6377
|
+
): CanonicalResultClassFamily | undefined {
|
|
6378
|
+
const declarations = identity.symbol.getDeclarations() ?? [];
|
|
6379
|
+
if (!declarations.some((declaration) =>
|
|
6380
|
+
isTrustedSoundLibSourceFile(declaration.getSourceFile()) &&
|
|
6381
|
+
isTrustedResultStdlibSourceFileName(declaration.getSourceFile().fileName)
|
|
6382
|
+
)) {
|
|
6383
|
+
return undefined;
|
|
6384
|
+
}
|
|
6385
|
+
|
|
6386
|
+
return getCanonicalResultClassFamilyForName(identity.symbol.getName());
|
|
6387
|
+
}
|
|
6388
|
+
|
|
6389
|
+
function getCanonicalResultClassFamilyForTargetIdentitySet(
|
|
6390
|
+
identitySet: TargetClassIdentitySet,
|
|
6391
|
+
): CanonicalResultClassFamily | undefined {
|
|
6392
|
+
let family: CanonicalResultClassFamily | undefined;
|
|
6393
|
+
for (const identity of identitySet.identities) {
|
|
6394
|
+
const identityFamily = getCanonicalResultClassFamilyForIdentity(identity);
|
|
6395
|
+
if (!identityFamily) {
|
|
6396
|
+
return undefined;
|
|
6397
|
+
}
|
|
6398
|
+
if (family && family !== identityFamily) {
|
|
6399
|
+
return undefined;
|
|
6400
|
+
}
|
|
6401
|
+
family = identityFamily;
|
|
6402
|
+
}
|
|
6403
|
+
|
|
6404
|
+
return family;
|
|
6405
|
+
}
|
|
6406
|
+
|
|
6407
|
+
function getCanonicalResultClassFamilyForType(
|
|
6408
|
+
context: AnalysisContext,
|
|
6409
|
+
type: ts.Type,
|
|
6410
|
+
visitedTypeIds: Set<number> = new Set(),
|
|
6411
|
+
): CanonicalResultClassFamily | undefined {
|
|
6412
|
+
const normalizedType = getSafeNonNullableRelationType(context, type);
|
|
6413
|
+
const rawTypeId = (normalizedType as ts.Type & { id?: number }).id;
|
|
6414
|
+
let visitedTypeId: number | undefined;
|
|
6415
|
+
if (typeof rawTypeId === 'number') {
|
|
6416
|
+
if (visitedTypeIds.has(rawTypeId)) {
|
|
6417
|
+
return undefined;
|
|
6418
|
+
}
|
|
6419
|
+
visitedTypeIds.add(rawTypeId);
|
|
6420
|
+
visitedTypeId = rawTypeId;
|
|
6421
|
+
}
|
|
6422
|
+
|
|
6423
|
+
try {
|
|
6424
|
+
if ((normalizedType.flags & ts.TypeFlags.Union) !== 0) {
|
|
6425
|
+
let family: CanonicalResultClassFamily | undefined;
|
|
6426
|
+
let sawConstituent = false;
|
|
6427
|
+
for (const constituentType of (normalizedType as ts.UnionType).types) {
|
|
6428
|
+
const normalizedConstituentType = getSafeNonNullableRelationType(context, constituentType);
|
|
6429
|
+
if ((normalizedConstituentType.flags & ts.TypeFlags.Never) !== 0) {
|
|
6430
|
+
continue;
|
|
6431
|
+
}
|
|
6432
|
+
const constituentFamily = getCanonicalResultClassFamilyForType(
|
|
6433
|
+
context,
|
|
6434
|
+
normalizedConstituentType,
|
|
6435
|
+
visitedTypeIds,
|
|
6436
|
+
);
|
|
6437
|
+
if (!constituentFamily) {
|
|
6438
|
+
return undefined;
|
|
6439
|
+
}
|
|
6440
|
+
if (family && family !== constituentFamily) {
|
|
6441
|
+
return undefined;
|
|
6442
|
+
}
|
|
6443
|
+
sawConstituent = true;
|
|
6444
|
+
family = constituentFamily;
|
|
6445
|
+
}
|
|
6446
|
+
|
|
6447
|
+
return sawConstituent ? family : undefined;
|
|
6448
|
+
}
|
|
6449
|
+
|
|
6450
|
+
if ((normalizedType.flags & ts.TypeFlags.Intersection) !== 0) {
|
|
6451
|
+
let family: CanonicalResultClassFamily | undefined;
|
|
6452
|
+
for (const constituentType of (normalizedType as ts.IntersectionType).types) {
|
|
6453
|
+
const constituentFamily = getCanonicalResultClassFamilyForType(
|
|
6454
|
+
context,
|
|
6455
|
+
constituentType,
|
|
6456
|
+
visitedTypeIds,
|
|
6457
|
+
);
|
|
6458
|
+
if (!constituentFamily) {
|
|
6459
|
+
continue;
|
|
6460
|
+
}
|
|
6461
|
+
if (family && family !== constituentFamily) {
|
|
6462
|
+
return undefined;
|
|
6463
|
+
}
|
|
6464
|
+
family = constituentFamily;
|
|
6465
|
+
}
|
|
6466
|
+
|
|
6467
|
+
return family;
|
|
6468
|
+
}
|
|
6469
|
+
|
|
6470
|
+
const relationInfo = getGenericRelationTypeInfo(context, normalizedType);
|
|
6471
|
+
const relationFamily = relationInfo
|
|
6472
|
+
? getCanonicalResultClassFamilyForGenericRelationInfo(relationInfo)
|
|
6473
|
+
: undefined;
|
|
6474
|
+
if (relationFamily) {
|
|
6475
|
+
return relationFamily;
|
|
6476
|
+
}
|
|
6477
|
+
|
|
6478
|
+
const directIdentity = getDirectClassIdentity(context, normalizedType);
|
|
6479
|
+
const directFamily = directIdentity
|
|
6480
|
+
? getCanonicalResultClassFamilyForIdentity(directIdentity)
|
|
6481
|
+
: undefined;
|
|
6482
|
+
if (directFamily) {
|
|
6483
|
+
return directFamily;
|
|
6484
|
+
}
|
|
6485
|
+
|
|
6486
|
+
const identities = collectGenericClassIdentities(context, normalizedType);
|
|
6487
|
+
if (identities.length === 0) {
|
|
6488
|
+
return undefined;
|
|
6489
|
+
}
|
|
6490
|
+
|
|
6491
|
+
let family: CanonicalResultClassFamily | undefined;
|
|
6492
|
+
for (const identity of identities) {
|
|
6493
|
+
const identityFamily = getCanonicalResultClassFamilyForIdentity(identity);
|
|
6494
|
+
if (!identityFamily) {
|
|
6495
|
+
return undefined;
|
|
6496
|
+
}
|
|
6497
|
+
if (family && family !== identityFamily) {
|
|
6498
|
+
return undefined;
|
|
6499
|
+
}
|
|
6500
|
+
family = identityFamily;
|
|
6501
|
+
}
|
|
6502
|
+
|
|
6503
|
+
return family;
|
|
6504
|
+
} finally {
|
|
6505
|
+
if (visitedTypeId !== undefined) {
|
|
6506
|
+
visitedTypeIds.delete(visitedTypeId);
|
|
6507
|
+
}
|
|
6508
|
+
}
|
|
6509
|
+
}
|
|
6510
|
+
|
|
6511
|
+
function sharesCanonicalResultClassFamily(
|
|
6512
|
+
context: AnalysisContext,
|
|
6513
|
+
sourceType: ts.Type,
|
|
6514
|
+
targetType: ts.Type,
|
|
6515
|
+
): boolean {
|
|
6516
|
+
const sourceFamily = getCanonicalResultClassFamilyForType(context, sourceType);
|
|
6517
|
+
return sourceFamily !== undefined &&
|
|
6518
|
+
sourceFamily === getCanonicalResultClassFamilyForType(context, targetType);
|
|
6519
|
+
}
|
|
6520
|
+
|
|
6315
6521
|
function getGenericParameterNames(
|
|
6316
6522
|
symbol: ts.Symbol,
|
|
6317
6523
|
arity: number,
|
|
@@ -1583,9 +1583,6 @@ function getUnsupportedFeatureDiagnostic(context, node) {
|
|
|
1583
1583
|
return unsupportedFeature(node.expression, 'prototypeMutation');
|
|
1584
1584
|
}
|
|
1585
1585
|
}
|
|
1586
|
-
if (ts.isForInStatement(node)) {
|
|
1587
|
-
return unsupportedFeature(node, 'forIn');
|
|
1588
|
-
}
|
|
1589
1586
|
if (ts.isLabeledStatement(node)) {
|
|
1590
1587
|
return unsupportedFeature(node.label, 'labeledStatement');
|
|
1591
1588
|
}
|
|
@@ -2381,10 +2381,6 @@ function getUnsupportedFeatureDiagnostic(
|
|
|
2381
2381
|
}
|
|
2382
2382
|
}
|
|
2383
2383
|
|
|
2384
|
-
if (ts.isForInStatement(node)) {
|
|
2385
|
-
return unsupportedFeature(node, 'forIn');
|
|
2386
|
-
}
|
|
2387
|
-
|
|
2388
2384
|
if (ts.isLabeledStatement(node)) {
|
|
2389
2385
|
return unsupportedFeature(node.label, 'labeledStatement');
|
|
2390
2386
|
}
|
|
@@ -11,7 +11,7 @@ import { createTempDirectory, fileExistsSync, makeDirectory, readStdinText, remo
|
|
|
11
11
|
import { materializeRuntimeGraph, } from './runtime/materialize.js';
|
|
12
12
|
import { runProgram } from './run_program.js';
|
|
13
13
|
import { projectEditorFile } from './editor_projection.js';
|
|
14
|
-
export const VERSION = '0.1.
|
|
14
|
+
export const VERSION = '0.1.17';
|
|
15
15
|
const FINDINGS_EXIT_CODE = 1;
|
|
16
16
|
const CLI_FAILURE_EXIT_CODE = 2;
|
|
17
17
|
function createCliDiagnostic(code, message, filePath, details) {
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
import { runProgram, type RunProgramOptions, type RunProgramResult } from './run_program.ts';
|
|
60
60
|
import { projectEditorFile } from './editor_projection.ts';
|
|
61
61
|
|
|
62
|
-
export const VERSION = '0.1.
|
|
62
|
+
export const VERSION = '0.1.17';
|
|
63
63
|
const FINDINGS_EXIT_CODE = 1;
|
|
64
64
|
const CLI_FAILURE_EXIT_CODE = 2;
|
|
65
65
|
|
|
@@ -2,14 +2,14 @@ import ts from 'typescript';
|
|
|
2
2
|
import { dirname, relative } from '../platform/path.js';
|
|
3
3
|
import { createAnnotationLookup } from '../annotation_syntax.js';
|
|
4
4
|
import { createSoundStdlibCompilerHost } from '../bundled/sound_stdlib.js';
|
|
5
|
-
import { formatDiagnostics, getNodeDiagnosticRange, hasErrorDiagnostics, toMergedDiagnostic, } from '../checker/diagnostics.js';
|
|
5
|
+
import { formatDiagnostics, getNodeDiagnosticRange, hasErrorDiagnostics, remapDiagnosticFilePaths, toMergedDiagnostic, } from '../checker/diagnostics.js';
|
|
6
6
|
import { COMPILER_DIAGNOSTIC_CODES, COMPILER_DIAGNOSTIC_MESSAGES, } from '../checker/engine/diagnostic_codes.js';
|
|
7
7
|
import { createAnalysisContext } from '../checker/engine/context.js';
|
|
8
8
|
import { runSoundAnalysis } from '../checker/rules/index.js';
|
|
9
9
|
import { runUniversalPolicyAnalysis } from '../checker/rules/universal.js';
|
|
10
10
|
import { collectSoundscriptRootNames, getConfigFileParsingDiagnostics, loadConfig, } from '../config.js';
|
|
11
11
|
import { createBuiltinExpandedProgram } from '../frontend/builtin_macro_support.js';
|
|
12
|
-
import { getLineAndCharacterOfPosition, mapProgramEnclosingRangeToSource, toSourceFileName, } from '../frontend/project_frontend.js';
|
|
12
|
+
import { getLineAndCharacterOfPosition, getPositionOfLineAndCharacter, mapProgramEnclosingRangeToSource, toSourceFileName, } from '../frontend/project_frontend.js';
|
|
13
13
|
import { CompilerUnsupportedError } from './errors.js';
|
|
14
14
|
import { lowerProgramToCompilerIR, validateHonestHeapBoundarySurfaces } from './lower.js';
|
|
15
15
|
import { CompilerToolchainError, packageCompilerOutput, } from './toolchain.js';
|
|
@@ -57,6 +57,72 @@ function createCompilerDiagnosticForNode(node, overrides) {
|
|
|
57
57
|
...getNodeDiagnosticRange(node),
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
function remapDiagnostics(diagnostics) {
|
|
61
|
+
return diagnostics.map((diagnostic) => remapDiagnosticFilePaths(diagnostic, toSourceFileName));
|
|
62
|
+
}
|
|
63
|
+
function hasRelatedInformation(diagnostic) {
|
|
64
|
+
return 'relatedInformation' in diagnostic;
|
|
65
|
+
}
|
|
66
|
+
function remapPreparedDiagnosticRange(diagnostic, preparedFile, diagnosticPreparedFiles) {
|
|
67
|
+
const remappedFilePath = diagnostic.filePath
|
|
68
|
+
? toSourceFileName(diagnostic.filePath)
|
|
69
|
+
: diagnostic.filePath;
|
|
70
|
+
if (!preparedFile ||
|
|
71
|
+
!diagnostic.filePath ||
|
|
72
|
+
diagnostic.line === undefined ||
|
|
73
|
+
diagnostic.column === undefined) {
|
|
74
|
+
const remappedDiagnostic = {
|
|
75
|
+
...diagnostic,
|
|
76
|
+
filePath: remappedFilePath,
|
|
77
|
+
};
|
|
78
|
+
if (hasRelatedInformation(diagnostic)) {
|
|
79
|
+
remappedDiagnostic.relatedInformation = diagnostic.relatedInformation?.map((relatedInformation) => remapPreparedDiagnosticRange(relatedInformation, relatedInformation.filePath
|
|
80
|
+
? diagnosticPreparedFiles.get(toSourceFileName(relatedInformation.filePath))
|
|
81
|
+
: undefined, diagnosticPreparedFiles));
|
|
82
|
+
}
|
|
83
|
+
return remappedDiagnostic;
|
|
84
|
+
}
|
|
85
|
+
const programStart = getPositionOfLineAndCharacter(preparedFile.rewrittenText, diagnostic.line - 1, diagnostic.column - 1);
|
|
86
|
+
const programEnd = diagnostic.endLine !== undefined && diagnostic.endColumn !== undefined
|
|
87
|
+
? getPositionOfLineAndCharacter(preparedFile.rewrittenText, diagnostic.endLine - 1, diagnostic.endColumn - 1)
|
|
88
|
+
: programStart;
|
|
89
|
+
const mappedRange = mapProgramEnclosingRangeToSource(preparedFile, programStart, programEnd);
|
|
90
|
+
const mappedStart = getLineAndCharacterOfPosition(preparedFile.originalText, mappedRange.start);
|
|
91
|
+
const mappedEnd = getLineAndCharacterOfPosition(preparedFile.originalText, mappedRange.end);
|
|
92
|
+
const remappedDiagnostic = {
|
|
93
|
+
...diagnostic,
|
|
94
|
+
filePath: remappedFilePath,
|
|
95
|
+
line: mappedStart.line + 1,
|
|
96
|
+
column: mappedStart.character + 1,
|
|
97
|
+
endLine: mappedEnd.line + 1,
|
|
98
|
+
endColumn: mappedEnd.character + 1,
|
|
99
|
+
};
|
|
100
|
+
if (hasRelatedInformation(diagnostic)) {
|
|
101
|
+
remappedDiagnostic.relatedInformation = diagnostic.relatedInformation?.map((relatedInformation) => {
|
|
102
|
+
const relatedPreparedFile = relatedInformation.filePath
|
|
103
|
+
? diagnosticPreparedFiles.get(toSourceFileName(relatedInformation.filePath))
|
|
104
|
+
: undefined;
|
|
105
|
+
return remapPreparedDiagnosticRange(relatedInformation, relatedPreparedFile, diagnosticPreparedFiles);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return remappedDiagnostic;
|
|
109
|
+
}
|
|
110
|
+
function remapSoundDiagnostics(diagnostics, diagnosticPreparedFiles) {
|
|
111
|
+
return diagnostics.map((diagnostic) => {
|
|
112
|
+
const preparedFile = diagnostic.filePath
|
|
113
|
+
? diagnosticPreparedFiles.get(toSourceFileName(diagnostic.filePath))
|
|
114
|
+
: undefined;
|
|
115
|
+
return remapPreparedDiagnosticRange(diagnostic, preparedFile, diagnosticPreparedFiles);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function remapCompilerDiagnostics(diagnostics, diagnosticPreparedFiles) {
|
|
119
|
+
return diagnostics.map((diagnostic) => {
|
|
120
|
+
const preparedFile = diagnostic.filePath
|
|
121
|
+
? diagnosticPreparedFiles.get(toSourceFileName(diagnostic.filePath))
|
|
122
|
+
: undefined;
|
|
123
|
+
return remapPreparedDiagnosticRange(diagnostic, preparedFile, diagnosticPreparedFiles);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
60
126
|
function createProgram(options) {
|
|
61
127
|
const loadedConfig = loadConfig(options.projectPath, { target: options.target });
|
|
62
128
|
const soundscriptRootNames = collectSoundscriptRootNames(options.projectPath, loadedConfig);
|
|
@@ -78,7 +144,7 @@ function createProgram(options) {
|
|
|
78
144
|
analysisPreparedProgram: expandedProgram.analysisPreparedProgram,
|
|
79
145
|
diagnosticPreparedFiles: expandedProgram.diagnosticPreparedFiles,
|
|
80
146
|
dispose: () => expandedProgram.dispose(),
|
|
81
|
-
frontendDiagnostics: expandedProgram.frontendDiagnostics(),
|
|
147
|
+
frontendDiagnostics: remapDiagnostics(expandedProgram.frontendDiagnostics()),
|
|
82
148
|
program: expandedProgram.program,
|
|
83
149
|
runtime: loadedConfig.runtime,
|
|
84
150
|
tsDiagnosticPrograms: expandedProgram.tsDiagnosticPrograms,
|
|
@@ -193,7 +259,7 @@ function collectDiagnostics(analysisPreparedProgram, diagnosticPreparedFiles, pr
|
|
|
193
259
|
workingDirectory,
|
|
194
260
|
includeSourceFile: (sourceFile) => !sourceFile.isDeclarationFile,
|
|
195
261
|
});
|
|
196
|
-
const universalDiagnostics = runUniversalPolicyAnalysis(analysisContext);
|
|
262
|
+
const universalDiagnostics = remapSoundDiagnostics(runUniversalPolicyAnalysis(analysisContext), diagnosticPreparedFiles);
|
|
197
263
|
if (hasErrorDiagnostics(tsDiagnostics)) {
|
|
198
264
|
return [...frontendDiagnostics, ...tsDiagnostics, ...universalDiagnostics];
|
|
199
265
|
}
|
|
@@ -201,7 +267,7 @@ function collectDiagnostics(analysisPreparedProgram, diagnosticPreparedFiles, pr
|
|
|
201
267
|
...frontendDiagnostics,
|
|
202
268
|
...tsDiagnostics,
|
|
203
269
|
...universalDiagnostics,
|
|
204
|
-
...runSoundAnalysis(analysisContext),
|
|
270
|
+
...remapSoundDiagnostics(runSoundAnalysis(analysisContext), diagnosticPreparedFiles),
|
|
205
271
|
];
|
|
206
272
|
}
|
|
207
273
|
function findUnsupportedValueClass(program) {
|
|
@@ -242,13 +308,13 @@ export function compileProject(options) {
|
|
|
242
308
|
}
|
|
243
309
|
const unsupportedValueClass = findUnsupportedValueClass(program);
|
|
244
310
|
if (unsupportedValueClass) {
|
|
245
|
-
const compilerDiagnostics = [
|
|
311
|
+
const compilerDiagnostics = remapCompilerDiagnostics([
|
|
246
312
|
createCompilerDiagnosticForNode(unsupportedValueClass, {
|
|
247
313
|
code: COMPILER_DIAGNOSTIC_CODES.valueClassesRequireJsEmit,
|
|
248
314
|
message: COMPILER_DIAGNOSTIC_MESSAGES.valueClassesRequireJsEmit,
|
|
249
315
|
hint: 'Use `soundscript build`, `soundscript node`, or another JS emit path for `#[value]`, or remove the annotation before compiling to Wasm.',
|
|
250
316
|
}),
|
|
251
|
-
];
|
|
317
|
+
], diagnosticPreparedFiles);
|
|
252
318
|
return {
|
|
253
319
|
diagnostics: compilerDiagnostics,
|
|
254
320
|
output: formatDiagnostics(compilerDiagnostics, options.workingDirectory),
|
|
@@ -286,11 +352,11 @@ export function compileProject(options) {
|
|
|
286
352
|
hint: error.diagnosticHint,
|
|
287
353
|
notes: error.diagnosticNotes,
|
|
288
354
|
};
|
|
289
|
-
const compilerDiagnostics = [
|
|
355
|
+
const compilerDiagnostics = remapCompilerDiagnostics([
|
|
290
356
|
error.node
|
|
291
357
|
? createCompilerDiagnosticForNode(error.node, diagnosticOverrides)
|
|
292
358
|
: createCompilerDiagnostic(options.projectPath, diagnosticOverrides),
|
|
293
|
-
];
|
|
359
|
+
], diagnosticPreparedFiles);
|
|
294
360
|
return {
|
|
295
361
|
diagnostics: compilerDiagnostics,
|
|
296
362
|
output: formatDiagnostics(compilerDiagnostics, options.workingDirectory),
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getNodeDiagnosticRange,
|
|
11
11
|
hasErrorDiagnostics,
|
|
12
12
|
type MergedDiagnostic,
|
|
13
|
+
remapDiagnosticFilePaths,
|
|
13
14
|
toMergedDiagnostic,
|
|
14
15
|
} from '../checker/diagnostics.ts';
|
|
15
16
|
import {
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
import { createBuiltinExpandedProgram } from '../frontend/builtin_macro_support.ts';
|
|
30
31
|
import {
|
|
31
32
|
getLineAndCharacterOfPosition,
|
|
33
|
+
getPositionOfLineAndCharacter,
|
|
32
34
|
mapProgramEnclosingRangeToSource,
|
|
33
35
|
type PreparedSourceFile,
|
|
34
36
|
toSourceFileName,
|
|
@@ -118,6 +120,115 @@ function createCompilerDiagnosticForNode(
|
|
|
118
120
|
};
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
function remapDiagnostics<T extends MergedDiagnostic>(diagnostics: readonly T[]): T[] {
|
|
124
|
+
return diagnostics.map((diagnostic) => remapDiagnosticFilePaths(diagnostic, toSourceFileName));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function hasRelatedInformation(
|
|
128
|
+
diagnostic: MergedDiagnostic | DiagnosticRelatedInformation,
|
|
129
|
+
): diagnostic is MergedDiagnostic {
|
|
130
|
+
return 'relatedInformation' in diagnostic;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function remapPreparedDiagnosticRange<T extends MergedDiagnostic | DiagnosticRelatedInformation>(
|
|
134
|
+
diagnostic: T,
|
|
135
|
+
preparedFile: PreparedSourceFile | undefined,
|
|
136
|
+
diagnosticPreparedFiles: ReadonlyMap<string, PreparedSourceFile>,
|
|
137
|
+
): T {
|
|
138
|
+
const remappedFilePath = diagnostic.filePath
|
|
139
|
+
? toSourceFileName(diagnostic.filePath)
|
|
140
|
+
: diagnostic.filePath;
|
|
141
|
+
|
|
142
|
+
if (
|
|
143
|
+
!preparedFile ||
|
|
144
|
+
!diagnostic.filePath ||
|
|
145
|
+
diagnostic.line === undefined ||
|
|
146
|
+
diagnostic.column === undefined
|
|
147
|
+
) {
|
|
148
|
+
const remappedDiagnostic = {
|
|
149
|
+
...diagnostic,
|
|
150
|
+
filePath: remappedFilePath,
|
|
151
|
+
} as T;
|
|
152
|
+
if (hasRelatedInformation(diagnostic)) {
|
|
153
|
+
(remappedDiagnostic as MergedDiagnostic).relatedInformation = diagnostic.relatedInformation?.map(
|
|
154
|
+
(relatedInformation) =>
|
|
155
|
+
remapPreparedDiagnosticRange(
|
|
156
|
+
relatedInformation,
|
|
157
|
+
relatedInformation.filePath
|
|
158
|
+
? diagnosticPreparedFiles.get(toSourceFileName(relatedInformation.filePath))
|
|
159
|
+
: undefined,
|
|
160
|
+
diagnosticPreparedFiles,
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return remappedDiagnostic;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const programStart = getPositionOfLineAndCharacter(
|
|
168
|
+
preparedFile.rewrittenText,
|
|
169
|
+
diagnostic.line - 1,
|
|
170
|
+
diagnostic.column - 1,
|
|
171
|
+
);
|
|
172
|
+
const programEnd = diagnostic.endLine !== undefined && diagnostic.endColumn !== undefined
|
|
173
|
+
? getPositionOfLineAndCharacter(
|
|
174
|
+
preparedFile.rewrittenText,
|
|
175
|
+
diagnostic.endLine - 1,
|
|
176
|
+
diagnostic.endColumn - 1,
|
|
177
|
+
)
|
|
178
|
+
: programStart;
|
|
179
|
+
const mappedRange = mapProgramEnclosingRangeToSource(preparedFile, programStart, programEnd);
|
|
180
|
+
const mappedStart = getLineAndCharacterOfPosition(preparedFile.originalText, mappedRange.start);
|
|
181
|
+
const mappedEnd = getLineAndCharacterOfPosition(preparedFile.originalText, mappedRange.end);
|
|
182
|
+
|
|
183
|
+
const remappedDiagnostic = {
|
|
184
|
+
...diagnostic,
|
|
185
|
+
filePath: remappedFilePath,
|
|
186
|
+
line: mappedStart.line + 1,
|
|
187
|
+
column: mappedStart.character + 1,
|
|
188
|
+
endLine: mappedEnd.line + 1,
|
|
189
|
+
endColumn: mappedEnd.character + 1,
|
|
190
|
+
} as T;
|
|
191
|
+
if (hasRelatedInformation(diagnostic)) {
|
|
192
|
+
(remappedDiagnostic as MergedDiagnostic).relatedInformation = diagnostic.relatedInformation?.map(
|
|
193
|
+
(relatedInformation) => {
|
|
194
|
+
const relatedPreparedFile = relatedInformation.filePath
|
|
195
|
+
? diagnosticPreparedFiles.get(toSourceFileName(relatedInformation.filePath))
|
|
196
|
+
: undefined;
|
|
197
|
+
return remapPreparedDiagnosticRange(
|
|
198
|
+
relatedInformation,
|
|
199
|
+
relatedPreparedFile,
|
|
200
|
+
diagnosticPreparedFiles,
|
|
201
|
+
);
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return remappedDiagnostic;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function remapSoundDiagnostics<T extends MergedDiagnostic>(
|
|
209
|
+
diagnostics: readonly T[],
|
|
210
|
+
diagnosticPreparedFiles: ReadonlyMap<string, PreparedSourceFile>,
|
|
211
|
+
): T[] {
|
|
212
|
+
return diagnostics.map((diagnostic) => {
|
|
213
|
+
const preparedFile = diagnostic.filePath
|
|
214
|
+
? diagnosticPreparedFiles.get(toSourceFileName(diagnostic.filePath))
|
|
215
|
+
: undefined;
|
|
216
|
+
return remapPreparedDiagnosticRange(diagnostic, preparedFile, diagnosticPreparedFiles);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function remapCompilerDiagnostics<T extends MergedDiagnostic>(
|
|
221
|
+
diagnostics: readonly T[],
|
|
222
|
+
diagnosticPreparedFiles: ReadonlyMap<string, PreparedSourceFile>,
|
|
223
|
+
): T[] {
|
|
224
|
+
return diagnostics.map((diagnostic) => {
|
|
225
|
+
const preparedFile = diagnostic.filePath
|
|
226
|
+
? diagnosticPreparedFiles.get(toSourceFileName(diagnostic.filePath))
|
|
227
|
+
: undefined;
|
|
228
|
+
return remapPreparedDiagnosticRange(diagnostic, preparedFile, diagnosticPreparedFiles);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
121
232
|
function createProgram(options: CompileProjectOptions): {
|
|
122
233
|
analysisPreparedProgram: {
|
|
123
234
|
toProgramFileName(fileName: string): string;
|
|
@@ -159,7 +270,7 @@ function createProgram(options: CompileProjectOptions): {
|
|
|
159
270
|
analysisPreparedProgram: expandedProgram.analysisPreparedProgram,
|
|
160
271
|
diagnosticPreparedFiles: expandedProgram.diagnosticPreparedFiles,
|
|
161
272
|
dispose: () => expandedProgram.dispose(),
|
|
162
|
-
frontendDiagnostics: expandedProgram.frontendDiagnostics(),
|
|
273
|
+
frontendDiagnostics: remapDiagnostics(expandedProgram.frontendDiagnostics()),
|
|
163
274
|
program: expandedProgram.program,
|
|
164
275
|
runtime: loadedConfig.runtime,
|
|
165
276
|
tsDiagnosticPrograms: expandedProgram.tsDiagnosticPrograms,
|
|
@@ -356,7 +467,10 @@ function collectDiagnostics(
|
|
|
356
467
|
workingDirectory,
|
|
357
468
|
includeSourceFile: (sourceFile) => !sourceFile.isDeclarationFile,
|
|
358
469
|
});
|
|
359
|
-
const universalDiagnostics =
|
|
470
|
+
const universalDiagnostics = remapSoundDiagnostics(
|
|
471
|
+
runUniversalPolicyAnalysis(analysisContext),
|
|
472
|
+
diagnosticPreparedFiles,
|
|
473
|
+
);
|
|
360
474
|
if (hasErrorDiagnostics(tsDiagnostics)) {
|
|
361
475
|
return [...frontendDiagnostics, ...tsDiagnostics, ...universalDiagnostics];
|
|
362
476
|
}
|
|
@@ -365,7 +479,7 @@ function collectDiagnostics(
|
|
|
365
479
|
...frontendDiagnostics,
|
|
366
480
|
...tsDiagnostics,
|
|
367
481
|
...universalDiagnostics,
|
|
368
|
-
...runSoundAnalysis(analysisContext),
|
|
482
|
+
...remapSoundDiagnostics(runSoundAnalysis(analysisContext), diagnosticPreparedFiles),
|
|
369
483
|
];
|
|
370
484
|
}
|
|
371
485
|
|
|
@@ -430,14 +544,14 @@ export function compileProject(options: CompileProjectOptions): CompileProjectRe
|
|
|
430
544
|
|
|
431
545
|
const unsupportedValueClass = findUnsupportedValueClass(program);
|
|
432
546
|
if (unsupportedValueClass) {
|
|
433
|
-
const compilerDiagnostics = [
|
|
547
|
+
const compilerDiagnostics = remapCompilerDiagnostics([
|
|
434
548
|
createCompilerDiagnosticForNode(unsupportedValueClass, {
|
|
435
549
|
code: COMPILER_DIAGNOSTIC_CODES.valueClassesRequireJsEmit,
|
|
436
550
|
message: COMPILER_DIAGNOSTIC_MESSAGES.valueClassesRequireJsEmit,
|
|
437
551
|
hint:
|
|
438
552
|
'Use `soundscript build`, `soundscript node`, or another JS emit path for `#[value]`, or remove the annotation before compiling to Wasm.',
|
|
439
553
|
}),
|
|
440
|
-
];
|
|
554
|
+
], diagnosticPreparedFiles);
|
|
441
555
|
return {
|
|
442
556
|
diagnostics: compilerDiagnostics,
|
|
443
557
|
output: formatDiagnostics(compilerDiagnostics, options.workingDirectory),
|
|
@@ -475,11 +589,11 @@ export function compileProject(options: CompileProjectOptions): CompileProjectRe
|
|
|
475
589
|
hint: error.diagnosticHint,
|
|
476
590
|
notes: error.diagnosticNotes,
|
|
477
591
|
};
|
|
478
|
-
const compilerDiagnostics = [
|
|
592
|
+
const compilerDiagnostics = remapCompilerDiagnostics([
|
|
479
593
|
error.node
|
|
480
594
|
? createCompilerDiagnosticForNode(error.node, diagnosticOverrides)
|
|
481
595
|
: createCompilerDiagnostic(options.projectPath, diagnosticOverrides),
|
|
482
|
-
];
|
|
596
|
+
], diagnosticPreparedFiles);
|
|
483
597
|
return {
|
|
484
598
|
diagnostics: compilerDiagnostics,
|
|
485
599
|
output: formatDiagnostics(compilerDiagnostics, options.workingDirectory),
|