Skip to content

Commit ffef437

Browse files
Merge pull request #799 from Microsoft/stopBlindlyColoring
Values sharing names with interfaces no longer classified as interfaces
2 parents 060a8b6 + a6e991a commit ffef437

File tree

6 files changed

+117
-97
lines changed

6 files changed

+117
-97
lines changed

src/compiler/checker.ts

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -7099,23 +7099,6 @@ module ts {
70997099
return mapToArray(symbols);
71007100
}
71017101

7102-
// True if the given identifier is the name of a type declaration node (class, interface, enum, type parameter, etc)
7103-
function isTypeDeclarationName(name: Node): boolean {
7104-
return name.kind == SyntaxKind.Identifier &&
7105-
isTypeDeclaration(name.parent) &&
7106-
(<Declaration>name.parent).name === name;
7107-
}
7108-
7109-
function isTypeDeclaration(node: Node): boolean {
7110-
switch (node.kind) {
7111-
case SyntaxKind.TypeParameter:
7112-
case SyntaxKind.ClassDeclaration:
7113-
case SyntaxKind.InterfaceDeclaration:
7114-
case SyntaxKind.EnumDeclaration:
7115-
return true;
7116-
}
7117-
}
7118-
71197102
// True if the given identifier is part of a type reference
71207103
function isTypeReferenceIdentifier(entityName: EntityName): boolean {
71217104
var node: Node = entityName;
@@ -7194,75 +7177,6 @@ module ts {
71947177
return false;
71957178
}
71967179

7197-
function isTypeNode(node: Node): boolean {
7198-
if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) {
7199-
return true;
7200-
}
7201-
7202-
switch (node.kind) {
7203-
case SyntaxKind.AnyKeyword:
7204-
case SyntaxKind.NumberKeyword:
7205-
case SyntaxKind.StringKeyword:
7206-
case SyntaxKind.BooleanKeyword:
7207-
return true;
7208-
case SyntaxKind.VoidKeyword:
7209-
return node.parent.kind !== SyntaxKind.PrefixOperator;
7210-
case SyntaxKind.StringLiteral:
7211-
// Specialized signatures can have string literals as their parameters' type names
7212-
return node.parent.kind === SyntaxKind.Parameter;
7213-
// Identifiers and qualified names may be type nodes, depending on their context. Climb
7214-
// above them to find the lowest container
7215-
case SyntaxKind.Identifier:
7216-
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
7217-
if (node.parent.kind === SyntaxKind.QualifiedName) {
7218-
node = node.parent;
7219-
}
7220-
// Fall through
7221-
case SyntaxKind.QualifiedName:
7222-
// At this point, node is either a qualified name or an identifier
7223-
var parent = node.parent;
7224-
if (parent.kind === SyntaxKind.TypeQuery) {
7225-
return false;
7226-
}
7227-
// Do not recursively call isTypeNode on the parent. In the example:
7228-
//
7229-
// var a: A.B.C;
7230-
//
7231-
// Calling isTypeNode would consider the qualified name A.B a type node. Only C or
7232-
// A.B.C is a type node.
7233-
if (parent.kind >= SyntaxKind.FirstTypeNode && parent.kind <= SyntaxKind.LastTypeNode) {
7234-
return true;
7235-
}
7236-
switch (parent.kind) {
7237-
case SyntaxKind.TypeParameter:
7238-
return node === (<TypeParameterDeclaration>parent).constraint;
7239-
case SyntaxKind.Property:
7240-
case SyntaxKind.Parameter:
7241-
case SyntaxKind.VariableDeclaration:
7242-
return node === (<VariableDeclaration>parent).type;
7243-
case SyntaxKind.FunctionDeclaration:
7244-
case SyntaxKind.FunctionExpression:
7245-
case SyntaxKind.ArrowFunction:
7246-
case SyntaxKind.Constructor:
7247-
case SyntaxKind.Method:
7248-
case SyntaxKind.GetAccessor:
7249-
case SyntaxKind.SetAccessor:
7250-
return node === (<FunctionDeclaration>parent).type;
7251-
case SyntaxKind.CallSignature:
7252-
case SyntaxKind.ConstructSignature:
7253-
case SyntaxKind.IndexSignature:
7254-
return node === (<SignatureDeclaration>parent).type;
7255-
case SyntaxKind.TypeAssertion:
7256-
return node === (<TypeAssertion>parent).type;
7257-
case SyntaxKind.CallExpression:
7258-
case SyntaxKind.NewExpression:
7259-
return (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
7260-
}
7261-
}
7262-
7263-
return false;
7264-
}
7265-
72667180
function isInRightSideOfImportOrExportAssignment(node: EntityName) {
72677181
while (node.parent.kind === SyntaxKind.QualifiedName) {
72687182
node = node.parent;

src/compiler/parser.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,100 @@ module ts {
402402
return false;
403403
}
404404

405+
/**
406+
* Note: this function only works when given a node with valid parent pointers.
407+
*/
408+
export function isTypeNode(node: Node): boolean {
409+
if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) {
410+
return true;
411+
}
412+
413+
switch (node.kind) {
414+
case SyntaxKind.AnyKeyword:
415+
case SyntaxKind.NumberKeyword:
416+
case SyntaxKind.StringKeyword:
417+
case SyntaxKind.BooleanKeyword:
418+
return true;
419+
case SyntaxKind.VoidKeyword:
420+
return node.parent.kind !== SyntaxKind.PrefixOperator;
421+
case SyntaxKind.StringLiteral:
422+
// Specialized signatures can have string literals as their parameters' type names
423+
return node.parent.kind === SyntaxKind.Parameter;
424+
// Identifiers and qualified names may be type nodes, depending on their context. Climb
425+
// above them to find the lowest container
426+
case SyntaxKind.Identifier:
427+
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
428+
if (node.parent.kind === SyntaxKind.QualifiedName) {
429+
node = node.parent;
430+
}
431+
// Fall through
432+
case SyntaxKind.QualifiedName:
433+
// At this point, node is either a qualified name or an identifier
434+
var parent = node.parent;
435+
if (parent.kind === SyntaxKind.TypeQuery) {
436+
return false;
437+
}
438+
// Do not recursively call isTypeNode on the parent. In the example:
439+
//
440+
// var a: A.B.C;
441+
//
442+
// Calling isTypeNode would consider the qualified name A.B a type node. Only C or
443+
// A.B.C is a type node.
444+
if (parent.kind >= SyntaxKind.FirstTypeNode && parent.kind <= SyntaxKind.LastTypeNode) {
445+
return true;
446+
}
447+
switch (parent.kind) {
448+
case SyntaxKind.TypeParameter:
449+
return node === (<TypeParameterDeclaration>parent).constraint;
450+
case SyntaxKind.Property:
451+
case SyntaxKind.Parameter:
452+
case SyntaxKind.VariableDeclaration:
453+
return node === (<VariableDeclaration>parent).type;
454+
case SyntaxKind.FunctionDeclaration:
455+
case SyntaxKind.FunctionExpression:
456+
case SyntaxKind.ArrowFunction:
457+
case SyntaxKind.Constructor:
458+
case SyntaxKind.Method:
459+
case SyntaxKind.GetAccessor:
460+
case SyntaxKind.SetAccessor:
461+
return node === (<FunctionDeclaration>parent).type;
462+
case SyntaxKind.CallSignature:
463+
case SyntaxKind.ConstructSignature:
464+
case SyntaxKind.IndexSignature:
465+
return node === (<SignatureDeclaration>parent).type;
466+
case SyntaxKind.TypeAssertion:
467+
return node === (<TypeAssertion>parent).type;
468+
case SyntaxKind.CallExpression:
469+
case SyntaxKind.NewExpression:
470+
return (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
471+
}
472+
}
473+
474+
return false;
475+
}
476+
477+
/**
478+
* Note: this function only works when given a node with valid parent pointers.
479+
*
480+
* returns true if the given identifier is the name of a type declaration node (class, interface, enum, type parameter, etc)
481+
*/
482+
export function isTypeDeclarationName(name: Node): boolean {
483+
return name.kind == SyntaxKind.Identifier &&
484+
isTypeDeclaration(name.parent) &&
485+
(<Declaration>name.parent).name === name;
486+
}
487+
488+
489+
export function isTypeDeclaration(node: Node): boolean {
490+
switch (node.kind) {
491+
case SyntaxKind.TypeParameter:
492+
case SyntaxKind.ClassDeclaration:
493+
case SyntaxKind.InterfaceDeclaration:
494+
case SyntaxKind.EnumDeclaration:
495+
return true;
496+
}
497+
}
498+
405499
export function getContainingFunction(node: Node): SignatureDeclaration {
406500
while (true) {
407501
node = node.parent;

src/harness/fourslash.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,7 @@ module FourSlash {
15761576

15771577
private verifyClassifications(expected: { classificationType: string; text: string }[], actual: ts.ClassifiedSpan[]) {
15781578
if (actual.length !== expected.length) {
1579-
this.raiseError('verifySyntacticClassification failed - expected total classifications to be ' + expected.length + ', but was ' + actual.length);
1579+
this.raiseError('verifyClassifications failed - expected total classifications to be ' + expected.length + ', but was ' + actual.length);
15801580
}
15811581

15821582
for (var i = 0; i < expected.length; i++) {
@@ -1585,15 +1585,15 @@ module FourSlash {
15851585

15861586
var expectedType: string = (<any>ts.ClassificationTypeNames)[expectedClassification.classificationType];
15871587
if (expectedType !== actualClassification.classificationType) {
1588-
this.raiseError('verifySyntacticClassification failed - expected classifications type to be ' +
1588+
this.raiseError('verifyClassifications failed - expected classifications type to be ' +
15891589
expectedType + ', but was ' +
15901590
actualClassification.classificationType);
15911591
}
15921592

15931593
var actualSpan = actualClassification.textSpan;
15941594
var actualText = this.activeFile.content.substr(actualSpan.start(), actualSpan.length());
15951595
if (expectedClassification.text !== actualText) {
1596-
this.raiseError('verifySyntacticClassification failed - expected classificatied text to be ' +
1596+
this.raiseError('verifyClassifications failed - expected classificatied text to be ' +
15971597
expectedClassification.text + ', but was ' +
15981598
actualText);
15991599
}

src/services/services.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4044,7 +4044,7 @@ module ts {
40444044

40454045
return result;
40464046

4047-
function classifySymbol(symbol: Symbol) {
4047+
function classifySymbol(symbol: Symbol, isInTypePosition: boolean) {
40484048
var flags = symbol.getFlags();
40494049

40504050
if (flags & SymbolFlags.Class) {
@@ -4053,14 +4053,16 @@ module ts {
40534053
else if (flags & SymbolFlags.Enum) {
40544054
return ClassificationTypeNames.enumName;
40554055
}
4056-
else if (flags & SymbolFlags.Interface) {
4057-
return ClassificationTypeNames.interfaceName;
4058-
}
40594056
else if (flags & SymbolFlags.Module) {
40604057
return ClassificationTypeNames.moduleName;
40614058
}
4062-
else if (flags & SymbolFlags.TypeParameter) {
4063-
return ClassificationTypeNames.typeParameterName;
4059+
else if (isInTypePosition) {
4060+
if (flags & SymbolFlags.Interface) {
4061+
return ClassificationTypeNames.interfaceName;
4062+
}
4063+
else if (flags & SymbolFlags.TypeParameter) {
4064+
return ClassificationTypeNames.typeParameterName;
4065+
}
40644066
}
40654067
}
40664068

@@ -4070,7 +4072,7 @@ module ts {
40704072
if (node.kind === SyntaxKind.Identifier && node.getWidth() > 0) {
40714073
var symbol = typeInfoResolver.getSymbolInfo(node);
40724074
if (symbol) {
4073-
var type = classifySymbol(symbol);
4075+
var type = classifySymbol(symbol, isTypeNode(node) || isTypeDeclarationName(node));
40744076
if (type) {
40754077
result.push({
40764078
textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()),

tests/cases/fourslash/semanticClassification1.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//// }
77
//// interface X extends M.I { }
88

9-
debugger;
109
var c = classification;
1110
verify.semanticClassificationsAre(
1211
c.moduleName("M"), c.interfaceName("I"), c.interfaceName("X"), c.moduleName("M"), c.interfaceName("I"));
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
//// interface Thing {
4+
//// toExponential(): number;
5+
//// }
6+
////
7+
//// var Thing = 0;
8+
//// Thing.toExponential();
9+
10+
var c = classification;
11+
verify.semanticClassificationsAre(c.interfaceName("Thing"));

0 commit comments

Comments
 (0)