Skip to content

Commit

Permalink
Merge branch 'master' into completionsBracket
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Hanson committed Jan 4, 2018
2 parents 4f5f540 + 2ea5f58 commit 761f2cb
Show file tree
Hide file tree
Showing 42 changed files with 149 additions and 272 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace ts.codefix {
});

function getQualifiedName(sourceFile: SourceFile, pos: number): QualifiedName & { left: Identifier } | undefined {
const qualifiedName = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isQualifiedName)!;
const qualifiedName = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ true), isQualifiedName)!;
Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name.");
return isIdentifier(qualifiedName.left) ? qualifiedName as QualifiedName & { left: Identifier } : undefined;
}
Expand Down
34 changes: 16 additions & 18 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,27 +228,25 @@ namespace ts.Completions {
// We don't set this for global variables or completions from external module exports, because we can have multiple of those.
// Based on the order we add things we will always see locals first, then globals, then module exports.
// So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name.
const uniques = createMap<true>();
if (symbols) {
for (const symbol of symbols) {
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions);
if (!entry) {
continue;
}

const { name } = entry;
if (uniques.has(name)) {
continue;
}
const uniques = createMap<true>();
for (const symbol of symbols) {
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions);
if (!entry) {
continue;
}

// Latter case tests whether this is a global variable.
if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile()))) {
uniques.set(name, true);
}
const { name } = entry;
if (uniques.has(name)) {
continue;
}

entries.push(entry);
// Latter case tests whether this is a global variable.
if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile()))) {
uniques.set(name, true);
}

entries.push(entry);
}

log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (timestamp() - start));
Expand Down
67 changes: 19 additions & 48 deletions src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,10 @@ namespace ts.FindAllReferences {

export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position);

if (!referencedSymbols || !referencedSymbols.length) {
return undefined;
}

const out: ReferencedSymbol[] = [];
const checker = program.getTypeChecker();
for (const { definition, references } of referencedSymbols) {
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) =>
// Only include referenced symbols that have a valid definition.
if (definition) {
out.push({ definition: definitionToReferencedSymbolDefinitionInfo(definition, checker), references: references.map(toReferenceEntry) });
}
}

return out;
definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker), references: references.map(toReferenceEntry) });
}

export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] {
Expand Down Expand Up @@ -876,6 +865,8 @@ namespace ts.FindAllReferences.Core {
case SpecialSearchKind.Class:
addClassStaticThisReferences(referenceLocation, search, state);
break;
default:
Debug.assertNever(state.specialSearchKind);
}

getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
Expand Down Expand Up @@ -1436,7 +1427,7 @@ namespace ts.FindAllReferences.Core {
// This is not needed when searching for re-exports.
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, implementations: boolean): Symbol[] {
// The search set contains at least the current symbol
const result = [symbol];
const result: Symbol[] = [];

const containingObjectLiteralElement = getContainingObjectLiteralElement(location);
if (containingObjectLiteralElement) {
Expand All @@ -1453,9 +1444,9 @@ namespace ts.FindAllReferences.Core {
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), contextualSymbol => {
addRange(result, checker.getRootSymbols(contextualSymbol));
});
for (const contextualSymbol of getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker)) {
addRootSymbols(contextualSymbol);
}

/* Because in short-hand property assignment, location has two meaning : property name and as value of the property
* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
Expand Down Expand Up @@ -1496,9 +1487,7 @@ namespace ts.FindAllReferences.Core {
// If this is a union property, add all the symbols from all its source symbols in all unioned types.
// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
for (const rootSymbol of checker.getRootSymbols(sym)) {
if (rootSymbol !== sym) {
result.push(rootSymbol);
}
result.push(rootSymbol);

// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
Expand All @@ -1522,7 +1511,7 @@ namespace ts.FindAllReferences.Core {
* @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol.
* The value of previousIterationSymbol is undefined when the function is first called.
*/
function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[], previousIterationSymbolsCache: SymbolTable, checker: TypeChecker): void {
function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Push<Symbol>, previousIterationSymbolsCache: SymbolTable, checker: TypeChecker): void {
if (!symbol) {
return;
}
Expand Down Expand Up @@ -1591,9 +1580,7 @@ namespace ts.FindAllReferences.Core {
// compare to our searchSymbol
const containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation);
if (containingObjectLiteralElement) {
const contextualSymbol = forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), contextualSymbol =>
find(checker.getRootSymbols(contextualSymbol), search.includes));

const contextualSymbol = firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), findRootSymbol);
if (contextualSymbol) {
return contextualSymbol;
}
Expand Down Expand Up @@ -1622,7 +1609,7 @@ namespace ts.FindAllReferences.Core {
function findRootSymbol(sym: Symbol): Symbol | undefined {
// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
// Or a union property, use its underlying unioned symbols
return forEach(state.checker.getRootSymbols(sym), rootSymbol => {
return firstDefined(checker.getRootSymbols(sym), rootSymbol => {
// if it is in the list, then we are done
if (search.includes(rootSymbol)) {
return rootSymbol;
Expand All @@ -1633,12 +1620,12 @@ namespace ts.FindAllReferences.Core {
// parent symbol
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
// Parents will only be defined if implementations is true
if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, state.checker))) {
if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker))) {
return undefined;
}

const result: Symbol[] = [];
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker);
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker);
return find(result, search.includes);
}

Expand All @@ -1660,28 +1647,12 @@ namespace ts.FindAllReferences.Core {
}

/** Gets all symbols for one property. Does not get symbols for every property. */
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): Symbol[] | undefined {
const objectLiteral = <ObjectLiteralExpression>node.parent;
const contextualType = checker.getContextualType(objectLiteral);
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): ReadonlyArray<Symbol> {
const contextualType = checker.getContextualType(<ObjectLiteralExpression>node.parent);
const name = getNameFromObjectLiteralElement(node);
if (name && contextualType) {
const result: Symbol[] = [];
const symbol = contextualType.getProperty(name);
if (symbol) {
result.push(symbol);
}

if (contextualType.flags & TypeFlags.Union) {
forEach((<UnionType>contextualType).types, t => {
const symbol = t.getProperty(name);
if (symbol) {
result.push(symbol);
}
});
}
return result;
}
return undefined;
const symbol = contextualType && name && contextualType.getProperty(name);
return symbol ? [symbol] :
contextualType && contextualType.flags & TypeFlags.Union ? mapDefined((<UnionType>contextualType).types, t => t.getProperty(name)) : emptyArray;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,5 @@ function checkRefs() {
const ranges = test.ranges();
const [r0, r1] = ranges;
verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]);
verify.referenceGroups(r1, [
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] },
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] }
]);
verify.referenceGroups(r1, [{ definition: "(method) Second.Test.start(): Second.Test", ranges }]);
}
45 changes: 45 additions & 0 deletions tests/cases/fourslash/codeFixInPropertyAccess_js.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/// <reference path='fourslash.ts' />

// @allowJs: true
// @checkJs: true

// @Filename: /a.js
//// /**
//// * @typedef Foo
//// * @property foo
//// */

//// /**
//// * @param {Foo.foo} inst
//// */
//// function blah(inst) {
//// return false;
//// }

verify.codeFixAll({
fixId: "correctQualifiedNameToIndexedAccessType",
newFileContent:
`/**
* @typedef Foo
* @property foo
*/
/**
* @param {Foo["foo"]} inst
*/
function blah(inst) {
return false;
}`,
});


/**
* @typedef Foo
* @property foo
*/

