Skip to content

Commit c450d8d

Browse files
committed
Determine if the function/var is local to function block
1 parent 53d084e commit c450d8d

File tree

7 files changed

+94
-110
lines changed

7 files changed

+94
-110
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,7 @@ module ts {
10141014
}
10151015

10161016
// if this is anonymous type break
1017-
if (symbol.flags & SymbolFlags.TypeLiteral) {
1017+
if (symbol.flags & SymbolFlags.TypeLiteral || symbol.flags & SymbolFlags.ObjectLiteral) {
10181018
return;
10191019
}
10201020

src/services/services.ts

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,16 +1317,46 @@ module ts {
13171317
return displayPart("\n", SymbolDisplayPartKind.lineBreak);
13181318
}
13191319

1320+
function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
1321+
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
1322+
}
1323+
1324+
function isLocalVariableOrFunction(symbol: Symbol) {
1325+
if (symbol.parent) {
1326+
return false; // This is exported symbol
1327+
}
1328+
1329+
return ts.forEach(symbol.declarations, declaration => {
1330+
// Function expressions are local
1331+
if (declaration.kind === SyntaxKind.FunctionExpression) {
1332+
return true;
1333+
}
1334+
1335+
if (declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration) {
1336+
return;
1337+
}
1338+
1339+
// If the parent is not sourceFile or module element it is local variable
1340+
for (var parent = declaration.parent; parent.kind !== SyntaxKind.FunctionBlock; parent = parent.parent) {
1341+
// Reached source file or module block
1342+
if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) {
1343+
return;
1344+
}
1345+
}
1346+
1347+
// parent is in function block
1348+
return true;
1349+
});
1350+
}
1351+
13201352
export function symbolPart(text: string, symbol: Symbol) {
13211353
return displayPart(text, displayPartKind(symbol), symbol);
13221354

13231355
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
13241356
var flags = symbol.flags;
13251357

13261358
if (flags & SymbolFlags.Variable) {
1327-
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter
1328-
? SymbolDisplayPartKind.parameterName
1329-
: SymbolDisplayPartKind.localName;
1359+
return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
13301360
}
13311361
else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; }
13321362
else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; }
@@ -2534,27 +2564,35 @@ module ts {
25342564
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
25352565
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
25362566
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
2567+
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags);
2568+
if (result === ScriptElementKind.unknown) {
2569+
if (flags & SymbolFlags.IndexSignature) return ScriptElementKind.indexSignatureElement;
2570+
if (flags & SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
2571+
if (flags & SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
2572+
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
2573+
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
2574+
}
2575+
2576+
return result;
2577+
}
2578+
2579+
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags) {
25372580
if (flags & SymbolFlags.Variable) {
2538-
if (ts.forEach(symbol.declarations, declaration => declaration.kind === SyntaxKind.Parameter)) {
2581+
if (isFirstDeclarationOfSymbolParameter(symbol)) {
25392582
return ScriptElementKind.parameterElement;
25402583
}
2541-
return ScriptElementKind.variableElement;
2584+
return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
25422585
}
2543-
if (flags & SymbolFlags.Function) return ScriptElementKind.functionElement;
2586+
if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
25442587
if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
25452588
if (flags & SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement;
25462589
if (flags & SymbolFlags.Method) return ScriptElementKind.memberFunctionElement;
25472590
if (flags & SymbolFlags.Property) return ScriptElementKind.memberVariableElement;
2548-
if (flags & SymbolFlags.IndexSignature) return ScriptElementKind.indexSignatureElement;
2549-
if (flags & SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
2550-
if (flags & SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
25512591
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
2552-
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
2553-
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
25542592

25552593
return ScriptElementKind.unknown;
25562594
}
2557-
2595+
25582596
function getTypeKind(type: Type): string {
25592597
var flags = type.getFlags();
25602598

@@ -2613,7 +2651,7 @@ module ts {
26132651

26142652
function getSymbolDisplayPartsofSymbol(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, typeResolver: TypeChecker): SymbolDisplayPart[] {
26152653
var displayParts: SymbolDisplayPart[] = [];
2616-
var symbolFlags = typeResolver.getTargetSymbol(symbol).flags;
2654+
var symbolFlags = typeResolver.getRootSymbol(symbol).flags;
26172655
if (symbolFlags & SymbolFlags.Class) {
26182656
displayParts.push(keywordPart(SyntaxKind.ClassKeyword));
26192657
displayParts.push(spacePart());
@@ -2647,36 +2685,16 @@ module ts {
26472685
}
26482686
else {
26492687
//public static string FormatSymbolName(string name, string fullSymbolName, string kind, out bool useTypeName)
2688+
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags);
26502689
var text: string;
2651-
if (symbolFlags & SymbolFlags.Property) {
2652-
text = "property";
2653-
}
2654-
else if (symbolFlags & SymbolFlags.EnumMember) {
2690+
if (symbolKind === ScriptElementKind.unknown) {
2691+
if (symbolFlags & SymbolFlags.EnumMember) {
26552692
text = "enum member";
26562693
}
2657-
else if (symbolFlags & SymbolFlags.Function) {
2658-
text = "function";
2659-
}
2660-
else if (symbolFlags & SymbolFlags.Variable) {
2661-
if (ts.forEach(symbol.declarations, declaration => declaration.kind === SyntaxKind.Parameter)) {
2662-
text = "parameter";
2663-
}
2664-
else {
2665-
text = "var";
2666-
}
2667-
}
2668-
else if (symbolFlags & SymbolFlags.Method) {
2669-
text = "method";
2670-
}
2671-
else if (symbolFlags & SymbolFlags.Constructor) {
2672-
text = "constructor";
2673-
}
2674-
else if (symbolFlags & SymbolFlags.GetAccessor) {
2675-
text = "getter";
2676-
}
2677-
else if (symbolFlags & SymbolFlags.SetAccessor) {
2678-
text = "setter";
2679-
}
2694+
}
2695+
else {
2696+
text = symbolKind;
2697+
}
26802698

26812699
if (text || symbolFlags & SymbolFlags.Signature) {
26822700
addNewLineIfDisplayPartsExist();

tests/cases/fourslash/completionListInNamedFunctionExpression.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ goTo.marker("insideFunctionExpression");
2424
verify.memberListContains("foo");
2525

2626
goTo.marker("referenceInsideFunctionExpression");
27-
verify.quickInfoIs("(function) foo(): number");
27+
verify.quickInfoIs("(local function) foo(): number");
2828

2929
goTo.marker("referenceInGlobalScope");
30-
verify.quickInfoIs("(function) foo(a: number): string");
31-
32-
30+
verify.quickInfoIs("(function) foo(a: number): string");

tests/cases/fourslash/functionProperty.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,20 @@ verify.currentSignatureHelpIs('x(a: number): void');
3030
goTo.marker('signatureC');
3131
verify.currentSignatureHelpIs('x(a: number): void');
3232

33-
//goTo.marker('completionA');
34-
//verify.completionListContains("x", "(a: number): void");
33+
goTo.marker('completionA');
34+
verify.completionListContains("x", "(property) x: (a: number) => void");
3535

36-
//goTo.marker('completionB');
37-
//verify.completionListContains("x", "(a: number) => void");
36+
goTo.marker('completionB');
37+
verify.completionListContains("x", "(property) x: (a: number) => void");
3838

39-
//goTo.marker('completionC');
40-
//verify.completionListContains("x", "(a: number) => void");
39+
goTo.marker('completionC');
40+
verify.completionListContains("x", "(property) x: (a: number) => void");
4141

42-
//goTo.marker('quickInfoA');
43-
//verify.quickInfoIs("(a: number): void", undefined, "x", "local function");
42+
goTo.marker('quickInfoA');
43+
verify.quickInfoIs("(property) x: (a: number) => void", undefined);
4444

45-
//goTo.marker('quickInfoB');
46-
//verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
45+
goTo.marker('quickInfoB');
46+
verify.quickInfoIs("(property) x: (a: number) => void", undefined);
4747

48-
//goTo.marker('quickInfoC');
49-
//verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
48+
goTo.marker('quickInfoC');
49+
verify.quickInfoIs("(property) x: (a: number) => void", undefined);

tests/cases/fourslash/genericFunctionWithGenericParams1.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,4 @@
66
////};
77

88
goTo.marker();
9-
// TODO (local var)
10-
//verify.quickInfoIs('(local var) xx: T', null);
11-
verify.quickInfoIs('(var) xx: T', null);
12-
9+
verify.quickInfoIs('(local var) xx: T', null);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////function /*1*/foo() {
4+
//// function /*2*/bar2() {
5+
//// }
6+
//// var y = function /*3*/bar3() {
7+
//// }
8+
////}
9+
////var x = function /*4*/bar4() {
10+
////}
11+
12+
goTo.marker("1");
13+
verify.quickInfoIs('(function) foo(): void');
14+
goTo.marker("2");
15+
debugger;
16+
verify.quickInfoIs('(local function) bar2(): void');
17+
goTo.marker("3");
18+
verify.quickInfoIs('(local function) bar3(): void');
19+
goTo.marker("4");
20+
verify.quickInfoIs('(local function) bar4(): void');

tests/cases/fourslash_old/functionProperty.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)