diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 4d91893df05..8ed2f185b9b 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1014,7 +1014,7 @@ module ts {
}
// if this is anonymous type break
- if (symbol.flags & SymbolFlags.TypeLiteral) {
+ if (symbol.flags & SymbolFlags.TypeLiteral || symbol.flags & SymbolFlags.ObjectLiteral) {
return;
}
diff --git a/src/services/services.ts b/src/services/services.ts
index 6aca2b4bb50..278895dfb33 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -1317,6 +1317,38 @@ module ts {
return displayPart("\n", SymbolDisplayPartKind.lineBreak);
}
+ function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
+ return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
+ }
+
+ function isLocalVariableOrFunction(symbol: Symbol) {
+ if (symbol.parent) {
+ return false; // This is exported symbol
+ }
+
+ return ts.forEach(symbol.declarations, declaration => {
+ // Function expressions are local
+ if (declaration.kind === SyntaxKind.FunctionExpression) {
+ return true;
+ }
+
+ if (declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration) {
+ return;
+ }
+
+ // If the parent is not sourceFile or module element it is local variable
+ for (var parent = declaration.parent; parent.kind !== SyntaxKind.FunctionBlock; parent = parent.parent) {
+ // Reached source file or module block
+ if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) {
+ return;
+ }
+ }
+
+ // parent is in function block
+ return true;
+ });
+ }
+
export function symbolPart(text: string, symbol: Symbol) {
return displayPart(text, displayPartKind(symbol), symbol);
@@ -1324,9 +1356,7 @@ module ts {
var flags = symbol.flags;
if (flags & SymbolFlags.Variable) {
- return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter
- ? SymbolDisplayPartKind.parameterName
- : SymbolDisplayPartKind.localName;
+ return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
}
else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; }
@@ -2534,27 +2564,35 @@ module ts {
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
+ var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags);
+ if (result === ScriptElementKind.unknown) {
+ if (flags & SymbolFlags.IndexSignature) return ScriptElementKind.indexSignatureElement;
+ if (flags & SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
+ if (flags & SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
+ if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
+ if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
+ }
+
+ return result;
+ }
+
+ function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags) {
if (flags & SymbolFlags.Variable) {
- if (ts.forEach(symbol.declarations, declaration => declaration.kind === SyntaxKind.Parameter)) {
+ if (isFirstDeclarationOfSymbolParameter(symbol)) {
return ScriptElementKind.parameterElement;
}
- return ScriptElementKind.variableElement;
+ return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
}
- if (flags & SymbolFlags.Function) return ScriptElementKind.functionElement;
+ if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
if (flags & SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement;
if (flags & SymbolFlags.Method) return ScriptElementKind.memberFunctionElement;
if (flags & SymbolFlags.Property) return ScriptElementKind.memberVariableElement;
- if (flags & SymbolFlags.IndexSignature) return ScriptElementKind.indexSignatureElement;
- if (flags & SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
- if (flags & SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
- if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
- if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
return ScriptElementKind.unknown;
}
-
+
function getTypeKind(type: Type): string {
var flags = type.getFlags();
@@ -2613,7 +2651,7 @@ module ts {
function getSymbolDisplayPartsofSymbol(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, typeResolver: TypeChecker): SymbolDisplayPart[] {
var displayParts: SymbolDisplayPart[] = [];
- var symbolFlags = typeResolver.getTargetSymbol(symbol).flags;
+ var symbolFlags = typeResolver.getRootSymbol(symbol).flags;
if (symbolFlags & SymbolFlags.Class) {
displayParts.push(keywordPart(SyntaxKind.ClassKeyword));
displayParts.push(spacePart());
@@ -2647,36 +2685,16 @@ module ts {
}
else {
//public static string FormatSymbolName(string name, string fullSymbolName, string kind, out bool useTypeName)
+ var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags);
var text: string;
- if (symbolFlags & SymbolFlags.Property) {
- text = "property";
- }
- else if (symbolFlags & SymbolFlags.EnumMember) {
+ if (symbolKind === ScriptElementKind.unknown) {
+ if (symbolFlags & SymbolFlags.EnumMember) {
text = "enum member";
}
- else if (symbolFlags & SymbolFlags.Function) {
- text = "function";
- }
- else if (symbolFlags & SymbolFlags.Variable) {
- if (ts.forEach(symbol.declarations, declaration => declaration.kind === SyntaxKind.Parameter)) {
- text = "parameter";
- }
- else {
- text = "var";
- }
- }
- else if (symbolFlags & SymbolFlags.Method) {
- text = "method";
- }
- else if (symbolFlags & SymbolFlags.Constructor) {
- text = "constructor";
- }
- else if (symbolFlags & SymbolFlags.GetAccessor) {
- text = "getter";
- }
- else if (symbolFlags & SymbolFlags.SetAccessor) {
- text = "setter";
- }
+ }
+ else {
+ text = symbolKind;
+ }
if (text || symbolFlags & SymbolFlags.Signature) {
addNewLineIfDisplayPartsExist();
diff --git a/tests/cases/fourslash/completionListInNamedFunctionExpression.ts b/tests/cases/fourslash/completionListInNamedFunctionExpression.ts
index 4e2ad4dec3a..6321018f5b5 100644
--- a/tests/cases/fourslash/completionListInNamedFunctionExpression.ts
+++ b/tests/cases/fourslash/completionListInNamedFunctionExpression.ts
@@ -24,9 +24,7 @@ goTo.marker("insideFunctionExpression");
verify.memberListContains("foo");
goTo.marker("referenceInsideFunctionExpression");
-verify.quickInfoIs("(function) foo(): number");
+verify.quickInfoIs("(local function) foo(): number");
goTo.marker("referenceInGlobalScope");
-verify.quickInfoIs("(function) foo(a: number): string");
-
-
+verify.quickInfoIs("(function) foo(a: number): string");
\ No newline at end of file
diff --git a/tests/cases/fourslash/functionProperty.ts b/tests/cases/fourslash/functionProperty.ts
index 4f089d95cf3..e9ffdcf2cdf 100644
--- a/tests/cases/fourslash/functionProperty.ts
+++ b/tests/cases/fourslash/functionProperty.ts
@@ -30,20 +30,20 @@ verify.currentSignatureHelpIs('x(a: number): void');
goTo.marker('signatureC');
verify.currentSignatureHelpIs('x(a: number): void');
-//goTo.marker('completionA');
-//verify.completionListContains("x", "(a: number): void");
+goTo.marker('completionA');
+verify.completionListContains("x", "(property) x: (a: number) => void");
-//goTo.marker('completionB');
-//verify.completionListContains("x", "(a: number) => void");
+goTo.marker('completionB');
+verify.completionListContains("x", "(property) x: (a: number) => void");
-//goTo.marker('completionC');
-//verify.completionListContains("x", "(a: number) => void");
+goTo.marker('completionC');
+verify.completionListContains("x", "(property) x: (a: number) => void");
-//goTo.marker('quickInfoA');
-//verify.quickInfoIs("(a: number): void", undefined, "x", "local function");
+goTo.marker('quickInfoA');
+verify.quickInfoIs("(property) x: (a: number) => void", undefined);
-//goTo.marker('quickInfoB');
-//verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
+goTo.marker('quickInfoB');
+verify.quickInfoIs("(property) x: (a: number) => void", undefined);
-//goTo.marker('quickInfoC');
-//verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
\ No newline at end of file
+goTo.marker('quickInfoC');
+verify.quickInfoIs("(property) x: (a: number) => void", undefined);
\ No newline at end of file
diff --git a/tests/cases/fourslash/genericFunctionWithGenericParams1.ts b/tests/cases/fourslash/genericFunctionWithGenericParams1.ts
index 10bce872f54..e57da708412 100644
--- a/tests/cases/fourslash/genericFunctionWithGenericParams1.ts
+++ b/tests/cases/fourslash/genericFunctionWithGenericParams1.ts
@@ -6,7 +6,4 @@
////};
goTo.marker();
-// TODO (local var)
-//verify.quickInfoIs('(local var) xx: T', null);
-verify.quickInfoIs('(var) xx: T', null);
-
+verify.quickInfoIs('(local var) xx: T', null);
diff --git a/tests/cases/fourslash/localFunction.ts b/tests/cases/fourslash/localFunction.ts
new file mode 100644
index 00000000000..d0227c83a8c
--- /dev/null
+++ b/tests/cases/fourslash/localFunction.ts
@@ -0,0 +1,20 @@
+///
+
+////function /*1*/foo() {
+//// function /*2*/bar2() {
+//// }
+//// var y = function /*3*/bar3() {
+//// }
+////}
+////var x = function /*4*/bar4() {
+////}
+
+goTo.marker("1");
+verify.quickInfoIs('(function) foo(): void');
+goTo.marker("2");
+debugger;
+verify.quickInfoIs('(local function) bar2(): void');
+goTo.marker("3");
+verify.quickInfoIs('(local function) bar3(): void');
+goTo.marker("4");
+verify.quickInfoIs('(local function) bar4(): void');
diff --git a/tests/cases/fourslash_old/functionProperty.ts b/tests/cases/fourslash_old/functionProperty.ts
deleted file mode 100644
index 4fb3ea52949..00000000000
--- a/tests/cases/fourslash_old/functionProperty.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-///
-
-////var a = {
-//// x(a: number) { }
-////};
-////
-////var b = {
-//// x: function (a: number) { }
-////};
-////
-////var c = {
-//// x: (a: number) => { }
-////};
-////a.x(/*signatureA*/1);
-////b.x(/*signatureB*/1);
-////c.x(/*signatureC*/1);
-////a./*completionA*/;
-////b./*completionB*/;
-////c./*completionC*/;
-////a./*quickInfoA*/x;
-////b./*quickInfoB*/x;
-////c./*quickInfoC*/x;
-
-goTo.marker('signatureA');
-verify.currentSignatureHelpIs('x(a: number): void');
-
-goTo.marker('signatureB');
-verify.currentSignatureHelpIs('x(a: number): void');
-
-goTo.marker('signatureC');
-verify.currentSignatureHelpIs('x(a: number): void');
-
-goTo.marker('completionA');
-verify.completionListContains("x", "(a: number): void");
-
-goTo.marker('completionB');
-verify.completionListContains("x", "(a: number) => void");
-
-goTo.marker('completionC');
-verify.completionListContains("x", "(a: number) => void");
-
-goTo.marker('quickInfoA');
-verify.quickInfoIs("(a: number): void", undefined, "x", "local function");
-
-goTo.marker('quickInfoB');
-verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
-
-goTo.marker('quickInfoC');
-verify.quickInfoIs("(a: number) => void", undefined, "x", "property");
\ No newline at end of file