Skip to content

Possible incorrect getDocumentHighlights behavior with global lexically scoped variables #4560

Closed
@jkillian

Description

@jkillian

There seem to be some related funny issues going on. When calling getDocumentHighlights on the position of the hello variable declaration in the following code snippet:

// Incorrect case:

class HelloWorld {
    constructor(public name: string) { }
    sayHello() {
        return `Hello, ${this.name}!`;
    }
};

let hello = new HelloWorld("TSLint");
hello.sayHello();

only the declaration is returned and not the usage on the next line. However, in the following code snippet, both uses are returned, correctly:

// Correct case:

class HelloWorld {
    constructor(public name: string) { }
    sayHello() {
        return `Hello, ${this.name}!`;
    }
};

if (true) {
    let hello = new HelloWorld("TSLint");
    hello.sayHello();
}
// Correct case (var vs. let):

class HelloWorld {
    constructor(public name: string) { }
    sayHello() {
        return `Hello, ${this.name}!`;
    }
};

var hello = new HelloWorld("TSLint");
hello.sayHello();

Also strangely, Sublime will correctly show both references in all three cases.

I've been trying to figure out the root cause but haven't been able to yet. It seems that the failure occurs specifically for lexically scoped variables declared at global scope, such as let declarations at global scope.

In case it helps, I did notice that in the getReferencesInNode function the array of possible positions contains exactly the two actual positions in both the incorrect and correct case. However, there is a difference when finding the relatedSymbol:

var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
if (referenceSymbol) {
    var referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
    var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
    var relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation);
    // NOTE (added for the Github issue):
    // relatedSymbol is undefined here in incorrect case, defined in the correct case
    if (relatedSymbol) {
        var referencedSymbol = getReferencedSymbol(relatedSymbol);
        referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation));
    }
    else if (!(referenceSymbol.flags & 67108864 /* Transient */) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
        var referencedSymbol = getReferencedSymbol(shorthandValueSymbol);
        referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
    }
}

(Related to palantir/tslint#570)

Metadata

Metadata

Labels

APIRelates to the public API for TypeScriptExternalRelates to another program, environment, or user action which we cannot control.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions