mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Determine if the function/var is local to function block
This commit is contained in:
parent
53d084e03d
commit
c450d8d392
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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");
|
||||
@ -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");
|
||||
goTo.marker('quickInfoC');
|
||||
verify.quickInfoIs("(property) x: (a: number) => void", undefined);
|
||||
@ -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);
|
||||
|
||||
20
tests/cases/fourslash/localFunction.ts
Normal file
20
tests/cases/fourslash/localFunction.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////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');
|
||||
@ -1,49 +0,0 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////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");
|
||||
Loading…
x
Reference in New Issue
Block a user