/**
* @param {Foo.foo} inst
*/
function blah(inst) {
return false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,4 @@
////
////let {[|property|]: pVar} = x;

const ranges = test.ranges();
const [r0, r1, r2] = ranges;
verify.referenceGroups(r0, [{ definition: "(property) property: {}", ranges }]);
verify.referenceGroups([r1, r2], [
{ definition: "(property) property: {}", ranges: [r0] },
{ definition: "(property) property: {}", ranges: [r1, r2] }
]);
verify.singleReferenceGroup("(property) property: {}");
3 changes: 1 addition & 2 deletions tests/cases/fourslash/findAllRefsForObjectSpread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ verify.referenceGroups(r1, [{ definition: "(property) A2.a: number", ranges: [r1

// but the resulting property refers to everything
verify.referenceGroups(r2, [
{ definition: "(property) A1.a: string", ranges: [r0, r3] },
{ definition: "(property) A1.a: string", ranges: [r0, r2, r3] },
{ definition: "(property) A2.a: number", ranges: [r1] },
{ definition: "(property) a: string | number", ranges: [r2] }
]);

verify.referenceGroups(r3, [{ definition: "(property) A1.a: string", ranges: [r0, r2, r3] }]);
6 changes: 1 addition & 5 deletions tests/cases/fourslash/findAllRefsInheritedProperties1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,5 @@
//// v.[|propName|];

const [r0, r1, r2, r3] = test.ranges();
verify.referenceGroups(r0, [{ definition: "(method) class1.doStuff(): void", ranges: [r0, r2] }]);
verify.referenceGroups(r2, [
{ definition: "(method) class1.doStuff(): void", ranges: [r0] },
{ definition: "(method) class1.doStuff(): void", ranges: [r2] }
]);
verify.singleReferenceGroup("(method) class1.doStuff(): void", [r0, r2]);
verify.singleReferenceGroup("(property) class1.propName: string", [r1, r3]);
8 changes: 1 addition & 7 deletions tests/cases/fourslash/findAllRefsInheritedProperties3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ verify.referenceGroups(r0, [{ definition: "(method) class1.doStuff(): void", ran
verify.referenceGroups(r1, [{ definition: "(property) class1.propName: string", ranges: [r1, r5, r7] }]);
verify.referenceGroups(r2, [{ definition: "(method) interface1.doStuff(): void", ranges: [r2, r4, r6] }]);
verify.referenceGroups(r3, [{ definition: "(property) interface1.propName: string", ranges: [r3, r5, r7] }]);
verify.referenceGroups(r4, [
verify.referenceGroups([r4, r6], [
{ definition: "(method) class1.doStuff(): void", ranges: [r0] },
{ definition: "(method) interface1.doStuff(): void", ranges: [r2] },
{ definition: "(method) class2.doStuff(): void", ranges: [r4, r6] }
Expand All @@ -32,9 +32,3 @@ verify.referenceGroups([r5, r7], [
{ definition: "(property) interface1.propName: string", ranges: [r3] },
{ definition: "(property) class2.propName: string", ranges: [r5, r7] }
]);
verify.referenceGroups(r6, [
{ definition: "(method) class1.doStuff(): void", ranges: [r0] },
{ definition: "(method) interface1.doStuff(): void", ranges: [r2] },
{ definition: "(method) class2.doStuff(): void", ranges: [r4] },
{ definition: "(method) class2.doStuff(): void", ranges: [r6] }
]);
7 changes: 1 addition & 6 deletions tests/cases/fourslash/findAllRefsMappedType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
////declare const u: U;
////u.[|a|];

const ranges = test.ranges();
const [r0, r1, r2] = ranges;
verify.referenceGroups([r0, r1], [{ definition: "(property) T.a: number", ranges }]);
verify.referenceGroups(r2, [
{ definition: "(property) T.a: number", ranges: [r0, r1] },
{ definition: "(property) a: string", ranges: [r2] }]);
verify.singleReferenceGroup("(property) T.a: number");
5 changes: 1 addition & 4 deletions tests/cases/fourslash/findAllRefsOnDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,4 @@
const ranges = test.ranges();
const [r0, r1] = ranges;
verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]);
verify.referenceGroups(r1, [
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] },
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] },
]);
verify.referenceGroups(r1, [{ definition: "(method) Second.Test.start(): Second.Test", ranges }]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// <reference path='fourslash.ts' />

// @noLib: true

////interface A {
//// readonly [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number | string;
////}
////interface B extends A {
//// readonly [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number;
////}
////const a: A = { [|{| "isWriteAccess": true, "isDefinition": true |}x|]: 0 };
////const b: B = { [|{| "isWriteAccess": true, "isDefinition": true |}x|]: 0 };

const [r0, r1, r2, r3] = test.ranges();
verify.referenceGroups(r0, [
{ definition: "(property) A.x: string | number", ranges: [r0, r1, r2, r3] },
]);
verify.referenceGroups(r1, [
{ definition: "(property) A.x: string | number", ranges: [r0, r2] },
{ definition: "(property) B.x: number", ranges: [r1, r3] },
]);
verify.referenceGroups(r2, [
{ definition: "(property) A.x: string | number", ranges: [r0, r1, r3] },
{ definition: "(property) x: number", ranges: [r2] },
]);
verify.referenceGroups(r3, [
{ definition: "(property) A.x: string | number", ranges: [r0, r2] },
{ definition: "(property) B.x: number", ranges: [r1] },
{ definition: "(property) x: number", ranges: [r3] },
]);
3 changes: 1 addition & 2 deletions tests/cases/fourslash/findAllRefsRootSymbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ verify.referenceGroups(r0, [{ definition: "(property) I.x: {}", ranges: [r0, r3]
verify.referenceGroups(r1, [{ definition: "(property) J.x: {}", ranges: [r1, r3] }]);
verify.referenceGroups(r2, [{ definition: "(property) x: string", ranges: [r2, r3] }]);
verify.referenceGroups(r3, [
{ definition: "(property) I.x: {}", ranges: [r0] },
{ definition: "(property) I.x: {}", ranges: [r0, r3] },
{ definition: "(property) J.x: {}", ranges: [r1] },
{ definition: "(property) x: string", ranges: [r2] },
{ definition: "(property) x: string & {}", ranges: [r3] },
]);
6 changes: 1 addition & 5 deletions tests/cases/fourslash/findAllRefsThisKeyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,4 @@ verify.referenceGroups(g0, [{ definition: "(parameter) this: any", ranges: [g0,
verify.referenceGroups(g1, [{ definition: "this: any", ranges: [g0, g1] }]);
verify.singleReferenceGroup("this: typeof C", [x, y]);
verify.singleReferenceGroup("this: this", [constructor, method]);
verify.referenceGroups(propDef, [{ definition: "(property) this: number", ranges: [propDef, propUse] }]);
verify.referenceGroups(propUse, [
{ definition: "(property) this: number", ranges: [propDef] },
{ definition: "(property) this: number", ranges: [propUse] },
]);
verify.singleReferenceGroup("(property) this: number", [propDef, propUse]);
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,4 @@
////var x: Foo;
////x.[|_bar|];

const ranges = test.ranges();
const [r0, r1] = ranges;
verify.referenceGroups(r0, [{ definition: "(method) Foo._bar(): number", ranges }]);
verify.referenceGroups(r1, [
{ definition: "(method) Foo._bar(): number", ranges: [r0] },
{ definition: "(method) Foo._bar(): number", ranges: [r1] }
]);
verify.singleReferenceGroup("(method) Foo._bar(): number");
Loading

0 comments on commit 761f2cb

Please sign in to comment.