Skip to content

Commit beb2725

Browse files
committed
Merge pull request #676 from Microsoft/completionFixes
Completion fixes
2 parents d867cec + 9e00693 commit beb2725

File tree

97 files changed

+507
-323
lines changed

Some content is hidden

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

97 files changed

+507
-323
lines changed

src/compiler/checker.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,7 +2432,7 @@ module ts {
24322432
case SyntaxKind.Identifier:
24332433
case SyntaxKind.QualifiedName:
24342434
var symbol = getSymbolInfo(node);
2435-
return getDeclaredTypeOfSymbol(symbol);
2435+
return symbol && getDeclaredTypeOfSymbol(symbol);
24362436
default:
24372437
return unknownType;
24382438
}
@@ -3472,41 +3472,6 @@ module ts {
34723472
return getAncestor(node, kind) !== undefined;
34733473
}
34743474

3475-
function getAncestor(node: Node, kind: SyntaxKind): Node {
3476-
switch (kind) {
3477-
// special-cases that can be come first
3478-
case SyntaxKind.ClassDeclaration:
3479-
while (node) {
3480-
switch (node.kind) {
3481-
case SyntaxKind.ClassDeclaration:
3482-
return <ClassDeclaration>node;
3483-
case SyntaxKind.EnumDeclaration:
3484-
case SyntaxKind.InterfaceDeclaration:
3485-
case SyntaxKind.ModuleDeclaration:
3486-
case SyntaxKind.ImportDeclaration:
3487-
// early exit cases - declarations cannot be nested in classes
3488-
return undefined;
3489-
default:
3490-
node = node.parent;
3491-
continue;
3492-
}
3493-
}
3494-
break;
3495-
default:
3496-
while (node) {
3497-
if (node.kind === kind) {
3498-
return node;
3499-
}
3500-
else {
3501-
node = node.parent;
3502-
}
3503-
}
3504-
break;
3505-
}
3506-
3507-
return undefined;
3508-
}
3509-
35103475
// EXPRESSION TYPE CHECKING
35113476

