feat(compiler-cli): detect missing structural directive imports#59443
feat(compiler-cli): detect missing structural directive imports#59443manbearwiz wants to merge 7 commits intoangular:mainfrom
Conversation
devversion
left a comment
There was a problem hiding this comment.
LGTM, thanks for the PR.
The diagnostic is named control flow, but might be fine. Also adding @thePunderWoman as the original author IIRC
Yeah that was one of the things I was unsure about. Would it be better as a separate diagnostic? Would renaming this diagnostic be considered a breaking change? |
|
@manbearwiz Since this extended diagnostic is specifically about control flow, this seems out of scope to me. I think it would be better to have a separate optional template diagnostic for this since it doesn't apply to everyone. What do you think? |
|
That works for me. I'll update it to be a separate diagnostic. Any other suggestions while I'm in there? This will definitely touch a lot more files |
f0b2991 to
9cdc812
Compare
|
@manbearwiz It looks like you have legitimate test failures. Can you take a look? |
|
Should be good to go |
|
Running the diagnostic against google's codebase surfaced some interesting issues. I could narrow it down as following : If there is an unexported component, even if that component is unrelated, the diagnostic raises a false positive : I pushed a (currently) broken test as a fixup, feel free to try to fix it. |
We've been discussing this a bit and we do understand why this is happening, which isn't too easy to address. |
I pushed a commit before I read this. I didn't look that thoroughly, but it seems like it ends up doing a reference comparison on nodes from 2 different ASTs? I definitely don't know enough about the ng compiler to know the best solution. My commit just changes the reference check to a name comparison. That's enough to make all the tests pass, but I would defer to you whether there are additional fields to compare or if different nodes should be passed into that fn entirely. |
|
Yeah that would pass the test but is unreliable; two different classes with equal name would be incorrectly matched. For this particular use-case that might be an acceptable trade-off for simplicity, but in the general sense it is incorrect and I think we need a better check. The problem occurs because Angular's template type-checking approach operates in a separate TypeScript |
|
The type-check file may be adjusted in various places: angular/packages/compiler-cli/src/ngtsc/typecheck/src/context.ts Lines 659 to 664 in b8f2a50 angular/packages/compiler-cli/src/ngtsc/typecheck/src/context.ts Lines 701 to 706 in b8f2a50 as well as additional import statements at the top. My suggestion would be to search for declarations of the same name in both files, then cross-reference based on their index in this list. TCB-generated code shouldn't have conflicting names so the indices should be stable. We'd only need to do this if we know that the type-check declaration is within a source file that was updated in the type-checking angular/packages/compiler-cli/src/ngtsc/program_driver/src/api.ts Lines 25 to 33 in 9dbe6fc so the perf impact of this (realizing this approach is quite expensive) may not be too much of a concern? |
|
I think that makes sense. I want to see if I can make a test case that makes the simple name comparison fail. Since this is a bug that affects existing diagnostics, do we want to handle this in this feature PR or should it be a seperate bug fix PR that would go in first? |
|
Having it in this PR could help us check if this actually fixes any false-positive we detected in Google's monorepo. I think it would be fine as a separate commit. |
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
Adds a new diagnostic that ensures that a standalone component using custom structural directives in a template has the necessary imports for those directives. Fixes angular#37322
|
I found a final breakage within the Google codebase. A function that wraps a component and which has a structural directive will report the import error despite having the correct import. This pattern was found in 2 unit tests, so it's really a rare case. |
There was a problem hiding this comment.
This fixes the issue with Components declared inside functions, but I have a medium confidence that this is the right fix.
There was a problem hiding this comment.
Had to introduce this change as compilation broke for this file
angular/packages/core/test/acceptance/authoring/model_inputs_spec.ts
Lines 594 to 613 in 05a03d3
|
G3 has been cleaned up. We'll go through a re-review after the recent changes. |
...check/extended/test/checks/missing_structural_directive/missing_structural_directive_spec.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
...ages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts
Show resolved
Hide resolved
...ages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts
Outdated
Show resolved
Hide resolved
...ages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts
Outdated
Show resolved
Hide resolved
|
Passing TGP, the broken target got fixed in between. |
|
This PR was merged into the repository by commit c889382. The changes were merged into the following branches: main |
|
@manbearwiz Thanks for your effort into this PR! 💯 |
|
Of course! Glad it got in. Thanks @JeanMeche for taking it the rest of the way! |
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |


PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: #37322
Currently, the compiler will warn about missing directive imports if they are one of the "known" structural directives from the CommonModule or use regular binding syntax. This extends that to include custom, user-defined, structural directives. Currently, missing an import for these custom structural directives just fails silently which is a pain point when doing standalone migrations.
What is the new behavior?
The compiler will now warn on missing custom structural directives.
Does this PR introduce a breaking change?
I made minimal changes and left existing logic in order to ensure the changes are not breaking. I am definitely open to taking another approach, adding more test cases, etc.