Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter out global keywords of UMD module export declarations in completion providing auto import suggestions #42141

Merged
merged 6 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,7 @@ namespace ts.Completions {
host: LanguageServiceHost
): CompletionData | Request | undefined {
const typeChecker = program.getTypeChecker();
const compilerOptions = program.getCompilerOptions();

let start = timestamp();
let currentToken = getTokenAtPosition(sourceFile, position); // TODO: GH#15853
Expand Down Expand Up @@ -1519,7 +1520,22 @@ namespace ts.Completions {
return false;
}

symbol = skipAlias(symbol, typeChecker);
// External modules can have global export declarations that will be
// available as global keywords in all scopes. But if the external module
// already has an explicit export and user only wants to user explicit
aminpaks marked this conversation as resolved.
Show resolved Hide resolved
// module imports then the global keywords will be filtered out so auto
// import suggestions will win in the completion
const symbolOrigin = skipAlias(symbol, typeChecker);
// We only want to filter out the global keywords
// Auto Imports are not available for scripts so this conditional is always false
if (!!sourceFile.externalModuleIndicator
&& !compilerOptions.allowUmdGlobalAccess
&& symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
&& symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions) {
return false;
}
// Continue with origin symbol
symbol = symbolOrigin;

// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// <reference path="./fourslash.ts" />

// @filename: /package.json
//// { "dependencies": { "@types/classnames": "*" } }

// @filename: /tsconfig.json
//// { "compilerOptions": { "allowUmdGlobalAccess": true } }

// @filename: /node_modules/@types/classnames/package.json
//// { "name": "@types/classnames", "types": "index.d.ts" }

// @filename: /node_modules/@types/classnames/index.d.ts
//// declare const classNames: () => string;
//// export = classNames;
//// export as namespace classNames;

// @filename: /SomeReactComponent.tsx
//// import * as React from 'react';
////
//// const el1 = <div className={class/*1*/}>foo</div>;

goTo.marker("1");

verify.completions({
includes: [{
name: "classNames",
hasAction: undefined, // Asserts to have no actions
sortText: completion.SortText.GlobalsOrKeywords,
}],
preferences: {
includeCompletionsForModuleExports: true,
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// <reference path="./fourslash.ts" />

// @filename: /package.json
//// { "dependencies": { "@types/classnames": "*" } }

// @filename: /tsconfig.json
//// {}

// @filename: /node_modules/@types/classnames/package.json
//// { "name": "@types/classnames", "types": "index.d.ts" }

// @filename: /node_modules/@types/classnames/index.d.ts
//// declare const classNames: () => string;
//// export = classNames;
//// export as namespace classNames;

// @filename: /SomeReactComponent.tsx
//// import * as React from 'react';
////
//// const el1 = <div className={class/*1*/}>foo</div>;

goTo.marker("1");

verify.completions({
includes: [{
name: "classNames",
hasAction: true,
source: "/node_modules/@types/classnames/index",
sortText: completion.SortText.AutoImportSuggestions,
}],
preferences: {
includeCompletionsForModuleExports: true,
}
});
32 changes: 32 additions & 0 deletions tests/cases/fourslash/completionsImport_umdModules3_script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// <reference path="./fourslash.ts" />

// @filename: /package.json
//// { "dependencies": { "@types/classnames": "*" } }

// @filename: /tsconfig.json
//// { "compilerOptions": { "module": "es2015" }}

// @filename: /node_modules/@types/classnames/package.json
//// { "name": "@types/classnames", "types": "index.d.ts" }

// @filename: /node_modules/@types/classnames/index.d.ts
//// declare const classNames: () => string;
//// export = classNames;
//// export as namespace classNames;

// @filename: /SomeReactComponent.tsx
////
//// const el1 = <div className={class/*1*/}>foo</div>

goTo.marker("1");

verify.completions({
includes: [{
name: "classNames",
hasAction: undefined, // Asserts to have no actions
sortText: completion.SortText.GlobalsOrKeywords,
}],
preferences: {
includeCompletionsForModuleExports: true,
}
});