Skip to content

Commit 552d82b

Browse files
Merge branch 'master' into JSLS
Conflicts: src/services/services.ts
2 parents ff2609f + 4f0dc28 commit 552d82b

101 files changed

Lines changed: 1413 additions & 1036 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/compiler/checker.ts

Lines changed: 60 additions & 183 deletions
Large diffs are not rendered by default.

src/compiler/emitter.ts

Lines changed: 259 additions & 122 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ module ts {
10951095

10961096
// If 'predicate' is supplied, then only the first symbol in scope matching the predicate
10971097
// will be returned. Otherwise, all symbols in scope will be returned.
1098-
getSymbolsInScope(location: Node, meaning: SymbolFlags, predicate?: (symbol: Symbol) => boolean): Symbol[];
1098+
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
10991099
getSymbolAtLocation(node: Node): Symbol;
11001100
getShorthandAssignmentValueSymbol(location: Node): Symbol;
11011101
getTypeAtLocation(node: Node): Type;
@@ -1206,8 +1206,8 @@ module ts {
12061206
}
12071207

12081208
export interface EmitResolver {
1209-
getGeneratedNameForNode(node: Node): string;
1210-
getExpressionNameSubstitution(node: Identifier): string;
1209+
hasGlobalName(name: string): boolean;
1210+
getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
12111211
hasExportDefaultValue(node: SourceFile): boolean;
12121212
isReferencedAliasDeclaration(node: Node): boolean;
12131213
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
@@ -1222,7 +1222,7 @@ module ts {
12221222
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
12231223
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
12241224
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
1225-
isUnknownIdentifier(location: Node, name: string): boolean;
1225+
resolvesToSomeValue(location: Node, name: string): boolean;
12261226
getBlockScopedVariableId(node: Identifier): number;
12271227
}
12281228

src/compiler/utilities.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,28 +1212,6 @@ module ts {
12121212
return node;
12131213
}
12141214

1215-
export function generateUniqueName(baseName: string, isExistingName: (name: string) => boolean): string {
1216-
// First try '_name'
1217-
if (baseName.charCodeAt(0) !== CharacterCodes._) {
1218-
baseName = "_" + baseName;
1219-
if (!isExistingName(baseName)) {
1220-
return baseName;
1221-
}
1222-
}
1223-
// Find the first unique '_name_n', where n is a positive number
1224-
if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
1225-
baseName += "_";
1226-
}
1227-
let i = 1;
1228-
while (true) {
1229-
let name = baseName + i;
1230-
if (!isExistingName(name)) {
1231-
return name;
1232-
}
1233-
i++;
1234-
}
1235-
}
1236-
12371215
// @internal
12381216
export function createDiagnosticCollection(): DiagnosticCollection {
12391217
let nonFileDiagnostics: Diagnostic[] = [];

src/services/services.ts

Lines changed: 44 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,61 +2565,59 @@ module ts {
25652565
}
25662566

25672567
/// Completion
2568-
function getValidCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget): string {
2568+
function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean): string {
25692569
let displayName = symbol.getName();
2570-
if (displayName && displayName.length > 0) {
2570+
if (displayName) {
25712571
let firstCharCode = displayName.charCodeAt(0);
25722572
// First check of the displayName is not external module; if it is an external module, it is not valid entry
25732573
if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
25742574
// If the symbol is external module, don't show it in the completion list
25752575
// (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
25762576
return undefined;
25772577
}
2578-
2579-
if (displayName && displayName.length >= 2 &&
2580-
firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
2581-
(firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
2582-
// If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
2583-
// invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
2584-
displayName = displayName.substring(1, displayName.length - 1);
2585-
}
2586-
2587-
let isValid = isIdentifierStart(displayName.charCodeAt(0), target);
2588-
for (let i = 1, n = displayName.length; isValid && i < n; i++) {
2589-
isValid = isIdentifierPart(displayName.charCodeAt(i), target);
2590-
}
2591-
2592-
if (isValid) {
2593-
return unescapeIdentifier(displayName);
2594-
}
25952578
}
25962579

2597-
return undefined;
2580+
return getCompletionEntryDisplayName(displayName, target, performCharacterChecks);
25982581
}
25992582

2600-
function getValidCompletionEntryDisplayName(displayName: string, target: ScriptTarget): string {
2583+
function getCompletionEntryDisplayName(displayName: string, target: ScriptTarget, performCharacterChecks: boolean): string {
2584+
if (!displayName) {
2585+
return undefined;
2586+
}
2587+
26012588
let firstCharCode = displayName.charCodeAt(0);
2602-
if (displayName && displayName.length >= 2 &&
2589+
if (displayName.length >= 2 &&
26032590
firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
26042591
(firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
26052592
// If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
26062593
// invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
26072594
displayName = displayName.substring(1, displayName.length - 1);
26082595
}
26092596

2610-
let isValid = isIdentifierStart(displayName.charCodeAt(0), target);
2611-
for (let i = 1, n = displayName.length; isValid && i < n; i++) {
2612-
isValid = isIdentifierPart(displayName.charCodeAt(i), target);
2597+
if (!displayName) {
2598+
return undefined;
2599+
}
2600+
2601+
if (performCharacterChecks) {
2602+
if (!isIdentifierStart(displayName.charCodeAt(0), target)) {
2603+
return undefined;
2604+
}
2605+
2606+
for (let i = 1, n = displayName.length; i < n; i++) {
2607+
if (!isIdentifierPart(displayName.charCodeAt(i), target)) {
2608+
return undefined;
2609+
}
2610+
}
26132611
}
26142612

2615-
return isValid ? unescapeIdentifier(displayName) : undefined;
2613+
return unescapeIdentifier(displayName);
26162614
}
26172615

26182616
function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker, location: Node): CompletionEntry {
26192617
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
26202618
// We would like to only show things that can be added after a dot, so for instance numeric properties can
26212619
// not be accessed with a dot (a.1 <- invalid)
2622-
let displayName = getValidCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target);
2620+
let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
26232621
if (!displayName) {
26242622
return undefined;
26252623
}
@@ -2640,37 +2638,18 @@ module ts {
26402638
};
26412639
}
26422640

2643-
// If symbolName is undefined, all symbols at the specified are returned. If symbolName
2644-
// is not undefined, then the first symbol with that name at the specified position
2645-
// will be returned. Calling without symbolName is useful when you want the entire
2646-
// list of symbols (like for getCompletionsAtPosition). Calling with a symbolName is
2647-
// useful when you want information about a single symbol (like for getCompletionEntryDetails).
2648-
function getCompletionData(fileName: string, position: number, symbolName?: string) {
2649-
let result = getCompletionDataWorker(fileName, position, symbolName);
2650-
if (!result) {
2651-
return undefined;
2652-
}
2653-
2654-
if (result.symbols && symbolName) {
2655-
var target = program.getCompilerOptions().target;
2656-
result.symbols = filter(result.symbols, s => getValidCompletionEntryDisplayNameForSymbol(s, target) === symbolName);
2657-
}
2658-
2659-
return result;
2660-
}
2661-
2662-
function getCompletionDataWorker(fileName: string, position: number, symbolName: string) {
2641+
function getCompletionData(fileName: string, position: number) {
26632642
let syntacticStart = new Date().getTime();
26642643
let sourceFile = getValidSourceFile(fileName);
26652644

26662645
let start = new Date().getTime();
26672646
let currentToken = getTokenAtPosition(sourceFile, position);
2668-
log("getCompletionsAtPosition: Get current token: " + (new Date().getTime() - start));
2647+
log("getCompletionData: Get current token: " + (new Date().getTime() - start));
26692648

26702649
start = new Date().getTime();
26712650
// Completion not allowed inside comments, bail out if this is the case
26722651
let insideComment = isInsideComment(sourceFile, currentToken, position);
2673-
log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
2652+
log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
26742653

26752654
if (insideComment) {
26762655
log("Returning an empty list because completion was inside a comment.");
@@ -2681,14 +2660,14 @@ module ts {
26812660
// Note: previousToken can be undefined if we are the beginning of the file
26822661
start = new Date().getTime();
26832662
let previousToken = findPrecedingToken(position, sourceFile);
2684-
log("getCompletionsAtPosition: Get previous token 1: " + (new Date().getTime() - start));
2663+
log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
26852664

26862665
// The caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
26872666
// Skip this partial identifier to the previous token
26882667
if (previousToken && position <= previousToken.end && previousToken.kind === SyntaxKind.Identifier) {
26892668
let start = new Date().getTime();
26902669
previousToken = findPrecedingToken(previousToken.pos, sourceFile);
2691-
log("getCompletionsAtPosition: Get previous token 2: " + (new Date().getTime() - start));
2670+
log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start));
26922671
}
26932672

26942673
// Check if this is a valid completion location
@@ -2731,8 +2710,7 @@ module ts {
27312710
}
27322711
}
27332712

2734-
// Add keywords if this is not a member completion list
2735-
log("getCompletionsAtPosition: Semantic work: " + (new Date().getTime() - semanticStart));
2713+
log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
27362714

27372715
return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot };
27382716

@@ -2808,12 +2786,7 @@ module ts {
28082786
/// TODO filter meaning based on the current context
28092787
let scopeNode = getScopeNode(previousToken, position, sourceFile);
28102788
let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
2811-
2812-
// Filter down to the symbol that matches the symbolName if we were given one.
2813-
let predicate = symbolName !== undefined
2814-
? (s: Symbol) => getValidCompletionEntryDisplayNameForSymbol(s, target) === symbolName
2815-
: undefined;
2816-
symbols = typeInfoResolver.getSymbolsInScope(scopeNode, symbolMeanings, predicate);
2789+
symbols = typeInfoResolver.getSymbolsInScope(scopeNode, symbolMeanings);
28172790
}
28182791

28192792
return true;
@@ -3160,7 +3133,7 @@ module ts {
31603133

31613134
var target = program.getCompilerOptions().target;
31623135
for (let name in allIdentifiers) {
3163-
let displayName = getValidCompletionEntryDisplayName(name, target);
3136+
let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true);
31643137
if (displayName) {
31653138
// Use '1' so that all javascript identifier entries sort after Symbol entries.
31663139
entries.push({
@@ -3201,12 +3174,19 @@ module ts {
32013174
function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
32023175
synchronizeHostData();
32033176

3204-
// Look up a completion symbol with this name.
3205-
let completionData = getCompletionData(fileName, position, entryName);
3177+
// Compute all the completion symbols again.
3178+
let completionData = getCompletionData(fileName, position);
32063179
if (completionData) {
32073180
let { symbols, location } = completionData;
3208-
if (symbols && symbols.length > 0) {
3209-
let symbol = symbols[0];
3181+
3182+
// Find the symbol with the matching entry name.
3183+
let target = program.getCompilerOptions().target;
3184+
// We don't need to perform character checks here because we're only comparing the
3185+
// name against 'entryName' (which is known to be good), not building a new
3186+
// completion entry.
3187+
let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false) === entryName ? s : undefined);
3188+
3189+
if (symbol) {
32103190
let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, typeInfoResolver, location, SemanticMeaning.All);
32113191
return {
32123192
name: entryName,

tests/baselines/reference/APISample_compile.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ declare module "typescript" {
860860
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
861861
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
862862
getReturnTypeOfSignature(signature: Signature): Type;
863-
getSymbolsInScope(location: Node, meaning: SymbolFlags, predicate?: (symbol: Symbol) => boolean): Symbol[];
863+
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
864864
getSymbolAtLocation(node: Node): Symbol;
865865
getShorthandAssignmentValueSymbol(location: Node): Symbol;
866866
getTypeAtLocation(node: Node): Type;
@@ -938,8 +938,8 @@ declare module "typescript" {
938938
errorModuleName?: string;
939939
}
940940
interface EmitResolver {
941-
getGeneratedNameForNode(node: Node): string;
942-
getExpressionNameSubstitution(node: Identifier): string;
941+
hasGlobalName(name: string): boolean;
942+
getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
943943
hasExportDefaultValue(node: SourceFile): boolean;
944944
isReferencedAliasDeclaration(node: Node): boolean;
945945
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
@@ -953,7 +953,7 @@ declare module "typescript" {
953953
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
954954
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
955955
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
956-
isUnknownIdentifier(location: Node, name: string): boolean;
956+
resolvesToSomeValue(location: Node, name: string): boolean;
957957
getBlockScopedVariableId(node: Identifier): number;
958958
}
959959
const enum SymbolFlags {

tests/baselines/reference/APISample_compile.types

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,15 +2632,12 @@ declare module "typescript" {
26322632
>Signature : Signature
26332633
>Type : Type
26342634

2635-
getSymbolsInScope(location: Node, meaning: SymbolFlags, predicate?: (symbol: Symbol) => boolean): Symbol[];
2636-
>getSymbolsInScope : (location: Node, meaning: SymbolFlags, predicate?: (symbol: Symbol) => boolean) => Symbol[]
2635+
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
2636+
>getSymbolsInScope : (location: Node, meaning: SymbolFlags) => Symbol[]
26372637
>location : Node
26382638
>Node : Node
26392639
>meaning : SymbolFlags
26402640
>SymbolFlags : SymbolFlags
2641-
>predicate : (symbol: Symbol) => boolean
2642-
>symbol : Symbol
2643-
>Symbol : Symbol
26442641
>Symbol : Symbol
26452642

26462643
getSymbolAtLocation(node: Node): Symbol;
@@ -3006,15 +3003,17 @@ declare module "typescript" {
30063003
interface EmitResolver {
30073004
>EmitResolver : EmitResolver
30083005

3009-
getGeneratedNameForNode(node: Node): string;
3010-
>getGeneratedNameForNode : (node: Node) => string
3011-
>node : Node
3012-
>Node : Node
3006+
hasGlobalName(name: string): boolean;
3007+
>hasGlobalName : (name: string) => boolean
3008+
>name : string
30133009

3014-
getExpressionNameSubstitution(node: Identifier): string;
3015-
>getExpressionNameSubstitution : (node: Identifier) => string
3010+
getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
3011+
>getExpressionNameSubstitution : (node: Identifier, getGeneratedNameForNode: (node: Node) => string) => string
30163012
>node : Identifier
30173013
>Identifier : Identifier
3014+
>getGeneratedNameForNode : (node: Node) => string
3015+
>node : Node
3016+
>Node : Node
30183017

30193018
hasExportDefaultValue(node: SourceFile): boolean;
30203019
>hasExportDefaultValue : (node: SourceFile) => boolean
@@ -3112,8 +3111,8 @@ declare module "typescript" {
31123111
>PropertyAccessExpression : PropertyAccessExpression
31133112
>ElementAccessExpression : ElementAccessExpression
31143113

3115-
isUnknownIdentifier(location: Node, name: string): boolean;
3116-
>isUnknownIdentifier : (location: Node, name: string) => boolean
3114+
resolvesToSomeValue(location: Node, name: string): boolean;
3115+
>resolvesToSomeValue : (location: Node, name: string) => boolean
31173116
>location : Node
31183117
>Node : Node
31193118
>name : string

0 commit comments

Comments
 (0)