35123477
function checkIdentifier(node: Identifier): Type {
@@ -3853,6 +3818,11 @@ module ts {
38533818
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
38543819
// be "pushed" onto a node using the contextualType property.
38553820
function getContextualType(node: Expression): Type {
3821+
if (isInsideWithStatementBody(node)) {
3822+
// We cannot answer semantic questions within a with block, do not proceed any further
3823+
return undefined;
3824+
}
3825+
38563826
if (node.contextualType) {
38573827
return node.contextualType;
38583828
}
@@ -6718,7 +6688,20 @@ module ts {
67186688
return findChildAtPosition(sourceFile);
67196689
}
67206690

6721-
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
6691+
function isInsideWithStatementBody(node: Node): boolean {
6692+
if (node) {
6693+
while (node.parent) {
6694+
if (node.parent.kind === SyntaxKind.WithStatement && (<WithStatement>node.parent).statement === node) {
6695+
return true;
6696+
}
6697+
node = node.parent;
6698+
}
6699+
}
6700+
6701+
return false;
6702+
}
6703+
6704+
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]{
67226705
var symbols: SymbolTable = {};
67236706
var memberFlags: NodeFlags = 0;
67246707
function copySymbol(symbol: Symbol, meaning: SymbolFlags) {
@@ -6738,6 +6721,12 @@ module ts {
67386721
}
67396722
}
67406723
}
6724+
6725+
if (isInsideWithStatementBody(location)) {
6726+
// We cannot answer semantic questions within a with block, do not proceed any further
6727+
return [];
6728+
}
6729+
67416730
while (location) {
67426731
if (location.locals && !isGlobalSourceFile(location)) {
67436732
copySymbols(location.locals, meaning);
@@ -7010,6 +6999,11 @@ module ts {
70106999
}
70117000

70127001
function getSymbolInfo(node: Node) {
7002+
if (isInsideWithStatementBody(node)) {
7003+
// We cannot answer semantic questions within a with block, do not proceed any further
7004+
return undefined;
7005+
}
7006+
70137007
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
70147008
// This is a declaration, call getSymbolOfNode
70157009
return getSymbolOfNode(node.parent);
@@ -7064,9 +7058,15 @@ module ts {
70647058
}
70657059

70667060
function getTypeOfNode(node: Node): Type {
7061+
if (isInsideWithStatementBody(node)) {
7062+
// We cannot answer semantic questions within a with block, do not proceed any further
7063+
return unknownType;
7064+
}
7065+
70677066
if (isExpression(node)) {
70687067
return getTypeOfExpression(<Expression>node);
70697068
}
7069+
70707070
if (isTypeNode(node)) {
70717071
return getTypeFromTypeNode(<TypeNode>node);
70727072
}
@@ -7079,7 +7079,7 @@ module ts {
70797079

70807080
if (isTypeDeclarationName(node)) {
70817081
var symbol = getSymbolInfo(node);
7082-
return getDeclaredTypeOfSymbol(symbol);
7082+
return symbol && getDeclaredTypeOfSymbol(symbol);
70837083
}
70847084

70857085
if (isDeclaration(node)) {
@@ -7090,12 +7090,12 @@ module ts {
70907090

70917091
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
70927092
var symbol = getSymbolInfo(node);
7093-
return getTypeOfSymbol(symbol);
7093+
return symbol && getTypeOfSymbol(symbol);
70947094
}
70957095

70967096
if (isInRightSideOfImportOrExportAssignment(node)) {
70977097
var symbol = getSymbolInfo(node);
7098-
var declaredType = getDeclaredTypeOfSymbol(symbol);
7098+
var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
70997099
return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
71007100
}
71017101

@@ -7147,7 +7147,7 @@ module ts {
71477147
}
71487148

71497149
function getRootSymbol(symbol: Symbol) {
7150-
return (symbol.flags & SymbolFlags.Transient) ? getSymbolLinks(symbol).target : symbol;
7150+
return ((symbol.flags & SymbolFlags.Transient) && getSymbolLinks(symbol).target) || symbol;
71517151
}
71527152

71537153
// Emitter support

src/compiler/parser.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,39 @@ module ts {
531531
return false;
532532
}
533533

534+
export function getAncestor(node: Node, kind: SyntaxKind): Node {
535+
switch (kind) {
536+
// special-cases that can be come first
537+
case SyntaxKind.ClassDeclaration:
538+
while (node) {
539+
switch (node.kind) {
540+
case SyntaxKind.ClassDeclaration:
541+
return <ClassDeclaration>node;
542+
case SyntaxKind.EnumDeclaration:
543+
case SyntaxKind.InterfaceDeclaration:
544+
case SyntaxKind.ModuleDeclaration:
545+
case SyntaxKind.ImportDeclaration:
546+
// early exit cases - declarations cannot be nested in classes
547+
return undefined;
548+
default:
549+
node = node.parent;
550+
continue;
551+
}
552+
}
553+
break;
554+
default:
555+
while (node) {
556+
if (node.kind === kind) {
557+
return node;
558+
}
559+
node = node.parent;
560+
}
561+
break;
562+
}
563+
564+
return undefined;
565+
}
566+
534567
enum ParsingContext {
535568
SourceElements, // Elements in source file
536569
ModuleElements, // Elements in module declaration
@@ -2200,10 +2233,38 @@ module ts {
22002233

22012234
function parseCallAndAccess(expr: Expression, inNewExpression: boolean): Expression {
22022235
while (true) {
2236+
var dotStart = scanner.getTokenPos();
22032237
if (parseOptional(SyntaxKind.DotToken)) {
22042238
var propertyAccess = <PropertyAccess>createNode(SyntaxKind.PropertyAccess, expr.pos);
2239+
// Technically a keyword is valid here as all keywords are identifier names.
2240+
// However, often we'll encounter this in error situations when the keyword
2241+
// is actually starting another valid construct.
2242+
//
2243+
// So, we check for the following specific case:
2244+
//
2245+
// name.
2246+
// keyword identifierNameOrKeyword
2247+
//
2248+
// Note: the newlines are important here. For example, if that above code
2249+
// were rewritten into:
2250+
//
2251+
// name.keyword
2252+
// identifierNameOrKeyword
2253+
//
2254+
// Then we would consider it valid. That's because ASI would take effect and
2255+
// the code would be implicitly: "name.keyword; identifierNameOrKeyword".
2256+
// In the first case though, ASI will not take effect because there is not a
2257+
// line terminator after the keyword.
2258+
if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord() && lookAhead(() => scanner.isReservedWord())) {
2259+
grammarErrorAtPos(dotStart, scanner.getStartPos() - dotStart, Diagnostics.Identifier_expected);
2260+
var id = <Identifier>createMissingNode();
2261+
}
2262+
else {
2263+
var id = parseIdentifierName();
2264+
}
2265+
22052266
propertyAccess.left = expr;
2206-
propertyAccess.right = parseIdentifierName();
2267+
propertyAccess.right = id;
22072268
expr = finishNode(propertyAccess);
22082269
continue;
22092270
}

0 commit comments

Comments
 (0)