Skip to content

Commit

Permalink
Fix auto imports in opening JSX tag (#44724)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch committed Jun 24, 2021
1 parent baff2f8 commit 2b421bf
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
17 changes: 8 additions & 9 deletions src/services/completions.ts
Expand Up @@ -1297,10 +1297,9 @@ namespace ts.Completions {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
const tagSymbols = typeChecker.getJsxIntrinsicTagNamesAt(location);
Debug.assertEachIsDefined(tagSymbols, "getJsxIntrinsicTagNames() should all be defined");
symbols = typeChecker.getJsxIntrinsicTagNamesAt(location);
Debug.assertEachIsDefined(symbols, "getJsxIntrinsicTagNames() should all be defined");
tryGetGlobalSymbols();
symbols = tagSymbols.concat(symbols);
completionKind = CompletionKind.Global;
keywordFilters = KeywordCompletionFilters.None;
}
Expand Down Expand Up @@ -1586,7 +1585,7 @@ namespace ts.Completions {
const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
if (!attrsType) return GlobalsSearch.Continue;
const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions);
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
symbols = concatenate(symbols, filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties));
setSortTextToOptionalMember();
completionKind = CompletionKind.MemberLike;
isNewIdentifierLocation = false;
Expand Down Expand Up @@ -1644,7 +1643,7 @@ namespace ts.Completions {

const symbolMeanings = (isTypeOnly ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias;

symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
symbols = concatenate(symbols, typeChecker.getSymbolsInScope(scopeNode, symbolMeanings));
Debug.assertEachIsDefined(symbols, "getSymbolsInScope() should all be defined");
for (const symbol of symbols) {
if (!typeChecker.isArgumentsSymbol(symbol) &&
Expand Down Expand Up @@ -1981,7 +1980,7 @@ namespace ts.Completions {
const existingMemberEscapedNames: Set<__String> = new Set();
existingMembers.forEach(s => existingMemberEscapedNames.add(s.escapedName));

symbols = filter(members, s => !existingMemberEscapedNames.has(s.escapedName));
symbols = concatenate(symbols, filter(members, s => !existingMemberEscapedNames.has(s.escapedName)));

completionKind = CompletionKind.ObjectPropertyDeclaration;
isNewIdentifierLocation = true;
Expand Down Expand Up @@ -2070,7 +2069,7 @@ namespace ts.Completions {

if (typeMembers && typeMembers.length > 0) {
// Add filtered items to the completion list
symbols = filterObjectMembersList(typeMembers, Debug.checkDefined(existingMembers));
symbols = concatenate(symbols, filterObjectMembersList(typeMembers, Debug.checkDefined(existingMembers)));
}
setSortTextToOptionalMember();

Expand Down Expand Up @@ -2106,7 +2105,7 @@ namespace ts.Completions {
isNewIdentifierLocation = false;
const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
const existing = new Set((namedImportsOrExports.elements as NodeArray<ImportOrExportSpecifier>).filter(n => !isCurrentlyEditingNode(n)).map(n => (n.propertyName || n.name).escapedText));
symbols = exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.has(e.escapedName));
symbols = concatenate(symbols, exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.has(e.escapedName)));
return GlobalsSearch.Success;
}

Expand Down Expand Up @@ -2185,7 +2184,7 @@ namespace ts.Completions {
type?.symbol && typeChecker.getPropertiesOfType(typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl)) :
type && typeChecker.getPropertiesOfType(type);
});
symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags);
symbols = concatenate(symbols, filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags));
}

return GlobalsSearch.Success;
Expand Down
35 changes: 35 additions & 0 deletions tests/cases/fourslash/completionsImportFromJSXTag.ts
@@ -0,0 +1,35 @@
/// <reference path="fourslash.ts" />

// @jsx: react

// @Filename: /types.d.ts
//// declare namespace JSX {
//// interface IntrinsicElements { a }
//// }

// @Filename: /Box.tsx
//// export function Box(props: any) { return null; }

// @Filename: /App.tsx
//// export function App() {
//// return (
//// <div className="App">
//// <Box/**/
//// </div>
//// )
//// }

verify.applyCodeActionFromCompletion("", {
name: "Box",
source: "/Box",
description: `Import 'Box' from module "./Box"`,
newFileContent: `import { Box } from "./Box";
export function App() {
return (
<div className="App">
<Box
</div>
)
}`
});

0 comments on commit 2b421bf

Please sign in to comment.