Skip to content

Commit 5f0b53c

Browse files
dylhunnpkozlowski-opensource
authored andcommitted
feat(language-service): Allow auto-imports to suggest multiple possible imports. (#47787)
This change allows the language service to suggest imports for *all* directives returned from the compiler, and for *all* import specifiers for each directive. The first change has immediate effect, since there could already be multiple directives with the same selector. The second change is future-proofing; the compiler currently only returns a single best specifier, but will return more in the future. PR Close #47787
1 parent d436a19 commit 5f0b53c

File tree

1 file changed

+36
-35
lines changed

1 file changed

+36
-35
lines changed

packages/language-service/src/codefixes/fix_missing_import.ts

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export const missingImportMeta: CodeActionMeta = {
3939
function getCodeActions(
4040
{templateInfo, start, compiler, formatOptions, preferences, errorCode, tsLs}:
4141
CodeActionContext) {
42+
let codeActions: ts.CodeFixAction[] = [];
43+
4244
const checker = compiler.getTemplateTypeChecker();
4345
const tsChecker = compiler.programDriver.getProgram().getTypeChecker();
4446

@@ -64,46 +66,45 @@ function getCodeActions(
6466
}
6567
const importOn = owningNgModule ?? templateInfo.component;
6668

67-
// Find all possible importable directives with a matching selector, and take one of them.
68-
// In the future, we could handle multiple matches as additional quick fixes.
69+
// Find all possible importable directives with a matching selector.
6970
const allPossibleDirectives = checker.getPotentialTemplateDirectives(templateInfo.component);
7071
const matchingDirectives =
7172
getDirectiveMatchesForElementTag(missingElement, allPossibleDirectives);
72-
if (matchingDirectives.size === 0) {
73-
return [];
74-
}
75-
const bestMatch: PotentialDirective = matchingDirectives.values().next().value;
76-
const bestMatchSymbol = bestMatch.tsSymbol.valueDeclaration;
77-
78-
// Get possible trait imports corresponding to the recommended directive. Only use the
79-
// compiler's best import; in the future, we could suggest multiple imports if they exist.
80-
const potentialImports = checker.getPotentialImportsFor(bestMatch, importOn);
81-
if (potentialImports.length === 0) {
82-
return [];
83-
}
84-
const potentialImport = potentialImports[0];
85-
86-
// Update the imports on the TypeScript file and Angular decorator.
87-
let [fileImportChanges, importName] = updateImportsForTypescriptFile(
88-
tsChecker, importOn.getSourceFile(), potentialImport, bestMatchSymbol.getSourceFile());
89-
let traitImportChanges = updateImportsForAngularTrait(checker, importOn, importName);
90-
91-
// All quick fixes should always update the trait import; however, the TypeScript import might
92-
// already be present.
93-
if (traitImportChanges.length === 0) {
94-
return [];
73+
const matches = matchingDirectives.values();
74+
75+
// Generate suggestions for each possible match.
76+
for (let currMatch of matches) {
77+
const currMatchSymbol = currMatch.tsSymbol.valueDeclaration;
78+
79+
// Get possible trait imports corresponding to the recommended directive.
80+
const potentialImports = checker.getPotentialImportsFor(currMatch, importOn);
81+
82+
// For each possible import specifier, create a suggestion.
83+
for (let potentialImport of potentialImports) {
84+
// Update the imports on the TypeScript file and Angular decorator.
85+
let [fileImportChanges, importName] = updateImportsForTypescriptFile(
86+
tsChecker, importOn.getSourceFile(), potentialImport, currMatchSymbol.getSourceFile());
87+
let traitImportChanges = updateImportsForAngularTrait(checker, importOn, importName);
88+
89+
// All quick fixes should always update the trait import; however, the TypeScript import might
90+
// already be present.
91+
if (traitImportChanges.length === 0) {
92+
continue;
93+
}
94+
95+
// Create a code action for this import.
96+
codeActions.push({
97+
fixName: FixIdForCodeFixesAll.FIX_MISSING_IMPORT,
98+
description: `Import ${importName} from '${potentialImport.moduleSpecifier}' on ${
99+
importOn.name!.text}`,
100+
changes: [{
101+
fileName: importOn.getSourceFile().fileName,
102+
textChanges: [...fileImportChanges, ...traitImportChanges],
103+
}]
104+
});
105+
}
95106
}
96107

97-
// Create the code action to insert the new imports.
98-
const codeActions: ts.CodeFixAction[] = [{
99-
fixName: FixIdForCodeFixesAll.FIX_MISSING_IMPORT,
100-
description:
101-
`Import ${importName} from '${potentialImport.moduleSpecifier}' on ${importOn.name!.text}`,
102-
changes: [{
103-
fileName: importOn.getSourceFile().fileName,
104-
textChanges: [...fileImportChanges, ...traitImportChanges],
105-
}],
106-
}];
107108
return codeActions;
108109
}
109110

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy