From 4c28e7337232650b8ed0c1bdd1de71c7ded80f29 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Nov 2014 14:10:37 -0800 Subject: [PATCH 1/2] All the identifiers need to be escaped to make sure compiler doesnt confuse __NonUnderscore character incorrectly Fixes #548 --- src/compiler/parser.ts | 4 +- .../escapedReservedCompilerNamedIdentifier.js | 93 +++++++++++++++++++ ...capedReservedCompilerNamedIdentifier.types | 85 +++++++++++++++++ .../protoAsIndexInIndexExpression.types | 4 +- .../escapedReservedCompilerNamedIdentifier.ts | 31 +++++++ 5 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/escapedReservedCompilerNamedIdentifier.js create mode 100644 tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types create mode 100644 tests/cases/compiler/escapedReservedCompilerNamedIdentifier.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 132213f950a..4849cb8c89e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1158,6 +1158,7 @@ module ts { } function internIdentifier(text: string): string { + text = escapeIdentifier(text); return hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text); } @@ -1168,8 +1169,7 @@ module ts { identifierCount++; if (isIdentifier) { var node = createNode(SyntaxKind.Identifier); - var text = escapeIdentifier(scanner.getTokenValue()); - node.text = internIdentifier(text); + node.text = internIdentifier(scanner.getTokenValue()); nextToken(); return finishNode(node); } diff --git a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.js b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.js new file mode 100644 index 00000000000..e2a8471be0a --- /dev/null +++ b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.js @@ -0,0 +1,93 @@ +//// [escapedReservedCompilerNamedIdentifier.ts] +// double underscores +var __proto__ = 10; +var o = { + "__proto__": 0 +}; +var b = o["__proto__"]; +var o1 = { + __proto__: 0 +}; +var b1 = o1["__proto__"]; +// Triple underscores +var ___proto__ = 10; +var o2 = { + "___proto__": 0 +}; +var b2 = o2["___proto__"]; +var o3 = { + ___proto__: 0 +}; +var b3 = o3["___proto__"]; +// One underscore +var _proto__ = 10; +var o4 = { + "_proto__": 0 +}; +var b4 = o4["_proto__"]; +var o5 = { + _proto__: 0 +}; +var b5 = o5["_proto__"]; + +//// [escapedReservedCompilerNamedIdentifier.js] +// double underscores +var __proto__ = 10; +var o = { + "__proto__": 0 +}; +var b = o["__proto__"]; +var o1 = { + __proto__: 0 +}; +var b1 = o1["__proto__"]; +// Triple underscores +var ___proto__ = 10; +var o2 = { + "___proto__": 0 +}; +var b2 = o2["___proto__"]; +var o3 = { + ___proto__: 0 +}; +var b3 = o3["___proto__"]; +// One underscore +var _proto__ = 10; +var o4 = { + "_proto__": 0 +}; +var b4 = o4["_proto__"]; +var o5 = { + _proto__: 0 +}; +var b5 = o5["_proto__"]; + + +//// [escapedReservedCompilerNamedIdentifier.d.ts] +declare var __proto__: number; +declare var o: { + "__proto__": number; +}; +declare var b: number; +declare var o1: { + __proto__: number; +}; +declare var b1: number; +declare var ___proto__: number; +declare var o2: { + "___proto__": number; +}; +declare var b2: number; +declare var o3: { + ___proto__: number; +}; +declare var b3: number; +declare var _proto__: number; +declare var o4: { + "_proto__": number; +}; +declare var b4: number; +declare var o5: { + _proto__: number; +}; +declare var b5: number; diff --git a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types new file mode 100644 index 00000000000..f54c7b80757 --- /dev/null +++ b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types @@ -0,0 +1,85 @@ +=== tests/cases/compiler/escapedReservedCompilerNamedIdentifier.ts === +// double underscores +var __proto__ = 10; +>__proto__ : number + +var o = { +>o : { "__proto__": number; } +>{ "__proto__": 0} : { "__proto__": number; } + + "__proto__": 0 +}; +var b = o["__proto__"]; +>b : number +>o["__proto__"] : number +>o : { "__proto__": number; } + +var o1 = { +>o1 : { __proto__: number; } +>{ __proto__: 0} : { __proto__: number; } + + __proto__: 0 +>__proto__ : number + +}; +var b1 = o1["__proto__"]; +>b1 : number +>o1["__proto__"] : number +>o1 : { __proto__: number; } + +// Triple underscores +var ___proto__ = 10; +>___proto__ : number + +var o2 = { +>o2 : { "___proto__": number; } +>{ "___proto__": 0} : { "___proto__": number; } + + "___proto__": 0 +}; +var b2 = o2["___proto__"]; +>b2 : number +>o2["___proto__"] : number +>o2 : { "___proto__": number; } + +var o3 = { +>o3 : { ___proto__: number; } +>{ ___proto__: 0} : { ___proto__: number; } + + ___proto__: 0 +>___proto__ : number + +}; +var b3 = o3["___proto__"]; +>b3 : number +>o3["___proto__"] : number +>o3 : { ___proto__: number; } + +// One underscore +var _proto__ = 10; +>_proto__ : number + +var o4 = { +>o4 : { "_proto__": number; } +>{ "_proto__": 0} : { "_proto__": number; } + + "_proto__": 0 +}; +var b4 = o4["_proto__"]; +>b4 : number +>o4["_proto__"] : number +>o4 : { "_proto__": number; } + +var o5 = { +>o5 : { _proto__: number; } +>{ _proto__: 0} : { _proto__: number; } + + _proto__: 0 +>_proto__ : number + +}; +var b5 = o5["_proto__"]; +>b5 : number +>o5["_proto__"] : number +>o5 : { _proto__: number; } + diff --git a/tests/baselines/reference/protoAsIndexInIndexExpression.types b/tests/baselines/reference/protoAsIndexInIndexExpression.types index e950098e6a1..bde87801fa5 100644 --- a/tests/baselines/reference/protoAsIndexInIndexExpression.types +++ b/tests/baselines/reference/protoAsIndexInIndexExpression.types @@ -20,8 +20,8 @@ WorkspacePrototype['__proto__'] = EntityPrototype; >EntityPrototype : any var o = { ->o : {} ->{ "__proto__": 0} : {} +>o : { "__proto__": number; } +>{ "__proto__": 0} : { "__proto__": number; } "__proto__": 0 }; diff --git a/tests/cases/compiler/escapedReservedCompilerNamedIdentifier.ts b/tests/cases/compiler/escapedReservedCompilerNamedIdentifier.ts new file mode 100644 index 00000000000..da874acf73a --- /dev/null +++ b/tests/cases/compiler/escapedReservedCompilerNamedIdentifier.ts @@ -0,0 +1,31 @@ +//@declaration: true +// double underscores +var __proto__ = 10; +var o = { + "__proto__": 0 +}; +var b = o["__proto__"]; +var o1 = { + __proto__: 0 +}; +var b1 = o1["__proto__"]; +// Triple underscores +var ___proto__ = 10; +var o2 = { + "___proto__": 0 +}; +var b2 = o2["___proto__"]; +var o3 = { + ___proto__: 0 +}; +var b3 = o3["___proto__"]; +// One underscore +var _proto__ = 10; +var o4 = { + "_proto__": 0 +}; +var b4 = o4["_proto__"]; +var o5 = { + _proto__: 0 +}; +var b5 = o5["_proto__"]; \ No newline at end of file From 37d84996db580d244e6d24b7eb3c1e10c8341246 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Nov 2014 15:56:56 -0800 Subject: [PATCH 2/2] Fix the completion entry for __proto Fixes #850 --- src/services/services.ts | 13 ++- tests/cases/fourslash/proto.ts | 6 +- .../fourslash/protoPropertyInObjectLiteral.ts | 21 +++++ .../protoVarInContexutalObjectLiteral.ts | 94 +++++++++++++++++++ ...VarVisibleWithOuterScopeUnderscoreProto.ts | 12 +++ 5 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 tests/cases/fourslash/protoPropertyInObjectLiteral.ts create mode 100644 tests/cases/fourslash/protoVarInContexutalObjectLiteral.ts create mode 100644 tests/cases/fourslash/protoVarVisibleWithOuterScopeUnderscoreProto.ts diff --git a/src/services/services.ts b/src/services/services.ts index 506770e3f2d..800d63738f0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2385,7 +2385,7 @@ module ts { if (isValid) { - return displayName; + return unescapeIdentifier(displayName); } } @@ -2561,9 +2561,12 @@ module ts { var start = new Date().getTime(); forEach(symbols, symbol => { var entry = createCompletionEntry(symbol, session.typeChecker, location); - if (entry && !lookUp(session.symbols, entry.name)) { - session.entries.push(entry); - session.symbols[entry.name] = symbol; + if (entry) { + var id = escapeIdentifier(entry.name); + if (!lookUp(session.symbols, id)) { + session.entries.push(entry); + session.symbols[id] = symbol; + } } }); host.log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start)); @@ -2771,7 +2774,7 @@ module ts { return undefined; } - var symbol = lookUp(activeCompletionSession.symbols, entryName); + var symbol = lookUp(activeCompletionSession.symbols, escapeIdentifier(entryName)); if (symbol) { var location = getTouchingPropertyName(sourceFile, position); var completionEntry = createCompletionEntry(symbol, session.typeChecker, location); diff --git a/tests/cases/fourslash/proto.ts b/tests/cases/fourslash/proto.ts index 73f23dea64f..cdb279b5009 100644 --- a/tests/cases/fourslash/proto.ts +++ b/tests/cases/fourslash/proto.ts @@ -12,9 +12,9 @@ verify.quickInfoIs("interface M.__proto__", ""); goTo.marker('2'); verify.quickInfoIs("(var) __proto__: M.__proto__", ""); goTo.marker('3'); -//verify.completionListContains("__proto__", "(var) __proto__: M.__proto__", ""); +verify.completionListContains("__proto__", "(var) __proto__: M.__proto__", ""); edit.insert("__proto__"); -//goTo.definition(); -//verify.caretAtMarker('2'); +goTo.definition(); +verify.caretAtMarker('2'); goTo.marker('4'); verify.quickInfoIs("(var) fun: (__proto__: any) => boolean", ""); \ No newline at end of file diff --git a/tests/cases/fourslash/protoPropertyInObjectLiteral.ts b/tests/cases/fourslash/protoPropertyInObjectLiteral.ts new file mode 100644 index 00000000000..8812f0adf62 --- /dev/null +++ b/tests/cases/fourslash/protoPropertyInObjectLiteral.ts @@ -0,0 +1,21 @@ +/// + +////var o1 = { +//// "__proto__": 10 +////}; +////var o2 = { +//// __proto__: 10 +////}; +////o1./*1*/ +////o2./*2*/ + +goTo.marker('1'); +verify.completionListContains("__proto__", '(property) "__proto__": number'); +edit.insert("__proto__ = 10;"); +goTo.marker('1'); +verify.quickInfoIs('(property) "__proto__": number'); +goTo.marker('2'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +edit.insert("__proto__ = 10;"); +goTo.marker('2'); +verify.quickInfoIs('(property) __proto__: number'); \ No newline at end of file diff --git a/tests/cases/fourslash/protoVarInContexutalObjectLiteral.ts b/tests/cases/fourslash/protoVarInContexutalObjectLiteral.ts new file mode 100644 index 00000000000..cf76ba7c3cd --- /dev/null +++ b/tests/cases/fourslash/protoVarInContexutalObjectLiteral.ts @@ -0,0 +1,94 @@ +/// + +////var o1 : { +//// __proto__: number; +//// p: number; +////} = { +//// /*1*/ +//// }; +////var o2: { +//// __proto__: number; +//// p: number; +////} = { +//// /*2*/ +//// }; +////var o3: { +//// "__proto__": number; +//// p: number; +////} = { +//// /*3*/ +//// }; +////var o4: { +//// "__proto__": number; +//// p: number; +////} = { +//// /*4*/ +//// }; +////var o5: { +//// __proto__: number; +//// ___proto__: string; +//// p: number; +////} = { +//// /*5*/ +//// }; +////var o6: { +//// __proto__: number; +//// ___proto__: string; +//// p: number; +////} = { +//// /*6*/ +//// }; + +goTo.marker('1'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('__proto__: 10,'); +verify.not.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); + +goTo.marker('2'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('"__proto__": 10,'); +verify.not.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); + +goTo.marker('3'); +verify.completionListContains("__proto__", '(property) "__proto__": number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('__proto__: 10,'); +verify.not.completionListContains("__proto__", '(property) "__proto__": number'); +verify.completionListContains("p", '(property) p: number'); + +goTo.marker('4'); +verify.completionListContains("__proto__", '(property) "__proto__": number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('"__proto__": 10,'); +verify.not.completionListContains("__proto__", '(property) "__proto__": number'); +verify.completionListContains("p", '(property) p: number'); + +goTo.marker('5'); +verify.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('__proto__: 10,'); +verify.not.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('"___proto__": "10",'); +verify.not.completionListContains("__proto__", '(property) __proto__: number'); +verify.not.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("p", '(property) p: number'); + +goTo.marker('6'); +verify.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('___proto__: "10",'); +verify.completionListContains("__proto__", '(property) __proto__: number'); +verify.not.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("p", '(property) p: number'); +edit.insert('"__proto__": 10,'); +verify.not.completionListContains("__proto__", '(property) __proto__: number'); +verify.not.completionListContains("___proto__", '(property) ___proto__: string'); +verify.completionListContains("p", '(property) p: number'); \ No newline at end of file diff --git a/tests/cases/fourslash/protoVarVisibleWithOuterScopeUnderscoreProto.ts b/tests/cases/fourslash/protoVarVisibleWithOuterScopeUnderscoreProto.ts new file mode 100644 index 00000000000..a36f5ddbfe2 --- /dev/null +++ b/tests/cases/fourslash/protoVarVisibleWithOuterScopeUnderscoreProto.ts @@ -0,0 +1,12 @@ +/// + +////// outer +////var ___proto__ = 10; +////function foo() { +//// var __proto__ = "hello"; +//// /**/ +////} + +goTo.marker(''); +verify.completionListContains("__proto__", '(local var) __proto__: string'); +verify.completionListContains("___proto__", '(var) ___proto__: number'); \ No newline at end of file