Skip to content

Commit d8aba1d

Browse files
devversionpkozlowski-opensource
authored andcommitted
refactor(migrations): automatically skip inputs outside of project (angular#57883)
Currently we support filtering files outside of the project, or source files via `shouldMigrateInput` option. This works well, but we can smartly skip inputs in batch migrations if we never saw a source declaration. This is an improvement in G3 where we cannot simply limit the migration to a given directory, because we may include build targets from various places. E.g. via reverse dependency tracking— so this fixes the issue naturally. Notably, an explicit filter would improve reference lookups because we wouldn't consider the input when determining potential references. That is because we would know beforehand that those inputs in the `.d.ts` cannot be migrated inputs— and therefore references with names of the input would never be verified via expensive type checking. This is fine for G3 though, and there is no way around this. This is a slow performance overhead; mostly releveant for VSCode integration. PR Close angular#57883
1 parent 4112e6f commit d8aba1d

File tree

6 files changed

+26
-8
lines changed

6 files changed

+26
-8
lines changed

packages/core/schematics/migrations/signal-migration/src/batch/extract.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export function getCompilationUnitMetadata(knownInputs: KnownInputs, result: Mig
3737
...res,
3838
[inputClassFieldIdStr as string & ClassFieldUniqueKey]: {
3939
isIncompatible: incompatibility,
40+
seenAsSourceInput: info.metadata.inSourceFile,
4041
},
4142
};
4243
},

packages/core/schematics/migrations/signal-migration/src/batch/merge_unit_data.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,28 @@ export function mergeCompilationUnitData(
3030
const existing = result.knownInputs[key];
3131
if (existing === undefined) {
3232
result.knownInputs[key] = info;
33-
} else if (existing.isIncompatible === null && info.isIncompatible) {
33+
continue;
34+
}
35+
36+
if (existing.isIncompatible === null && info.isIncompatible) {
3437
// input might not be incompatible in one target, but others might invalidate it.
3538
// merge the incompatibility state.
3639
existing.isIncompatible = info.isIncompatible;
3740
}
41+
if (!existing.seenAsSourceInput && info.seenAsSourceInput) {
42+
existing.seenAsSourceInput = true;
43+
}
3844
}
45+
}
3946

40-
for (const reference of file.references) {
41-
const referenceId = computeReferenceId(reference);
42-
if (seenReferenceFromIds.has(referenceId)) {
43-
continue;
44-
}
45-
seenReferenceFromIds.add(referenceId);
46-
result.references.push(reference);
47+
for (const info of Object.values(result.knownInputs)) {
48+
// We never saw a source file for this input, globally. Mark it as incompatible,
49+
// so that all references and inheritance checks can propagate accordingly.
50+
if (!info.seenAsSourceInput) {
51+
info.isIncompatible = {
52+
kind: IncompatibilityType.VIA_INPUT,
53+
reason: InputIncompatibilityReason.OutsideOfMigrationScope,
54+
};
4755
}
4856
}
4957

packages/core/schematics/migrations/signal-migration/src/batch/unit_data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export interface CompilationUnitData {
5151
| {kind: IncompatibilityType.VIA_CLASS; reason: ClassIncompatibilityReason}
5252
| {kind: IncompatibilityType.VIA_INPUT; reason: InputIncompatibilityReason}
5353
| null;
54+
seenAsSourceInput: boolean;
5455
};
5556
};
5657

packages/core/schematics/migrations/signal-migration/src/best_effort_mode.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {KnownInputs} from './input_detection/known_inputs';
1111

1212
/** Input reasons that cannot be ignored. */
1313
const nonIgnorableInputIncompatibilities: InputIncompatibilityReason[] = [
14+
// Outside of scope inputs should not be migrated. E.g. references to inputs in `node_modules/`.
15+
InputIncompatibilityReason.OutsideOfMigrationScope,
1416
// Explicitly filtered inputs cannot be skipped via best effort mode.
1517
InputIncompatibilityReason.SkippedViaConfigFilter,
1618
// There is no good output for accessor inputs.

packages/core/schematics/migrations/signal-migration/src/input_detection/incompatibility.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ts from 'typescript';
1010

1111
/** Reasons why an input cannot be migrated. */
1212
export enum InputIncompatibilityReason {
13+
OutsideOfMigrationScope,
1314
SkippedViaConfigFilter,
1415
Accessor,
1516
WriteAssignment,

packages/core/schematics/migrations/signal-migration/src/input_detection/incompatibility_human.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ export function getMessageForInputIncompatibility(reason: InputIncompatibilityRe
7474
short: 'Your application code writes to the input. This prevents migration.',
7575
extra: 'Signal inputs are readonly, so migrating would break your build.',
7676
};
77+
case InputIncompatibilityReason.OutsideOfMigrationScope:
78+
return {
79+
short: 'This input is not part of any source files in your project.',
80+
extra: 'The migration excludes inputs if no source file declaring the input was seen.',
81+
};
7782
}
7883
}
7984

0 commit comments

Comments
 (0)