Skip to content

Commit 30c6947

Browse files
Addressed CR feedback.
1 parent a6d17d8 commit 30c6947

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

src/compiler/parser.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4345,10 +4345,6 @@ namespace ts {
43454345
}
43464346
}
43474347

4348-
function nextTokenIsStringLiteralOnSameLine() {
4349-
return !scanner.hasPrecedingLineBreak() && token === SyntaxKind.StringLiteral;
4350-
}
4351-
43524348
function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
43534349
nextToken();
43544350
return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token === SyntaxKind.StringLiteral);
@@ -5141,9 +5137,9 @@ namespace ts {
51415137
node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
51425138

51435139
// It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios,
5144-
// the 'from' keyword be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`)
5140+
// the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`)
51455141
// If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect.
5146-
if (token === SyntaxKind.FromKeyword || lookAhead(nextTokenIsStringLiteralOnSameLine)) {
5142+
if (token === SyntaxKind.FromKeyword || (token === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) {
51475143
parseExpected(SyntaxKind.FromKeyword)
51485144
node.moduleSpecifier = parseModuleSpecifier();
51495145
}

src/services/services.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,11 +3255,6 @@ namespace ts {
32553255
* @returns true if 'symbols' was successfully populated; false otherwise.
32563256
*/
32573257
function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean {
3258-
// cursor is in import clause
3259-
// try to show exported member for imported module
3260-
isMemberCompletion = true;
3261-
isNewIdentifierLocation = false;
3262-
32633258
let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ?
32643259
SyntaxKind.ImportDeclaration :
32653260
SyntaxKind.ExportDeclaration;
@@ -3270,13 +3265,16 @@ namespace ts {
32703265
return false;
32713266
}
32723267

3268+
isMemberCompletion = true;
3269+
isNewIdentifierLocation = false;
3270+
32733271
let exports: Symbol[];
32743272
let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier);
32753273
if (moduleSpecifierSymbol) {
32763274
exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
32773275
}
32783276

3279-
symbols = exports ? filterModuleExports(exports, namedImportsOrExports) : emptyArray;
3277+
symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray;
32803278

32813279
return true;
32823280
}
@@ -3474,26 +3472,41 @@ namespace ts {
34743472
return false;
34753473
}
34763474

3477-
function filterModuleExports(exports: Symbol[], namedImportsOrExports: NamedImportsOrExports): Symbol[] {
3478-
let exisingImports: Map<boolean> = {};
3475+
/**
3476+
* Filters out completion suggestions for named imports or exports.
3477+
*
3478+
* @param exportsOfModule The list of symbols which a module exposes.
3479+
* @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause.
3480+
*
3481+
* @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports
3482+
* do not occur at the current position and have not otherwise been typed.
3483+
*/
3484+
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] {
3485+
let exisingImportsOrExports: Map<boolean> = {};
34793486

3480-
for (let element of namedImportsOrExports.elements) {
3487+
for (let element of namedImportsOrExports) {
34813488
// If this is the current item we are editing right now, do not filter it out
34823489
if (element.getStart() <= position && position <= element.getEnd()) {
34833490
continue;
34843491
}
34853492

34863493
let name = element.propertyName || element.name;
3487-
exisingImports[name.text] = true;
3494+
exisingImportsOrExports[name.text] = true;
34883495
}
34893496

3490-
if (isEmpty(exisingImports)) {
3491-
return exports;
3497+
if (isEmpty(exisingImportsOrExports)) {
3498+
return exportsOfModule;
34923499
}
34933500

3494-
return filter(exports, e => !lookUp(exisingImports, e.name));
3501+
return filter(exportsOfModule, e => !lookUp(exisingImportsOrExports, e.name));
34953502
}
34963503

3504+
/**
3505+
* Filters out completion suggestions for named imports or exports.
3506+
*
3507+
* @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
3508+
* do not occur at the current position and have not otherwise been typed.
3509+
*/
34973510
function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: Declaration[]): Symbol[] {
34983511
if (!existingMembers || existingMembers.length === 0) {
34993512
return contextualMemberSymbols;
@@ -3538,6 +3551,12 @@ namespace ts {
35383551
return filteredMembers;
35393552
}
35403553

3554+
/**
3555+
* Filters out completion suggestions from 'symbols' according to existing JSX attributes.
3556+
*
3557+
* @returns Symbols to be suggested in a JSX element, barring those whose attributes
3558+
* do not occur at the current position and have not otherwise been typed.
3559+
*/
35413560
function filterJsxAttributes(attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>, symbols: Symbol[]): Symbol[] {
35423561
let seenNames: Map<boolean> = {};
35433562
for (let attr of attributes) {

0 commit comments

Comments
 (0)