mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #726 from Microsoft/sigHelp
Signature help in the new compiler
This commit is contained in:
@@ -54,6 +54,8 @@ var servicesSources = [
|
||||
}).concat([
|
||||
"services.ts",
|
||||
"shims.ts",
|
||||
"signatureHelp.ts",
|
||||
"utilities.ts"
|
||||
].map(function (f) {
|
||||
return path.join(servicesDirectory, f);
|
||||
}));
|
||||
|
||||
+111
-62
@@ -91,6 +91,7 @@ module ts {
|
||||
getRootSymbol: getRootSymbol,
|
||||
getContextualType: getContextualType,
|
||||
getFullyQualifiedName: getFullyQualifiedName,
|
||||
getResolvedSignature: getResolvedSignature,
|
||||
getEnumMemberValue: getEnumMemberValue
|
||||
};
|
||||
|
||||
@@ -4330,55 +4331,26 @@ module ts {
|
||||
return unknownSignature;
|
||||
}
|
||||
|
||||
function isCandidateSignature(node: CallExpression, signature: Signature) {
|
||||
function signatureHasCorrectArity(node: CallExpression, signature: Signature): boolean {
|
||||
var args = node.arguments || emptyArray;
|
||||
return args.length >= signature.minArgumentCount &&
|
||||
var isCorrect = args.length >= signature.minArgumentCount &&
|
||||
(signature.hasRestParameter || args.length <= signature.parameters.length) &&
|
||||
(!node.typeArguments || signature.typeParameters && node.typeArguments.length === signature.typeParameters.length);
|
||||
}
|
||||
|
||||
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
|
||||
// A nit here is that we reorder only signatures that belong to the same symbol,
|
||||
// so order how inherited signatures are processed is still preserved.
|
||||
// interface A { (x: string): void }
|
||||
// interface B extends A { (x: 'foo'): string }
|
||||
// var b: B;
|
||||
// b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
|
||||
function collectCandidates(node: CallExpression, signatures: Signature[]): Signature[]{
|
||||
var result: Signature[] = [];
|
||||
var lastParent: Node;
|
||||
var lastSymbol: Symbol;
|
||||
var cutoffPos: number = 0;
|
||||
var pos: number;
|
||||
for (var i = 0; i < signatures.length; i++) {
|
||||
var signature = signatures[i];
|
||||
if (isCandidateSignature(node, signature)) {
|
||||
var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
|
||||
var parent = signature.declaration && signature.declaration.parent;
|
||||
if (!lastSymbol || symbol === lastSymbol) {
|
||||
if (lastParent && parent === lastParent) {
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
lastParent = parent;
|
||||
pos = cutoffPos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// current declaration belongs to a different symbol
|
||||
// set cutoffPos so re-orderings in the future won't change result set from 0 to cutoffPos
|
||||
pos = cutoffPos = result.length;
|
||||
lastParent = parent;
|
||||
}
|
||||
lastSymbol = symbol;
|
||||
|
||||
for (var j = result.length; j > pos; j--) {
|
||||
result[j] = result[j - 1];
|
||||
}
|
||||
result[pos] = signature;
|
||||
// For error recovery, since we have parsed OmittedExpressions for any extra commas
|
||||
// in the argument list, if we see any OmittedExpressions, just return true.
|
||||
// The reason this is ok is because omitted expressions here are syntactically
|
||||
// illegal, and will cause a parse error.
|
||||
// Note: It may be worth keeping the upper bound check on arity, but removing
|
||||
// the lower bound check if there are omitted expressions.
|
||||
if (!isCorrect) {
|
||||
// Technically this type assertion is not safe because args could be initialized to emptyArray
|
||||
// above.
|
||||
if ((<NodeArray<Node>>args).hasTrailingComma || forEach(args, arg => arg.kind === SyntaxKind.OmittedExpression)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return isCorrect;
|
||||
}
|
||||
|
||||
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
|
||||
@@ -4409,6 +4381,9 @@ module ts {
|
||||
var mapper = createInferenceMapper(context);
|
||||
// First infer from arguments that are not context sensitive
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (args[i].kind === SyntaxKind.OmittedExpression) {
|
||||
continue;
|
||||
}
|
||||
if (!excludeArgument || excludeArgument[i] === undefined) {
|
||||
var parameterType = getTypeAtPosition(signature, i);
|
||||
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
|
||||
@@ -4417,6 +4392,9 @@ module ts {
|
||||
// Next, infer from those context sensitive arguments that are no longer excluded
|
||||
if (excludeArgument) {
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (args[i].kind === SyntaxKind.OmittedExpression) {
|
||||
continue;
|
||||
}
|
||||
if (excludeArgument[i] === false) {
|
||||
var parameterType = getTypeAtPosition(signature, i);
|
||||
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
|
||||
@@ -4445,6 +4423,10 @@ module ts {
|
||||
if (node.arguments) {
|
||||
for (var i = 0; i < node.arguments.length; i++) {
|
||||
var arg = node.arguments[i];
|
||||
if (arg.kind === SyntaxKind.OmittedExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var paramType = getTypeAtPosition(signature, i);
|
||||
// String literals get string literal types unless we're reporting errors
|
||||
var argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ?
|
||||
@@ -4462,9 +4444,11 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function resolveCall(node: CallExpression, signatures: Signature[]): Signature {
|
||||
function resolveCall(node: CallExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
|
||||
forEach(node.typeArguments, checkSourceElement);
|
||||
var candidates = collectCandidates(node, signatures);
|
||||
var candidates = candidatesOutArray || [];
|
||||
// collectCandidates fills up the candidates array directly
|
||||
collectCandidates();
|
||||
if (!candidates.length) {
|
||||
error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
|
||||
return resolveErrorCall(node);
|
||||
@@ -4480,20 +4464,24 @@ module ts {
|
||||
var relation = candidates.length === 1 ? assignableRelation : subtypeRelation;
|
||||
while (true) {
|
||||
for (var i = 0; i < candidates.length; i++) {
|
||||
if (!signatureHasCorrectArity(node, candidates[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var candidate = candidates[i];
|
||||
if (candidate.typeParameters) {
|
||||
var candidateWithCorrectArity = candidates[i];
|
||||
if (candidateWithCorrectArity.typeParameters) {
|
||||
var typeArguments = node.typeArguments ?
|
||||
checkTypeArguments(candidate, node.typeArguments) :
|
||||
inferTypeArguments(candidate, args, excludeArgument);
|
||||
candidate = getSignatureInstantiation(candidate, typeArguments);
|
||||
checkTypeArguments(candidateWithCorrectArity, node.typeArguments) :
|
||||
inferTypeArguments(candidateWithCorrectArity, args, excludeArgument);
|
||||
candidateWithCorrectArity = getSignatureInstantiation(candidateWithCorrectArity, typeArguments);
|
||||
}
|
||||
if (!checkApplicableSignature(node, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
|
||||
if (!checkApplicableSignature(node, candidateWithCorrectArity, relation, excludeArgument, /*reportErrors*/ false)) {
|
||||
break;
|
||||
}
|
||||
var index = excludeArgument ? indexOf(excludeArgument, true) : -1;
|
||||
if (index < 0) {
|
||||
return candidate;
|
||||
return candidateWithCorrectArity;
|
||||
}
|
||||
excludeArgument[index] = false;
|
||||
}
|
||||
@@ -4503,17 +4491,70 @@ module ts {
|
||||
}
|
||||
relation = assignableRelation;
|
||||
}
|
||||
|
||||
// No signatures were applicable. Now report errors based on the last applicable signature with
|
||||
// no arguments excluded from assignability checks.
|
||||
checkApplicableSignature(node, candidate, relation, undefined, /*reportErrors*/ true);
|
||||
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
|
||||
// skip the checkApplicableSignature check.
|
||||
if (candidateWithCorrectArity) {
|
||||
checkApplicableSignature(node, candidateWithCorrectArity, relation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
return resolveErrorCall(node);
|
||||
|
||||
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
|
||||
// A nit here is that we reorder only signatures that belong to the same symbol,
|
||||
// so order how inherited signatures are processed is still preserved.
|
||||
// interface A { (x: string): void }
|
||||
// interface B extends A { (x: 'foo'): string }
|
||||
// var b: B;
|
||||
// b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
|
||||
function collectCandidates(): void {
|
||||
var result = candidates;
|
||||
var lastParent: Node;
|
||||
var lastSymbol: Symbol;
|
||||
var cutoffPos: number = 0;
|
||||
var pos: number;
|
||||
Debug.assert(!result.length);
|
||||
for (var i = 0; i < signatures.length; i++) {
|
||||
var signature = signatures[i];
|
||||
if (true) {
|
||||
var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
|
||||
var parent = signature.declaration && signature.declaration.parent;
|
||||
if (!lastSymbol || symbol === lastSymbol) {
|
||||
if (lastParent && parent === lastParent) {
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
lastParent = parent;
|
||||
pos = cutoffPos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// current declaration belongs to a different symbol
|
||||
// set cutoffPos so re-orderings in the future won't change result set from 0 to cutoffPos
|
||||
pos = cutoffPos = result.length;
|
||||
lastParent = parent;
|
||||
}
|
||||
lastSymbol = symbol;
|
||||
|
||||
for (var j = result.length; j > pos; j--) {
|
||||
result[j] = result[j - 1];
|
||||
}
|
||||
result[pos] = signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCallExpression(node: CallExpression): Signature {
|
||||
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
|
||||
if (node.func.kind === SyntaxKind.SuperKeyword) {
|
||||
var superType = checkSuperExpression(node.func);
|
||||
if (superType !== unknownType) {
|
||||
return resolveCall(node, getSignaturesOfType(superType, SignatureKind.Construct));
|
||||
return resolveCall(node, getSignaturesOfType(superType, SignatureKind.Construct), candidatesOutArray);
|
||||
}
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
@@ -4561,10 +4602,10 @@ module ts {
|
||||
}
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
return resolveCall(node, callSignatures);
|
||||
return resolveCall(node, callSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
function resolveNewExpression(node: NewExpression): Signature {
|
||||
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature {
|
||||
var expressionType = checkExpression(node.func);
|
||||
if (expressionType === unknownType) {
|
||||
// Another error has already been reported
|
||||
@@ -4599,7 +4640,7 @@ module ts {
|
||||
// that the user will not add any.
|
||||
var constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
|
||||
if (constructSignatures.length) {
|
||||
return resolveCall(node, constructSignatures);
|
||||
return resolveCall(node, constructSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
// If ConstructExpr's apparent type is an object type with no construct signatures but
|
||||
@@ -4608,7 +4649,7 @@ module ts {
|
||||
// operation is Any.
|
||||
var callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
|
||||
if (callSignatures.length) {
|
||||
var signature = resolveCall(node, callSignatures);
|
||||
var signature = resolveCall(node, callSignatures, candidatesOutArray);
|
||||
if (getReturnTypeOfSignature(signature) !== voidType) {
|
||||
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
|
||||
}
|
||||
@@ -4619,11 +4660,19 @@ module ts {
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
function getResolvedSignature(node: CallExpression): Signature {
|
||||
// candidatesOutArray is passed by signature help in the language service, and collectCandidates
|
||||
// must fill it up with the appropriate candidate signatures
|
||||
function getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedSignature) {
|
||||
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
|
||||
// However, it is possible that either candidatesOutArray was not passed in the first time,
|
||||
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
|
||||
// to correctly fill the candidatesOutArray.
|
||||
if (!links.resolvedSignature || candidatesOutArray) {
|
||||
links.resolvedSignature = anySignature;
|
||||
links.resolvedSignature = node.kind === SyntaxKind.CallExpression ? resolveCallExpression(node) : resolveNewExpression(node);
|
||||
links.resolvedSignature = node.kind === SyntaxKind.CallExpression
|
||||
? resolveCallExpression(node, candidatesOutArray)
|
||||
: resolveNewExpression(node, candidatesOutArray);
|
||||
}
|
||||
return links.resolvedSignature;
|
||||
}
|
||||
|
||||
+15
-1
@@ -11,7 +11,9 @@ module ts {
|
||||
var result: U;
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (result = callback(array[i])) break;
|
||||
if (result = callback(array[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -39,6 +41,18 @@ module ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
|
||||
var count = 0;
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (predicate(array[i])) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
if (array) {
|
||||
var result: T[] = [];
|
||||
|
||||
+41
-18
@@ -748,23 +748,46 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[], count?: number) {
|
||||
if (!(count >= 0)) count = nodes.length;
|
||||
if (nodes) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (i) write(", ");
|
||||
emit(nodes[i]);
|
||||
function emitTrailingCommaIfPresent(nodeList: NodeArray<Node>, isMultiline: boolean): void {
|
||||
if (nodeList.hasTrailingComma) {
|
||||
write(",");
|
||||
if (isMultiline) {
|
||||
writeLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitMultiLineList(nodes: Node[]) {
|
||||
function emitCommaList(nodes: NodeArray<Node>, includeTrailingComma: boolean, count?: number) {
|
||||
if (!(count >= 0)) {
|
||||
count = nodes.length;
|
||||
}
|
||||
if (nodes) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (i) {
|
||||
write(", ");
|
||||
}
|
||||
emit(nodes[i]);
|
||||
}
|
||||
|
||||
if (includeTrailingComma) {
|
||||
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitMultiLineList(nodes: NodeArray<Node>, includeTrailingComma: boolean) {
|
||||
if (nodes) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (i) write(",");
|
||||
if (i) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
emit(nodes[i]);
|
||||
}
|
||||
|
||||
if (includeTrailingComma) {
|
||||
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,14 +899,14 @@ module ts {
|
||||
if (node.flags & NodeFlags.MultiLine) {
|
||||
write("[");
|
||||
increaseIndent();
|
||||
emitMultiLineList(node.elements);
|
||||
emitMultiLineList(node.elements, /*includeTrailingComma*/ true);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("]");
|
||||
}
|
||||
else {
|
||||
write("[");
|
||||
emitCommaList(node.elements);
|
||||
emitCommaList(node.elements, /*includeTrailingComma*/ true);
|
||||
write("]");
|
||||
}
|
||||
}
|
||||
@@ -895,14 +918,14 @@ module ts {
|
||||
else if (node.flags & NodeFlags.MultiLine) {
|
||||
write("{");
|
||||
increaseIndent();
|
||||
emitMultiLineList(node.properties);
|
||||
emitMultiLineList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("}");
|
||||
}
|
||||
else {
|
||||
write("{ ");
|
||||
emitCommaList(node.properties);
|
||||
emitCommaList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
|
||||
write(" }");
|
||||
}
|
||||
}
|
||||
@@ -949,13 +972,13 @@ module ts {
|
||||
emitThis(node.func);
|
||||
if (node.arguments.length) {
|
||||
write(", ");
|
||||
emitCommaList(node.arguments);
|
||||
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
|
||||
}
|
||||
write(")");
|
||||
}
|
||||
else {
|
||||
write("(");
|
||||
emitCommaList(node.arguments);
|
||||
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
@@ -965,7 +988,7 @@ module ts {
|
||||
emit(node.func);
|
||||
if (node.arguments) {
|
||||
write("(");
|
||||
emitCommaList(node.arguments);
|
||||
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
@@ -1138,7 +1161,7 @@ module ts {
|
||||
if (node.declarations) {
|
||||
emitToken(SyntaxKind.VarKeyword, endPos);
|
||||
write(" ");
|
||||
emitCommaList(node.declarations);
|
||||
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
|
||||
}
|
||||
if (node.initializer) {
|
||||
emit(node.initializer);
|
||||
@@ -1286,7 +1309,7 @@ module ts {
|
||||
function emitVariableStatement(node: VariableStatement) {
|
||||
emitLeadingComments(node);
|
||||
if (!(node.flags & NodeFlags.Export)) write("var ");
|
||||
emitCommaList(node.declarations);
|
||||
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
|
||||
write(";");
|
||||
emitTrailingComments(node);
|
||||
}
|
||||
@@ -1395,7 +1418,7 @@ module ts {
|
||||
increaseIndent();
|
||||
write("(");
|
||||
if (node) {
|
||||
emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
|
||||
emitCommaList(node.parameters, /*includeTrailingComma*/ false, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
|
||||
}
|
||||
write(")");
|
||||
decreaseIndent();
|
||||
|
||||
+44
-24
@@ -628,12 +628,6 @@ module ts {
|
||||
Parameters, // Parameters in parameter list
|
||||
}
|
||||
|
||||
enum TrailingCommaBehavior {
|
||||
Disallow,
|
||||
Allow,
|
||||
Preserve
|
||||
}
|
||||
|
||||
// Tracks whether we nested (directly or indirectly) in a certain control block.
|
||||
// Used for validating break and continue statements.
|
||||
enum ControlBlockContext {
|
||||
@@ -1205,7 +1199,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Parses a comma-delimited list of elements
|
||||
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, trailingCommaBehavior: TrailingCommaBehavior): NodeArray<T> {
|
||||
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, allowTrailingComma: boolean): NodeArray<T> {
|
||||
var saveParsingContext = parsingContext;
|
||||
parsingContext |= 1 << kind;
|
||||
var result = <NodeArray<T>>[];
|
||||
@@ -1230,15 +1224,14 @@ module ts {
|
||||
else if (isListTerminator(kind)) {
|
||||
// Check if the last token was a comma.
|
||||
if (commaStart >= 0) {
|
||||
if (trailingCommaBehavior === TrailingCommaBehavior.Disallow) {
|
||||
if (!allowTrailingComma) {
|
||||
if (file.syntacticErrors.length === errorCountBeforeParsingList) {
|
||||
// Report a grammar error so we don't affect lookahead
|
||||
grammarErrorAtPos(commaStart, scanner.getStartPos() - commaStart, Diagnostics.Trailing_comma_not_allowed);
|
||||
}
|
||||
}
|
||||
else if (trailingCommaBehavior === TrailingCommaBehavior.Preserve) {
|
||||
result.push(<T>createNode(SyntaxKind.OmittedExpression));
|
||||
}
|
||||
// Always preserve a trailing comma by marking it on the NodeArray
|
||||
result.hasTrailingComma = true;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1273,7 +1266,7 @@ module ts {
|
||||
|
||||
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, startToken: SyntaxKind, endToken: SyntaxKind): NodeArray<T> {
|
||||
if (parseExpected(startToken)) {
|
||||
var result = parseDelimitedList(kind, parseElement, TrailingCommaBehavior.Disallow);
|
||||
var result = parseDelimitedList(kind, parseElement, /*allowTrailingComma*/ false);
|
||||
parseExpected(endToken);
|
||||
return result;
|
||||
}
|
||||
@@ -2309,7 +2302,11 @@ module ts {
|
||||
else {
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
}
|
||||
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
|
||||
// It is an error to have a trailing comma in an argument list. However, the checker
|
||||
// needs evidence of a trailing comma in order to give good results for signature help.
|
||||
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
|
||||
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
|
||||
parseArgumentExpression, /*allowTrailingComma*/ false);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
expr = finishNode(callExpr);
|
||||
continue;
|
||||
@@ -2378,15 +2375,33 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseAssignmentExpressionOrOmittedExpression(omittedExpressionDiagnostic: DiagnosticMessage): Expression {
|
||||
if (token === SyntaxKind.CommaToken) {
|
||||
if (omittedExpressionDiagnostic) {
|
||||
var errorStart = scanner.getTokenPos();
|
||||
var errorLength = scanner.getTextPos() - errorStart;
|
||||
grammarErrorAtPos(errorStart, errorLength, omittedExpressionDiagnostic);
|
||||
}
|
||||
return createNode(SyntaxKind.OmittedExpression);
|
||||
}
|
||||
|
||||
return parseAssignmentExpression();
|
||||
}
|
||||
|
||||
function parseArrayLiteralElement(): Expression {
|
||||
return token === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : parseAssignmentExpression();
|
||||
return parseAssignmentExpressionOrOmittedExpression(/*omittedExpressionDiagnostic*/ undefined);
|
||||
}
|
||||
|
||||
function parseArgumentExpression(): Expression {
|
||||
return parseAssignmentExpressionOrOmittedExpression(Diagnostics.Argument_expression_expected);
|
||||
}
|
||||
|
||||
function parseArrayLiteral(): ArrayLiteral {
|
||||
var node = <ArrayLiteral>createNode(SyntaxKind.ArrayLiteral);
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
|
||||
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArrayLiteralElement, TrailingCommaBehavior.Preserve);
|
||||
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers,
|
||||
parseArrayLiteralElement, /*allowTrailingComma*/ true);
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -2428,10 +2443,7 @@ module ts {
|
||||
node.flags |= NodeFlags.MultiLine;
|
||||
}
|
||||
|
||||
// ES3 itself does not accept a trailing comma in an object literal, however, we'd like to preserve it in ES5.
|
||||
var trailingCommaBehavior = languageVersion === ScriptTarget.ES3 ? TrailingCommaBehavior.Allow : TrailingCommaBehavior.Preserve;
|
||||
|
||||
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, trailingCommaBehavior);
|
||||
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, /*allowTrailingComma*/ true);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
|
||||
var seen: Map<SymbolFlags> = {};
|
||||
@@ -2520,7 +2532,11 @@ module ts {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
node.func = parseCallAndAccess(parsePrimaryExpression(), /* inNewExpression */ true);
|
||||
if (parseOptional(SyntaxKind.OpenParenToken) || token === SyntaxKind.LessThanToken && (node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen))) {
|
||||
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
|
||||
// It is an error to have a trailing comma in an argument list. However, the checker
|
||||
// needs evidence of a trailing comma in order to give good results for signature help.
|
||||
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
|
||||
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
|
||||
parseArgumentExpression, /*allowTrailingComma*/ false);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
}
|
||||
return finishNode(node);
|
||||
@@ -3089,7 +3105,8 @@ module ts {
|
||||
}
|
||||
|
||||
function parseVariableDeclarationList(flags: NodeFlags, noIn?: boolean): NodeArray<VariableDeclaration> {
|
||||
return parseDelimitedList(ParsingContext.VariableDeclarations, () => parseVariableDeclaration(flags, noIn), TrailingCommaBehavior.Disallow);
|
||||
return parseDelimitedList(ParsingContext.VariableDeclarations,
|
||||
() => parseVariableDeclaration(flags, noIn), /*allowTrailingComma*/ false);
|
||||
}
|
||||
|
||||
function parseVariableStatement(pos?: number, flags?: NodeFlags): VariableStatement {
|
||||
@@ -3488,7 +3505,8 @@ module ts {
|
||||
var implementsKeywordLength: number;
|
||||
if (parseOptional(SyntaxKind.ImplementsKeyword)) {
|
||||
implementsKeywordLength = scanner.getStartPos() - implementsKeywordStart;
|
||||
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
|
||||
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
|
||||
parseTypeReference, /*allowTrailingComma*/ false);
|
||||
}
|
||||
var errorCountBeforeClassBody = file.syntacticErrors.length;
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
@@ -3516,7 +3534,8 @@ module ts {
|
||||
var extendsKeywordLength: number;
|
||||
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
|
||||
extendsKeywordLength = scanner.getStartPos() - extendsKeywordStart;
|
||||
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
|
||||
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
|
||||
parseTypeReference, /*allowTrailingComma*/ false);
|
||||
}
|
||||
var errorCountBeforeInterfaceBody = file.syntacticErrors.length;
|
||||
node.members = parseTypeLiteral().members;
|
||||
@@ -3580,7 +3599,8 @@ module ts {
|
||||
parseExpected(SyntaxKind.EnumKeyword);
|
||||
node.name = parseIdentifier();
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
node.members = parseDelimitedList(ParsingContext.EnumMembers, parseAndCheckEnumMember, TrailingCommaBehavior.Allow);
|
||||
node.members = parseDelimitedList(ParsingContext.EnumMembers,
|
||||
parseAndCheckEnumMember, /*allowTrailingComma*/ true);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -261,7 +261,9 @@ module ts {
|
||||
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
|
||||
}
|
||||
|
||||
export interface NodeArray<T> extends Array<T>, TextRange { }
|
||||
export interface NodeArray<T> extends Array<T>, TextRange {
|
||||
hasTrailingComma?: boolean;
|
||||
}
|
||||
|
||||
export interface Identifier extends Node {
|
||||
text: string; // Text of identifier (with escapes converted to characters)
|
||||
@@ -648,6 +650,7 @@ module ts {
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
getRootSymbol(symbol: Symbol): Symbol;
|
||||
getContextualType(node: Node): Type;
|
||||
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
|
||||
|
||||
// Returns the constant value of this enum member, or 'undefined' if the enum member has a
|
||||
// computed value.
|
||||
@@ -935,7 +938,7 @@ module ts {
|
||||
resolvedReturnType: Type; // Resolved return type
|
||||
minArgumentCount: number; // Number of non-optional parameters
|
||||
hasRestParameter: boolean; // True if last parameter is rest parameter
|
||||
hasStringLiterals: boolean; // True if instantiated
|
||||
hasStringLiterals: boolean; // True if specialized
|
||||
target?: Signature; // Instantiation target
|
||||
mapper?: TypeMapper; // Instantiation mapper
|
||||
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
|
||||
|
||||
@@ -819,14 +819,14 @@ module FourSlash {
|
||||
public verifyCurrentSignatureHelpIs(expected: string) {
|
||||
this.taoInvalidReason = 'verifyCurrentSignatureHelpIs NYI';
|
||||
|
||||
var help = this.getActiveSignatureHelp();
|
||||
var help = this.getActiveSignatureHelpItem();
|
||||
assert.equal(help.prefix + help.parameters.map(p => p.display).join(help.separator) + help.suffix, expected);
|
||||
}
|
||||
|
||||
public verifyCurrentParameterIsVariable(isVariable: boolean) {
|
||||
this.taoInvalidReason = 'verifyCurrentParameterIsVariable NYI';
|
||||
|
||||
var signature = this.getActiveSignatureHelp();
|
||||
var signature = this.getActiveSignatureHelpItem();
|
||||
assert.isNotNull(signature);
|
||||
assert.equal(isVariable, signature.isVariadic);
|
||||
}
|
||||
@@ -842,7 +842,7 @@ module FourSlash {
|
||||
public verifyCurrentParameterSpanIs(parameter: string) {
|
||||
this.taoInvalidReason = 'verifyCurrentParameterSpanIs NYI';
|
||||
|
||||
var activeSignature = this.getActiveSignatureHelp();
|
||||
var activeSignature = this.getActiveSignatureHelpItem();
|
||||
var activeParameter = this.getActiveParameter();
|
||||
assert.equal(activeParameter.display, parameter);
|
||||
}
|
||||
@@ -858,19 +858,19 @@ module FourSlash {
|
||||
public verifyCurrentSignatureHelpParameterCount(expectedCount: number) {
|
||||
this.taoInvalidReason = 'verifyCurrentSignatureHelpParameterCount NYI';
|
||||
|
||||
assert.equal(this.getActiveSignatureHelp().parameters.length, expectedCount);
|
||||
assert.equal(this.getActiveSignatureHelpItem().parameters.length, expectedCount);
|
||||
}
|
||||
|
||||
public verifyCurrentSignatureHelpTypeParameterCount(expectedCount: number) {
|
||||
this.taoInvalidReason = 'verifyCurrentSignatureHelpTypeParameterCount NYI';
|
||||
|
||||
// assert.equal(this.getActiveSignatureHelp().typeParameters.length, expectedCount);
|
||||
// assert.equal(this.getActiveSignatureHelpItem().typeParameters.length, expectedCount);
|
||||
}
|
||||
|
||||
public verifyCurrentSignatureHelpDocComment(docComment: string) {
|
||||
this.taoInvalidReason = 'verifyCurrentSignatureHelpDocComment NYI';
|
||||
|
||||
var actualDocComment = this.getActiveSignatureHelp().documentation;
|
||||
var actualDocComment = this.getActiveSignatureHelpItem().documentation;
|
||||
assert.equal(actualDocComment, docComment);
|
||||
}
|
||||
|
||||
@@ -941,7 +941,7 @@ module FourSlash {
|
||||
// return help.formal;
|
||||
//}
|
||||
|
||||
private getActiveSignatureHelp() {
|
||||
private getActiveSignatureHelpItem() {
|
||||
var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
|
||||
|
||||
// If the signature hasn't been narrowed down yet (e.g. no parameters have yet been entered),
|
||||
@@ -953,14 +953,13 @@ module FourSlash {
|
||||
}
|
||||
|
||||
private getActiveParameter(): ts.SignatureHelpParameter {
|
||||
var currentSig = this.getActiveSignatureHelp();
|
||||
var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
|
||||
|
||||
var item = help.items[help.selectedItemIndex];
|
||||
var state = this.languageService.getSignatureHelpCurrentArgumentState(this.activeFile.fileName, this.currentCaretPosition, help.applicableSpan.start());
|
||||
|
||||
// Same logic as in getActiveSignatureHelp - this value might be -1 until a parameter value actually gets typed
|
||||
var currentParam = state === null ? 0 : state.argumentIndex;
|
||||
var currentParam = state === undefined ? 0 : state.argumentIndex;
|
||||
return item.parameters[currentParam];
|
||||
}
|
||||
|
||||
@@ -1083,7 +1082,7 @@ module FourSlash {
|
||||
}
|
||||
|
||||
public printCurrentSignatureHelp() {
|
||||
var sigHelp = this.getActiveSignatureHelp();
|
||||
var sigHelp = this.getActiveSignatureHelpItem();
|
||||
Harness.IO.log(JSON.stringify(sigHelp));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
module ts.formatting {
|
||||
export module SmartIndenter {
|
||||
|
||||
export function getIndentation(position: number, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
|
||||
if (position > sourceFile.text.length) {
|
||||
return 0; // past EOF
|
||||
@@ -108,8 +107,10 @@ module ts.formatting {
|
||||
*/
|
||||
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
|
||||
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
|
||||
var itemInfo = findPrecedingListItem(commaToken);
|
||||
return deriveActualIndentationFromList(itemInfo.list.getChildren(), itemInfo.listItemIndex, sourceFile, options);
|
||||
var commaItemInfo = findListItemInfo(commaToken);
|
||||
Debug.assert(commaItemInfo.listItemIndex > 0);
|
||||
// The item we're interested in is right before the comma
|
||||
return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -167,27 +168,6 @@ module ts.formatting {
|
||||
return sourceFile.getLineAndCharacterFromPosition(n.getStart(sourceFile));
|
||||
}
|
||||
|
||||
function findPrecedingListItem(commaToken: Node): { listItemIndex: number; list: Node } {
|
||||
// CommaToken node is synthetic and thus will be stored in SyntaxList, however parent of the CommaToken points to the container of the SyntaxList skipping the list.
|
||||
// In order to find the preceding list item we first need to locate SyntaxList itself and then search for the position of CommaToken
|
||||
var syntaxList = forEach(commaToken.parent.getChildren(), c => {
|
||||
// find syntax list that covers the span of CommaToken
|
||||
if (c.kind == SyntaxKind.SyntaxList && c.pos <= commaToken.end && c.end >= commaToken.end) {
|
||||
return c;
|
||||
}
|
||||
});
|
||||
Debug.assert(syntaxList);
|
||||
|
||||
var children = syntaxList.getChildren();
|
||||
var commaIndex = indexOf(children, commaToken);
|
||||
Debug.assert(commaIndex !== -1 && commaIndex !== 0);
|
||||
|
||||
return {
|
||||
listItemIndex: commaIndex - 1,
|
||||
list: syntaxList
|
||||
};
|
||||
}
|
||||
|
||||
function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean {
|
||||
return candidate.end > position || !isCompletedNode(candidate, sourceFile);
|
||||
}
|
||||
@@ -288,112 +268,6 @@ module ts.formatting {
|
||||
return column;
|
||||
}
|
||||
|
||||
function findNextToken(previousToken: Node, parent: Node): Node {
|
||||
return find(parent);
|
||||
|
||||
function find(n: Node): Node {
|
||||
if (isToken(n) && n.pos === previousToken.end) {
|
||||
// this is token that starts at the end of previous token - return it
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
var shouldDiveInChildNode =
|
||||
// previous token is enclosed somewhere in the child
|
||||
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
|
||||
// previous token ends exactly at the beginning of child
|
||||
(child.pos === previousToken.end);
|
||||
|
||||
if (shouldDiveInChildNode && nodeHasTokens(child)) {
|
||||
return find(child);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
|
||||
return find(sourceFile);
|
||||
|
||||
function findRightmostToken(n: Node): Node {
|
||||
if (isToken(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && findRightmostToken(candidate);
|
||||
|
||||
}
|
||||
|
||||
function find(n: Node): Node {
|
||||
if (isToken(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
if (nodeHasTokens(child)) {
|
||||
if (position < child.end) {
|
||||
if (child.getStart(sourceFile) >= position) {
|
||||
// actual start of the node is past the position - previous token should be at the end of previous child
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
|
||||
return candidate && findRightmostToken(candidate)
|
||||
}
|
||||
else {
|
||||
// candidate should be in this node
|
||||
return find(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.assert(n.kind === SyntaxKind.SourceFile);
|
||||
|
||||
// Here we know that none of child token nodes embrace the position,
|
||||
// the only known case is when position is at the end of the file.
|
||||
// Try to find the rightmost token in the file without filtering.
|
||||
// Namely we are skipping the check: 'position < node.end'
|
||||
if (children.length) {
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && findRightmostToken(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
|
||||
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
|
||||
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
|
||||
if (nodeHasTokens(children[i])) {
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if node is something that can contain tokens (except EOF) - filters out EOF tokens, Missing\Omitted expressions, empty SyntaxLists and expression statements that wrap any of listed nodes.
|
||||
*/
|
||||
function nodeHasTokens(n: Node): boolean {
|
||||
if (n.kind === SyntaxKind.ExpressionStatement) {
|
||||
return nodeHasTokens((<ExpressionStatement>n).expression);
|
||||
}
|
||||
|
||||
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SyntaxList is already realized so getChildCount should be fast and non-expensive
|
||||
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
|
||||
}
|
||||
|
||||
function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
|
||||
function nodeContentIsIndented(parent: Node, child: Node): boolean {
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
|
||||
+32
-41
@@ -9,6 +9,8 @@
|
||||
/// <reference path='getScriptLexicalStructureWalker.ts' />
|
||||
/// <reference path='breakpoints.ts' />
|
||||
/// <reference path='indentation.ts' />
|
||||
/// <reference path='signatureHelp.ts' />
|
||||
/// <reference path='utilities.ts' />
|
||||
/// <reference path='formatting\formatting.ts' />
|
||||
/// <reference path='formatting\smartIndenter.ts' />
|
||||
|
||||
@@ -201,7 +203,7 @@ module ts {
|
||||
}
|
||||
|
||||
public getFirstToken(sourceFile?: SourceFile): Node {
|
||||
var children = this.getChildren(sourceFile);
|
||||
var children = this.getChildren();
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
if (child.kind < SyntaxKind.Missing) return child;
|
||||
@@ -1129,7 +1131,7 @@ module ts {
|
||||
|
||||
export class OperationCanceledException { }
|
||||
|
||||
class CancellationTokenObject {
|
||||
export class CancellationTokenObject {
|
||||
|
||||
public static None: CancellationTokenObject = new CancellationTokenObject(null)
|
||||
|
||||
@@ -2250,40 +2252,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the token whose text contains the position, or the containing node. */
|
||||
function getNodeAtPosition(sourceFile: SourceFile, position: number) {
|
||||
var current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that has this
|
||||
for (var i = 0, n = current.getChildCount(); i < n; i++) {
|
||||
var child = current.getChildAt(i);
|
||||
if (child.getStart() <= position && position < child.getEnd()) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get a token that contains the position. This is guaranteed to return a token, the position can be in the
|
||||
* leading trivia or within the token text.
|
||||
*/
|
||||
function getTokenAtPosition(sourceFile: SourceFile, position: number) {
|
||||
var current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that has this
|
||||
for (var i = 0, n = current.getChildCount(); i < n; i++) {
|
||||
var child = current.getChildAt(i);
|
||||
if (child.getFullStart() <= position && position < child.getEnd()) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
function getContainerNode(node: Node): Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
@@ -2546,7 +2514,7 @@ module ts {
|
||||
result.push(getDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2747,7 +2715,7 @@ module ts {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shouldHighlightNextKeyword) {
|
||||
result.push(new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(elseKeyword.getStart(), ifKeyword.end), /* isWriteAccess */ false));
|
||||
i++; // skip the next keyword
|
||||
@@ -3754,7 +3722,30 @@ module ts {
|
||||
|
||||
// Reset writer back to undefined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput
|
||||
writer = undefined;
|
||||
return emitOutput;
|
||||
return emitOutput;
|
||||
}
|
||||
|
||||
// Signature help
|
||||
/**
|
||||
* This is a semantic operation.
|
||||
*/
|
||||
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
|
||||
synchronizeHostData();
|
||||
|
||||
fileName = TypeScript.switchToForwardSlashes(fileName);
|
||||
var sourceFile = getSourceFile(fileName);
|
||||
|
||||
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a syntactic operation
|
||||
*/
|
||||
function getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): SignatureHelpState {
|
||||
fileName = TypeScript.switchToForwardSlashes(fileName);
|
||||
var sourceFile = getCurrentSourceFile(fileName);
|
||||
|
||||
return SignatureHelp.getSignatureHelpCurrentArgumentState(sourceFile, position, applicableSpanStart);
|
||||
}
|
||||
|
||||
/// Syntactic features
|
||||
@@ -4353,9 +4344,9 @@ module ts {
|
||||
getCompletionsAtPosition: getCompletionsAtPosition,
|
||||
getCompletionEntryDetails: getCompletionEntryDetails,
|
||||
getTypeAtPosition: getTypeAtPosition,
|
||||
getSignatureHelpItems: getSignatureHelpItems,
|
||||
getSignatureHelpCurrentArgumentState: getSignatureHelpCurrentArgumentState,
|
||||
getQuickInfoAtPosition: getQuickInfoAtPosition,
|
||||
getSignatureHelpItems: (filename, position): SignatureHelpItems => null,
|
||||
getSignatureHelpCurrentArgumentState: (fileName, position, applicableSpanStart): SignatureHelpState => null,
|
||||
getDefinitionAtPosition: getDefinitionAtPosition,
|
||||
getReferencesAtPosition: getReferencesAtPosition,
|
||||
getOccurrencesAtPosition: getOccurrencesAtPosition,
|
||||
|
||||
@@ -599,8 +599,8 @@ module ts {
|
||||
return this.forwardJSONCall(
|
||||
"getSignatureHelpCurrentArgumentState('" + fileName + "', " + position + ", " + applicableSpanStart + ")",
|
||||
() => {
|
||||
var signatureInfo = this.languageService.getSignatureHelpItems(fileName, position);
|
||||
return signatureInfo;
|
||||
var signatureHelpState = this.languageService.getSignatureHelpCurrentArgumentState(fileName, position, applicableSpanStart);
|
||||
return signatureHelpState;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
///<reference path='services.ts' />
|
||||
|
||||
module ts.SignatureHelp {
|
||||
|
||||
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
|
||||
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
|
||||
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
|
||||
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
|
||||
// looking up the type. The method will also keep track of the parameter index inside the expression.
|
||||
//public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
|
||||
// var token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
|
||||
|
||||
// if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
|
||||
// // We are in the wrong generic list. bail out
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// var stack = 0;
|
||||
// var argumentIndex = 0;
|
||||
|
||||
// whileLoop:
|
||||
// while (token) {
|
||||
// switch (token.kind()) {
|
||||
// case TypeScript.SyntaxKind.LessThanToken:
|
||||
// if (stack === 0) {
|
||||
// // Found the beginning of the generic argument expression
|
||||
// var lessThanToken = token;
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
// if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
|
||||
// break whileLoop;
|
||||
// }
|
||||
|
||||
// // Found the name, return the data
|
||||
// return {
|
||||
// genericIdentifer: token,
|
||||
// lessThanToken: lessThanToken,
|
||||
// argumentIndex: argumentIndex
|
||||
// };
|
||||
// }
|
||||
// else if (stack < 0) {
|
||||
// // Seen one too many less than tokens, bail out
|
||||
// break whileLoop;
|
||||
// }
|
||||
// else {
|
||||
// stack--;
|
||||
// }
|
||||
|
||||
// break;
|
||||
|
||||
// case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
||||
// stack++;
|
||||
|
||||
// // Intentaion fall through
|
||||
// case TypeScript.SyntaxKind.GreaterThanToken:
|
||||
// stack++;
|
||||
// break;
|
||||
|
||||
// case TypeScript.SyntaxKind.CommaToken:
|
||||
// if (stack == 0) {
|
||||
// argumentIndex++;
|
||||
// }
|
||||
|
||||
// break;
|
||||
|
||||
// case TypeScript.SyntaxKind.CloseBraceToken:
|
||||
// // This can be object type, skip untill we find the matching open brace token
|
||||
// var unmatchedOpenBraceTokens = 0;
|
||||
|
||||
// // Skip untill the matching open brace token
|
||||
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
|
||||
// if (!token) {
|
||||
// // No matching token was found. bail out
|
||||
// break whileLoop;
|
||||
// }
|
||||
|
||||
// break;
|
||||
|
||||
// case TypeScript.SyntaxKind.EqualsGreaterThanToken:
|
||||
// // This can be a function type or a constructor type. In either case, we want to skip the function defintion
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
|
||||
// if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
|
||||
// // Skip untill the matching open paren token
|
||||
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
|
||||
|
||||
// if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
|
||||
// // Another generic type argument list, skip it\
|
||||
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
|
||||
// }
|
||||
|
||||
// if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
|
||||
// // In case this was a constructor type, skip the new keyword
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
// }
|
||||
|
||||
// if (!token) {
|
||||
// // No matching token was found. bail out
|
||||
// break whileLoop;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// // This is not a funtion type. exit the main loop
|
||||
// break whileLoop;
|
||||
// }
|
||||
|
||||
// break;
|
||||
|
||||
// case TypeScript.SyntaxKind.IdentifierName:
|
||||
// case TypeScript.SyntaxKind.AnyKeyword:
|
||||
// case TypeScript.SyntaxKind.NumberKeyword:
|
||||
// case TypeScript.SyntaxKind.StringKeyword:
|
||||
// case TypeScript.SyntaxKind.VoidKeyword:
|
||||
// case TypeScript.SyntaxKind.BooleanKeyword:
|
||||
// case TypeScript.SyntaxKind.DotToken:
|
||||
// case TypeScript.SyntaxKind.OpenBracketToken:
|
||||
// case TypeScript.SyntaxKind.CloseBracketToken:
|
||||
// // Valid tokens in a type name. Skip.
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// break whileLoop;
|
||||
// }
|
||||
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
|
||||
// if (!token || token.kind() !== tokenKind) {
|
||||
// throw TypeScript.Errors.invalidOperation();
|
||||
// }
|
||||
|
||||
// // Skip the current token
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
|
||||
// var stack = 0;
|
||||
|
||||
// while (token) {
|
||||
// if (token.kind() === matchingTokenKind) {
|
||||
// if (stack === 0) {
|
||||
// // Found the matching token, return
|
||||
// return token;
|
||||
// }
|
||||
// else if (stack < 0) {
|
||||
// // tokens overlapped.. bail out.
|
||||
// break;
|
||||
// }
|
||||
// else {
|
||||
// stack--;
|
||||
// }
|
||||
// }
|
||||
// else if (token.kind() === tokenKind) {
|
||||
// stack++;
|
||||
// }
|
||||
|
||||
// // Move back
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
// }
|
||||
|
||||
// // Did not find matching token
|
||||
// return null;
|
||||
//}
|
||||
var emptyArray: any[] = [];
|
||||
|
||||
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
|
||||
// Decide whether to show signature help
|
||||
var startingToken = findTokenOnLeftOfPosition(sourceFile, position);
|
||||
if (!startingToken) {
|
||||
// We are at the beginning of the file
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var argumentList = getContainingArgumentList(startingToken);
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
// Semantic filtering of signature help
|
||||
if (!argumentList) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var call = <CallExpression>argumentList.parent;
|
||||
var candidates = <Signature[]>[];
|
||||
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (!candidates.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return createSignatureHelpItems(candidates, resolvedSignature, argumentList);
|
||||
|
||||
/**
|
||||
* If node is an argument, returns its index in the argument list.
|
||||
* If not, returns -1.
|
||||
*/
|
||||
function getImmediatelyContainingArgumentList(node: Node): Node {
|
||||
if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// There are 3 cases to handle:
|
||||
// 1. The token introduces a list, and should begin a sig help session
|
||||
// 2. The token is either not associated with a list, or ends a list, so the session should end
|
||||
// 3. The token is buried inside a list, and should give sig help
|
||||
//
|
||||
// The following are examples of each:
|
||||
//
|
||||
// Case 1:
|
||||
// foo<$T, U>($a, b) -> The token introduces a list, and should begin a sig help session
|
||||
// Case 2:
|
||||
// fo$o<T, U>$(a, b)$ -> The token is either not associated with a list, or ends a list, so the session should end
|
||||
// Case 3:
|
||||
// foo<T$, U$>(a$, $b$) -> The token is buried inside a list, and should give sig help
|
||||
var parent = <CallExpression>node.parent;
|
||||
// Find out if 'node' is an argument, a type argument, or neither
|
||||
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
|
||||
// Find the list that starts right *after* the < or ( token
|
||||
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
|
||||
Debug.assert(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.GreaterThanToken
|
||||
|| node.kind === SyntaxKind.CloseParenToken
|
||||
|| node === parent.func) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return findContainingList(node);
|
||||
}
|
||||
|
||||
function getContainingArgumentList(node: Node): Node {
|
||||
for (var n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
|
||||
if (n.kind === SyntaxKind.FunctionBlock) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var argumentList = getImmediatelyContainingArgumentList(n);
|
||||
if (argumentList) {
|
||||
return argumentList;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Handle generic call with incomplete syntax
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListOrTypeArgumentList: Node): SignatureHelpItems {
|
||||
var items = map(candidates, candidateSignature => {
|
||||
var parameters = candidateSignature.parameters;
|
||||
var parameterHelpItems = parameters.length === 0 ? emptyArray : map(parameters, p => {
|
||||
var display = p.name;
|
||||
if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) {
|
||||
display = "..." + display;
|
||||
}
|
||||
var isOptional = !!(p.valueDeclaration.flags & NodeFlags.QuestionMark);
|
||||
if (isOptional) {
|
||||
display += "?";
|
||||
}
|
||||
display += ": " + typeInfoResolver.typeToString(typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
|
||||
return new SignatureHelpParameter(p.name, "", display, isOptional);
|
||||
});
|
||||
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
|
||||
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
|
||||
var signatureName = callTargetSymbol ? typeInfoResolver.symbolToString(callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : "";
|
||||
var prefix = signatureName;
|
||||
// TODO(jfreeman): Constraints?
|
||||
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
|
||||
prefix += "<" + map(candidateSignature.typeParameters, tp => tp.symbol.name).join(", ") + ">";
|
||||
}
|
||||
prefix += "(";
|
||||
var suffix = "): " + typeInfoResolver.typeToString(candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
|
||||
return new SignatureHelpItem(candidateSignature.hasRestParameter, prefix, suffix, ", ", parameterHelpItems, "");
|
||||
});
|
||||
var selectedItemIndex = candidates.indexOf(bestSignature);
|
||||
if (selectedItemIndex < 0) {
|
||||
selectedItemIndex = 0;
|
||||
}
|
||||
|
||||
// We use full start and skip trivia on the end because we want to include trivia on
|
||||
// both sides. For example,
|
||||
//
|
||||
// foo( /*comment */ a, b, c /*comment*/ )
|
||||
// | |
|
||||
//
|
||||
// The applicable span is from the first bar to the second bar (inclusive,
|
||||
// but not including parentheses)
|
||||
var applicableSpanStart = argumentListOrTypeArgumentList.getFullStart();
|
||||
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false);
|
||||
var applicableSpan = new TypeScript.TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
|
||||
return new SignatureHelpItems(items, applicableSpan, selectedItemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
export function getSignatureHelpCurrentArgumentState(sourceFile: SourceFile, position: number, applicableSpanStart: number): SignatureHelpState {
|
||||
var tokenPrecedingSpanStart = findPrecedingToken(applicableSpanStart, sourceFile);
|
||||
if (!tokenPrecedingSpanStart) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (tokenPrecedingSpanStart.kind !== SyntaxKind.OpenParenToken && tokenPrecedingSpanStart.kind !== SyntaxKind.LessThanToken) {
|
||||
// The span start must have moved backward in the file (for example if the open paren was backspaced)
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var tokenPrecedingCurrentPosition = findPrecedingToken(position, sourceFile);
|
||||
var call = <CallExpression>tokenPrecedingSpanStart.parent;
|
||||
Debug.assert(call.kind === SyntaxKind.CallExpression || call.kind === SyntaxKind.NewExpression, "wrong call kind " + SyntaxKind[call.kind]);
|
||||
if (tokenPrecedingCurrentPosition.kind === SyntaxKind.CloseParenToken || tokenPrecedingCurrentPosition.kind === SyntaxKind.GreaterThanToken) {
|
||||
if (tokenPrecedingCurrentPosition.parent === call) {
|
||||
// This call expression is complete. Stop signature help.
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var argumentListOrTypeArgumentList = getChildListThatStartsWithOpenerToken(call, tokenPrecedingSpanStart, sourceFile);
|
||||
// Debug.assert(argumentListOrTypeArgumentList.getChildCount() === 0 || argumentListOrTypeArgumentList.getChildCount() % 2 === 1, "Even number of children");
|
||||
|
||||
// The call might be finished, but incorrectly. Check if we are still within the bounds of the call
|
||||
if (position > skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var numberOfCommas = countWhere(argumentListOrTypeArgumentList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
|
||||
var argumentCount = numberOfCommas + 1;
|
||||
if (argumentCount <= 1) {
|
||||
return new SignatureHelpState(/*argumentIndex*/ 0, argumentCount);
|
||||
}
|
||||
|
||||
var indexOfNodeContainingPosition = findListItemIndexContainingPosition(argumentListOrTypeArgumentList, position);
|
||||
|
||||
// indexOfNodeContainingPosition checks that position is between pos and end of each child, so it is
|
||||
// possible that we are to the right of all children. Assume that we are still within
|
||||
// the applicable span and that we are typing the last argument
|
||||
// Alternatively, we could be in range of one of the arguments, in which case we need to divide
|
||||
// by 2 to exclude commas. Use bit shifting in order to take the floor of the division.
|
||||
var argumentIndex = indexOfNodeContainingPosition < 0 ? argumentCount - 1 : indexOfNodeContainingPosition >> 1;
|
||||
return new SignatureHelpState(argumentIndex, argumentCount);
|
||||
}
|
||||
|
||||
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
|
||||
var children = parent.getChildren(sourceFile);
|
||||
var indexOfOpenerToken = children.indexOf(openerToken);
|
||||
return children[indexOfOpenerToken + 1];
|
||||
}
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
|
||||
// See LICENSE.txt in the project root for complete license information.
|
||||
|
||||
///<reference path='references.ts' />
|
||||
|
||||
module TypeScript.Services {
|
||||
|
||||
export interface IPartiallyWrittenTypeArgumentListInformation {
|
||||
genericIdentifer: TypeScript.ISyntaxToken;
|
||||
lessThanToken: TypeScript.ISyntaxToken;
|
||||
argumentIndex: number;
|
||||
}
|
||||
|
||||
export interface IExpressionWithArgumentListSyntax extends IExpressionSyntax {
|
||||
expression: IExpressionSyntax;
|
||||
argumentList: ArgumentListSyntax;
|
||||
}
|
||||
|
||||
export class SignatureInfoHelpers {
|
||||
|
||||
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
|
||||
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
|
||||
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
|
||||
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
|
||||
// looking up the type. The method will also keep track of the parameter index inside the expression.
|
||||
public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): IPartiallyWrittenTypeArgumentListInformation {
|
||||
var token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
|
||||
|
||||
if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
|
||||
// We are in the wrong generic list. bail out
|
||||
return null;
|
||||
}
|
||||
|
||||
var stack = 0;
|
||||
var argumentIndex = 0;
|
||||
|
||||
whileLoop:
|
||||
while (token) {
|
||||
switch (token.kind()) {
|
||||
case TypeScript.SyntaxKind.LessThanToken:
|
||||
if (stack === 0) {
|
||||
// Found the beginning of the generic argument expression
|
||||
var lessThanToken = token;
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
|
||||
break whileLoop;
|
||||
}
|
||||
|
||||
// Found the name, return the data
|
||||
return {
|
||||
genericIdentifer: token,
|
||||
lessThanToken: lessThanToken,
|
||||
argumentIndex: argumentIndex
|
||||
};
|
||||
}
|
||||
else if (stack < 0) {
|
||||
// Seen one too many less than tokens, bail out
|
||||
break whileLoop;
|
||||
}
|
||||
else {
|
||||
stack--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
||||
stack++;
|
||||
|
||||
// Intentaion fall through
|
||||
case TypeScript.SyntaxKind.GreaterThanToken:
|
||||
stack++;
|
||||
break;
|
||||
|
||||
case TypeScript.SyntaxKind.CommaToken:
|
||||
if (stack == 0) {
|
||||
argumentIndex++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TypeScript.SyntaxKind.CloseBraceToken:
|
||||
// This can be object type, skip untill we find the matching open brace token
|
||||
var unmatchedOpenBraceTokens = 0;
|
||||
|
||||
// Skip untill the matching open brace token
|
||||
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
|
||||
if (!token) {
|
||||
// No matching token was found. bail out
|
||||
break whileLoop;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TypeScript.SyntaxKind.EqualsGreaterThanToken:
|
||||
// This can be a function type or a constructor type. In either case, we want to skip the function defintion
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
|
||||
if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
|
||||
// Skip untill the matching open paren token
|
||||
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
|
||||
|
||||
if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
|
||||
// Another generic type argument list, skip it\
|
||||
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
|
||||
}
|
||||
|
||||
if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
|
||||
// In case this was a constructor type, skip the new keyword
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
// No matching token was found. bail out
|
||||
break whileLoop;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This is not a funtion type. exit the main loop
|
||||
break whileLoop;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TypeScript.SyntaxKind.IdentifierName:
|
||||
case TypeScript.SyntaxKind.AnyKeyword:
|
||||
case TypeScript.SyntaxKind.NumberKeyword:
|
||||
case TypeScript.SyntaxKind.StringKeyword:
|
||||
case TypeScript.SyntaxKind.VoidKeyword:
|
||||
case TypeScript.SyntaxKind.BooleanKeyword:
|
||||
case TypeScript.SyntaxKind.DotToken:
|
||||
case TypeScript.SyntaxKind.OpenBracketToken:
|
||||
case TypeScript.SyntaxKind.CloseBracketToken:
|
||||
// Valid tokens in a type name. Skip.
|
||||
break;
|
||||
|
||||
default:
|
||||
break whileLoop;
|
||||
}
|
||||
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static getSignatureInfoFromSignatureSymbol(symbol: TypeScript.PullSymbol, signatures: TypeScript.PullSignatureSymbol[], enclosingScopeSymbol: TypeScript.PullSymbol, compilerState: LanguageServiceCompiler) {
|
||||
var signatureGroup: FormalSignatureItemInfo[] = [];
|
||||
|
||||
var hasOverloads = signatures.length > 1;
|
||||
|
||||
for (var i = 0, n = signatures.length; i < n; i++) {
|
||||
var signature = signatures[i];
|
||||
|
||||
// filter out the definition signature if there are overloads
|
||||
if (hasOverloads && signature.isDefinition()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var signatureGroupInfo = new FormalSignatureItemInfo();
|
||||
var paramIndexInfo: number[] = [];
|
||||
var functionName = signature.getScopedNameEx(enclosingScopeSymbol).toString();
|
||||
if (!functionName && (!symbol.isType() || (<TypeScript.PullTypeSymbol>symbol).isNamedTypeSymbol())) {
|
||||
functionName = symbol.getScopedNameEx(enclosingScopeSymbol).toString();
|
||||
}
|
||||
|
||||
var signatureMemberName = signature.getSignatureTypeNameEx(functionName, /*shortform*/ false, /*brackets*/ false, enclosingScopeSymbol, /*getParamMarkerInfo*/ true, /*getTypeParameterMarkerInfo*/ true);
|
||||
signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(signatureMemberName, paramIndexInfo);
|
||||
signatureGroupInfo.docComment = signature.docComments();
|
||||
|
||||
var parameterMarkerIndex = 0;
|
||||
|
||||
if (signature.isGeneric()) {
|
||||
var typeParameters = signature.getTypeParameters();
|
||||
for (var j = 0, m = typeParameters.length; j < m; j++) {
|
||||
var typeParameter = typeParameters[j];
|
||||
var signatureTypeParameterInfo = new FormalTypeParameterInfo();
|
||||
signatureTypeParameterInfo.name = typeParameter.getDisplayName();
|
||||
signatureTypeParameterInfo.docComment = typeParameter.docComments();
|
||||
signatureTypeParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
|
||||
signatureTypeParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
|
||||
parameterMarkerIndex++;
|
||||
signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
|
||||
}
|
||||
}
|
||||
|
||||
var parameters = signature.parameters;
|
||||
for (var j = 0, m = parameters.length; j < m; j++) {
|
||||
var parameter = parameters[j];
|
||||
var signatureParameterInfo = new FormalParameterInfo();
|
||||
signatureParameterInfo.isVariable = signature.hasVarArgs && (j === parameters.length - 1);
|
||||
signatureParameterInfo.name = parameter.getDisplayName();
|
||||
signatureParameterInfo.docComment = parameter.docComments();
|
||||
signatureParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
|
||||
signatureParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
|
||||
parameterMarkerIndex++;
|
||||
signatureGroupInfo.parameters.push(signatureParameterInfo);
|
||||
}
|
||||
|
||||
signatureGroup.push(signatureGroupInfo);
|
||||
}
|
||||
|
||||
return signatureGroup;
|
||||
}
|
||||
|
||||
public static getSignatureInfoFromGenericSymbol(symbol: TypeScript.PullSymbol, enclosingScopeSymbol: TypeScript.PullSymbol, compilerState: LanguageServiceCompiler) {
|
||||
var signatureGroupInfo = new FormalSignatureItemInfo();
|
||||
|
||||
var paramIndexInfo: number[] = [];
|
||||
var symbolName = symbol.getScopedNameEx(enclosingScopeSymbol, /*skipTypeParametersInName*/ false, /*useConstaintInName*/ true, /*getPrettyTypeName*/ false, /*getTypeParamMarkerInfo*/ true);
|
||||
|
||||
signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(symbolName, paramIndexInfo);
|
||||
signatureGroupInfo.docComment = symbol.docComments();
|
||||
|
||||
var typeSymbol = symbol.type;
|
||||
|
||||
var typeParameters = typeSymbol.getTypeParameters();
|
||||
for (var i = 0, n = typeParameters.length; i < n; i++) {
|
||||
var typeParameter = typeParameters[i];
|
||||
var signatureTypeParameterInfo = new FormalTypeParameterInfo();
|
||||
signatureTypeParameterInfo.name = typeParameter.getDisplayName();
|
||||
signatureTypeParameterInfo.docComment = typeParameter.docComments();
|
||||
signatureTypeParameterInfo.minChar = paramIndexInfo[2 * i];
|
||||
signatureTypeParameterInfo.limChar = paramIndexInfo[2 * i + 1];
|
||||
signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
|
||||
}
|
||||
|
||||
return [signatureGroupInfo];
|
||||
}
|
||||
|
||||
public static getActualSignatureInfoFromCallExpression(ast: IExpressionWithArgumentListSyntax, caretPosition: number, typeParameterInformation: IPartiallyWrittenTypeArgumentListInformation): ActualSignatureInfo {
|
||||
if (!ast) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = new ActualSignatureInfo();
|
||||
|
||||
// The expression is not guaranteed to be complete, we need to populate the min and lim with the most accurate information we have about
|
||||
// type argument and argument lists
|
||||
var parameterMinChar = caretPosition;
|
||||
var parameterLimChar = caretPosition;
|
||||
|
||||
if (ast.argumentList.typeArgumentList) {
|
||||
parameterMinChar = Math.min(start(ast.argumentList.typeArgumentList));
|
||||
parameterLimChar = Math.max(Math.max(start(ast.argumentList.typeArgumentList), end(ast.argumentList.typeArgumentList) + trailingTriviaWidth(ast.argumentList.typeArgumentList)));
|
||||
}
|
||||
|
||||
if (ast.argumentList.arguments) {
|
||||
parameterMinChar = Math.min(parameterMinChar, end(ast.argumentList.openParenToken));
|
||||
parameterLimChar = Math.max(parameterLimChar,
|
||||
ast.argumentList.closeParenToken.fullWidth() > 0 ? start(ast.argumentList.closeParenToken) : fullEnd(ast.argumentList));
|
||||
}
|
||||
|
||||
result.parameterMinChar = parameterMinChar;
|
||||
result.parameterLimChar = parameterLimChar;
|
||||
result.currentParameterIsTypeParameter = false;
|
||||
result.currentParameter = -1;
|
||||
|
||||
if (typeParameterInformation) {
|
||||
result.currentParameterIsTypeParameter = true;
|
||||
result.currentParameter = typeParameterInformation.argumentIndex;
|
||||
}
|
||||
else if (ast.argumentList.arguments && ast.argumentList.arguments.length > 0) {
|
||||
result.currentParameter = 0;
|
||||
for (var index = 0; index < ast.argumentList.arguments.length; index++) {
|
||||
if (caretPosition > end(ast.argumentList.arguments[index]) + lastToken(ast.argumentList.arguments[index]).trailingTriviaWidth()) {
|
||||
result.currentParameter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getActualSignatureInfoFromPartiallyWritenGenericExpression(caretPosition: number, typeParameterInformation: IPartiallyWrittenTypeArgumentListInformation): ActualSignatureInfo {
|
||||
var result = new ActualSignatureInfo();
|
||||
|
||||
result.parameterMinChar = start(typeParameterInformation.lessThanToken);
|
||||
result.parameterLimChar = Math.max(fullEnd(typeParameterInformation.lessThanToken), caretPosition);
|
||||
result.currentParameterIsTypeParameter = true;
|
||||
result.currentParameter = typeParameterInformation.argumentIndex;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static isSignatureHelpBlocker(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
|
||||
// We shouldn't be getting a possition that is outside the file because
|
||||
// isEntirelyInsideComment can't handle when the position is out of bounds,
|
||||
// callers should be fixed, however we should be resiliant to bad inputs
|
||||
// so we return true (this position is a blocker for getting signature help)
|
||||
if (position < 0 || position > fullWidth(sourceUnit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return TypeScript.Syntax.isEntirelyInsideComment(sourceUnit, position);
|
||||
}
|
||||
|
||||
public static isTargetOfObjectCreationExpression(positionedToken: TypeScript.ISyntaxToken): boolean {
|
||||
var positionedParent = TypeScript.Syntax.getAncestorOfKind(positionedToken, TypeScript.SyntaxKind.ObjectCreationExpression);
|
||||
if (positionedParent) {
|
||||
var objectCreationExpression = <TypeScript.ObjectCreationExpressionSyntax> positionedParent;
|
||||
var expressionRelativeStart = objectCreationExpression.newKeyword.fullWidth();
|
||||
var tokenRelativeStart = positionedToken.fullStart() - fullStart(positionedParent);
|
||||
return tokenRelativeStart >= expressionRelativeStart &&
|
||||
tokenRelativeStart <= (expressionRelativeStart + fullWidth(objectCreationExpression.expression));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
|
||||
if (!token || token.kind() !== tokenKind) {
|
||||
throw TypeScript.Errors.invalidOperation();
|
||||
}
|
||||
|
||||
// Skip the current token
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
|
||||
var stack = 0;
|
||||
|
||||
while (token) {
|
||||
if (token.kind() === matchingTokenKind) {
|
||||
if (stack === 0) {
|
||||
// Found the matching token, return
|
||||
return token;
|
||||
}
|
||||
else if (stack < 0) {
|
||||
// tokens overlapped.. bail out.
|
||||
break;
|
||||
}
|
||||
else {
|
||||
stack--;
|
||||
}
|
||||
}
|
||||
else if (token.kind() === tokenKind) {
|
||||
stack++;
|
||||
}
|
||||
|
||||
// Move back
|
||||
token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
}
|
||||
|
||||
// Did not find matching token
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
// These utilities are common to multiple language service features.
|
||||
module ts {
|
||||
export interface ListItemInfo {
|
||||
listItemIndex: number;
|
||||
list: Node;
|
||||
}
|
||||
|
||||
export function findListItemInfo(node: Node): ListItemInfo {
|
||||
var syntaxList = findContainingList(node);
|
||||
var children = syntaxList.getChildren();
|
||||
var index = indexOf(children, node);
|
||||
|
||||
return {
|
||||
listItemIndex: index,
|
||||
list: syntaxList
|
||||
};
|
||||
}
|
||||
|
||||
export function findContainingList(node: Node): Node {
|
||||
// The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will
|
||||
// be parented by the container of the SyntaxList, not the SyntaxList itself.
|
||||
// In order to find the list item index, we first need to locate SyntaxList itself and then search
|
||||
// for the position of the relevant node (or comma).
|
||||
var syntaxList = forEach(node.parent.getChildren(), c => {
|
||||
// find syntax list that covers the span of the node
|
||||
if (c.kind == SyntaxKind.SyntaxList && c.pos <= node.pos && c.end >= node.end) {
|
||||
return c;
|
||||
}
|
||||
});
|
||||
|
||||
return syntaxList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the start position of each child, but excludes the end.
|
||||
*/
|
||||
export function findListItemIndexContainingPosition(list: Node, position: number): number {
|
||||
Debug.assert(list.kind === SyntaxKind.SyntaxList);
|
||||
var children = list.getChildren();
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].pos <= position && children[i].end > position) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Get a token that contains the position. This is guaranteed to return a token, the position can be in the
|
||||
* leading trivia or within the token text.
|
||||
*/
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number) {
|
||||
var current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that has this
|
||||
for (var i = 0, n = current.getChildCount(); i < n; i++) {
|
||||
var child = current.getChildAt(i);
|
||||
if (child.getFullStart() <= position && position < child.getEnd()) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the token whose text contains the position, or the containing node. */
|
||||
export function getNodeAtPosition(sourceFile: SourceFile, position: number) {
|
||||
var current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that has this
|
||||
for (var i = 0, n = current.getChildCount(); i < n; i++) {
|
||||
var child = current.getChildAt(i);
|
||||
if (child.getStart() <= position && position < child.getEnd()) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The token on the left of the position is the token that strictly includes the position
|
||||
* or sits to the left of the cursor if it is on a boundary. For example
|
||||
*
|
||||
* fo|o -> will return foo
|
||||
* foo <comment> |bar -> will return foo
|
||||
*
|
||||
*/
|
||||
export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node {
|
||||
// Ideally, getTokenAtPosition should return a token. However, it is currently
|
||||
// broken, so we do a check to make sure the result was indeed a token.
|
||||
var tokenAtPosition = getTokenAtPosition(file, position);
|
||||
if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
|
||||
return tokenAtPosition;
|
||||
}
|
||||
|
||||
return findPrecedingToken(position, file);
|
||||
}
|
||||
|
||||
export function findNextToken(previousToken: Node, parent: Node): Node {
|
||||
return find(parent);
|
||||
|
||||
function find(n: Node): Node {
|
||||
if (isToken(n) && n.pos === previousToken.end) {
|
||||
// this is token that starts at the end of previous token - return it
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
var shouldDiveInChildNode =
|
||||
// previous token is enclosed somewhere in the child
|
||||
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
|
||||
// previous token ends exactly at the beginning of child
|
||||
(child.pos === previousToken.end);
|
||||
|
||||
if (shouldDiveInChildNode && nodeHasTokens(child)) {
|
||||
return find(child);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
|
||||
return find(sourceFile);
|
||||
|
||||
function findRightmostToken(n: Node): Node {
|
||||
if (isToken(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && findRightmostToken(candidate);
|
||||
|
||||
}
|
||||
|
||||
function find(n: Node): Node {
|
||||
if (isToken(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
if (nodeHasTokens(child)) {
|
||||
if (position < child.end) {
|
||||
if (child.getStart(sourceFile) >= position) {
|
||||
// actual start of the node is past the position - previous token should be at the end of previous child
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
|
||||
return candidate && findRightmostToken(candidate)
|
||||
}
|
||||
else {
|
||||
// candidate should be in this node
|
||||
return find(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.assert(n.kind === SyntaxKind.SourceFile);
|
||||
|
||||
// Here we know that none of child token nodes embrace the position,
|
||||
// the only known case is when position is at the end of the file.
|
||||
// Try to find the rightmost token in the file without filtering.
|
||||
// Namely we are skipping the check: 'position < node.end'
|
||||
if (children.length) {
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && findRightmostToken(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
|
||||
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
|
||||
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
|
||||
if (nodeHasTokens(children[i])) {
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nodeHasTokens(n: Node): boolean {
|
||||
if (n.kind === SyntaxKind.ExpressionStatement) {
|
||||
return nodeHasTokens((<ExpressionStatement>n).expression);
|
||||
}
|
||||
|
||||
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SyntaxList is already realized so getChildCount should be fast and non-expensive
|
||||
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
|
||||
}
|
||||
|
||||
function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ new (<any>A());
|
||||
// parentheses should be omitted
|
||||
// literals
|
||||
{ a: 0 };
|
||||
[1, 3, ];
|
||||
[1, 3,];
|
||||
"string";
|
||||
23.0;
|
||||
/regexp/g;
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
[{},]
|
||||
|
||||
//// [emptyExpr.js]
|
||||
[{}, ];
|
||||
[{},];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [1,1,];
|
||||
|
||||
//// [parserArrayLiteralExpression10.js]
|
||||
var v = [1, 1, ];
|
||||
var v = [1, 1,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [,,1,1,,1,,1,1,,1,];
|
||||
|
||||
//// [parserArrayLiteralExpression15.js]
|
||||
var v = [, , 1, 1, , 1, , 1, 1, , 1, ];
|
||||
var v = [, , 1, 1, , 1, , 1, 1, , 1,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [,];
|
||||
|
||||
//// [parserArrayLiteralExpression2.js]
|
||||
var v = [, ];
|
||||
var v = [,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [,,];
|
||||
|
||||
//// [parserArrayLiteralExpression3.js]
|
||||
var v = [, , ];
|
||||
var v = [, ,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [,,,];
|
||||
|
||||
//// [parserArrayLiteralExpression4.js]
|
||||
var v = [, , , ];
|
||||
var v = [, , ,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [1,];
|
||||
|
||||
//// [parserArrayLiteralExpression7.js]
|
||||
var v = [1, ];
|
||||
var v = [1,];
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var v = [,1,];
|
||||
|
||||
//// [parserArrayLiteralExpression8.js]
|
||||
var v = [, 1, ];
|
||||
var v = [, 1,];
|
||||
|
||||
@@ -17,7 +17,7 @@ var arrTest = (function () {
|
||||
};
|
||||
arrTest.prototype.callTest = function () {
|
||||
// these two should give the same error
|
||||
this.test([1, 2, "hi", 5, ]);
|
||||
this.test([1, 2, "hi", 5,]);
|
||||
this.test([1, 2, "hi", 5]);
|
||||
};
|
||||
return arrTest;
|
||||
|
||||
@@ -18,8 +18,8 @@ var o2 = { a: 1, b: 2 };
|
||||
var o3 = { a: 1 };
|
||||
var o4 = {};
|
||||
var a1 = [1, 2];
|
||||
var a2 = [1, 2, ];
|
||||
var a3 = [1, ];
|
||||
var a2 = [1, 2,];
|
||||
var a3 = [1,];
|
||||
var a4 = [];
|
||||
var a5 = [1, , ];
|
||||
var a6 = [, , ];
|
||||
var a5 = [1, ,];
|
||||
var a6 = [, ,];
|
||||
|
||||
@@ -14,12 +14,12 @@ var a6 = [, , ];
|
||||
|
||||
//// [trailingCommasES5.js]
|
||||
var o1 = { a: 1, b: 2 };
|
||||
var o2 = { a: 1, b: 2, };
|
||||
var o3 = { a: 1, };
|
||||
var o2 = { a: 1, b: 2, };
|
||||
var o3 = { a: 1, };
|
||||
var o4 = {};
|
||||
var a1 = [1, 2];
|
||||
var a2 = [1, 2, ];
|
||||
var a3 = [1, ];
|
||||
var a2 = [1, 2,];
|
||||
var a3 = [1,];
|
||||
var a4 = [];
|
||||
var a5 = [1, , ];
|
||||
var a6 = [, , ];
|
||||
var a5 = [1, ,];
|
||||
var a6 = [, ,];
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function /*11*/m2f(x: number) { };
|
||||
////module m2f { export interface I { foo(): void } }
|
||||
////var x: m2f./*1*/
|
||||
////var r/*2*/ = m2f/*3*/;
|
||||
|
||||
//goTo.marker('11');
|
||||
//verify.quickInfoIs('(x: number): void');
|
||||
|
||||
//goTo.marker('1');
|
||||
//verify.completionListContains('I');
|
||||
|
||||
//edit.insert('I.');
|
||||
//verify.not.completionListContains('foo');
|
||||
//edit.backspace(1);
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs('typeof m2f');
|
||||
|
||||
goTo.marker('3');
|
||||
edit.insert('(');
|
||||
verify.currentSignatureHelpIs('m2f(x: number): void');
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function m2g() { };
|
||||
////module m2g { export class C { foo(x: number) { } } }
|
||||
////var x: m2g./*1*/;
|
||||
////var r/*2*/ = m2g/*3*/;
|
||||
|
||||
//goTo.marker('1');
|
||||
//verify.completionListContains('C');
|
||||
|
||||
//edit.insert('C.');
|
||||
//verify.not.completionListContains('foo');
|
||||
//edit.backspace(1);
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs("typeof m2g", undefined, "r", "var");
|
||||
|
||||
goTo.marker('3');
|
||||
edit.insert('(');
|
||||
verify.currentSignatureHelpIs('m2g(): void');
|
||||
@@ -0,0 +1,34 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////declare class m3f { foo(x: number): void }
|
||||
////module m3f { export interface I { foo(): void } }
|
||||
////var x: m3f./*1*/
|
||||
////var r/*4*/ = new /*2*/m3f(/*3*/);
|
||||
////r./*5*/
|
||||
////var r2: m3f.I = r;
|
||||
////r2./*6*/
|
||||
|
||||
//goTo.marker('1');
|
||||
//verify.completionListContains('I');
|
||||
|
||||
//verify.not.completionListContains('foo');
|
||||
//edit.insert('I;');
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.completionListContains('m3f');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('m3f(): m3f');
|
||||
|
||||
//goTo.marker('4');
|
||||
//verify.quickInfoIs('m3f');
|
||||
|
||||
//goTo.marker('5');
|
||||
//verify.completionListContains('foo');
|
||||
//edit.insert('foo(1)');
|
||||
|
||||
goTo.marker('6');
|
||||
//verify.completionListContains('foo');
|
||||
edit.insert('foo(');
|
||||
// verify.currentSignatureHelpIs('foo(): void');
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface C {
|
||||
//// (): number;
|
||||
////}
|
||||
////var c: C;
|
||||
////c(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentSignatureHelpIs('c(): number');
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class C {
|
||||
//// public foo(x: string);
|
||||
//// public foo(x: number);
|
||||
//// public foo(x: any) { return x; }
|
||||
////}
|
||||
|
||||
////interface I extends C {
|
||||
//// other(x: any): any;
|
||||
////}
|
||||
|
||||
////var i: I;
|
||||
////i.foo(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentParameterSpanIs('x: string');
|
||||
@@ -0,0 +1,87 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: externalModuleWithExportAssignment_file0.ts
|
||||
////module m2 {
|
||||
//// export interface connectModule {
|
||||
//// (res, req, next): void;
|
||||
//// }
|
||||
//// export interface connectExport {
|
||||
//// use: (mod: connectModule) => connectExport;
|
||||
//// listen: (port: number) => void;
|
||||
//// }
|
||||
////}
|
||||
////var m2: {
|
||||
//// (): m2.connectExport;
|
||||
//// test1: m2.connectModule;
|
||||
//// test2(): m2.connectModule;
|
||||
////};
|
||||
////export = m2;
|
||||
|
||||
// @Filename: externalModuleWithExportAssignment_file1.ts
|
||||
////import /*1*/a1 = require("externalModuleWithExportAssignment_file0");
|
||||
////export var /*2*/a = a1;
|
||||
////a./*3*/test1(/*4*/null, null, null);
|
||||
////var /*6*/r1 = a.test2(/*5*/);
|
||||
////var /*8*/r2 = a(/*7*/);
|
||||
////a1./*9*/test1(/*10*/null, null, null);
|
||||
////var /*12*/r3 = a1.test2(/*11*/);
|
||||
////var /*14*/r4 = a1(/*13*/);
|
||||
////var v1: a1./*15*/connectExport;
|
||||
|
||||
//goTo.file("externalModuleWithExportAssignment_file1.ts");
|
||||
//goTo.marker('1');
|
||||
//verify.quickInfoIs("a1");
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs("{ test1: a1.connectModule; test2(): a1.connectModule; (): a1.connectExport; }", undefined, "a", "var");
|
||||
|
||||
//goTo.marker('3');
|
||||
//verify.quickInfoIs("(res: any, req: any, next: any): void", undefined, "a1.connectModule", "function");
|
||||
//verify.completionListContains("test1", "a1.connectModule", undefined, "test1", "property");
|
||||
//verify.completionListContains("test2", "(): a1.connectModule", undefined, "test2", "method");
|
||||
//verify.not.completionListContains("connectModule");
|
||||
//verify.not.completionListContains("connectExport");
|
||||
|
||||
goTo.marker('4');
|
||||
verify.currentSignatureHelpIs("test1(res: any, req: any, next: any): void");
|
||||
|
||||
goTo.marker('5');
|
||||
verify.currentSignatureHelpIs("test2(): a1.connectModule");
|
||||
|
||||
//goTo.marker('6');
|
||||
//verify.quickInfoIs("a1.connectModule", undefined, "r1", "var");
|
||||
|
||||
goTo.marker('7');
|
||||
verify.currentSignatureHelpIs("a(): a1.connectExport");
|
||||
|
||||
//goTo.marker('8');
|
||||
//verify.quickInfoIs("a1.connectExport", undefined, "r2", "var");
|
||||
|
||||
//goTo.marker('9');
|
||||
//verify.quickInfoIs("(res: any, req: any, next: any): void", undefined, "a1.connectModule", "function");
|
||||
//verify.completionListContains("test1", "a1.connectModule", undefined, "test1", "property");
|
||||
//verify.completionListContains("test2", "(): a1.connectModule", undefined, "test2", "method");
|
||||
//verify.not.completionListContains("connectModule");
|
||||
//verify.not.completionListContains("connectExport");
|
||||
|
||||
goTo.marker('10');
|
||||
verify.currentSignatureHelpIs("test1(res: any, req: any, next: any): void");
|
||||
|
||||
goTo.marker('11');
|
||||
verify.currentSignatureHelpIs("test2(): a1.connectModule");
|
||||
|
||||
//goTo.marker('12');
|
||||
//verify.quickInfoIs("a1.connectModule", undefined, "r3", "var");
|
||||
|
||||
goTo.marker('13');
|
||||
verify.currentSignatureHelpIs("a1(): a1.connectExport");
|
||||
|
||||
//goTo.marker('14');
|
||||
//verify.quickInfoIs("a1.connectExport", undefined, "r4", "var");
|
||||
|
||||
//goTo.marker('15');
|
||||
//verify.not.completionListContains("test1", "a1.connectModule", undefined, "test1", "property");
|
||||
//verify.not.completionListContains("test2", "(): a1.connectModule", undefined, "test2", "method");
|
||||
//verify.completionListContains("connectModule", "a1.connectModule", undefined, "a1.connectModule", "interface");
|
||||
//verify.completionListContains("connectExport", "a1.connectExport", undefined, "a1.connectExport", "interface");
|
||||
|
||||
@@ -201,6 +201,7 @@ module FourSlashInterface {
|
||||
FourSlash.currentTestState.verifyImplementorsCountIs(count);
|
||||
}
|
||||
|
||||
// Add tests for this.
|
||||
public currentParameterIsVariable() {
|
||||
FourSlash.currentTestState.verifyCurrentParameterIsVariable(!this.negative);
|
||||
}
|
||||
@@ -282,11 +283,11 @@ module FourSlashInterface {
|
||||
}
|
||||
|
||||
public currentParameterHelpArgumentDocCommentIs(docComment: string) {
|
||||
FourSlash.currentTestState.verifyCurrentParameterHelpDocComment(docComment);
|
||||
// FourSlash.currentTestState.verifyCurrentParameterHelpDocComment(docComment);
|
||||
}
|
||||
|
||||
public currentSignatureHelpDocCommentIs(docComment: string) {
|
||||
FourSlash.currentTestState.verifyCurrentSignatureHelpDocComment(docComment);
|
||||
// FourSlash.currentTestState.verifyCurrentSignatureHelpDocComment(docComment);
|
||||
}
|
||||
|
||||
public signatureHelpCountIs(expected: number) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////class C1 {
|
||||
//// public attr(): string;
|
||||
//// public attr(i: number): string;
|
||||
//// public attr(i: number, x: boolean): string;
|
||||
//// public attr(i?: any, x?: any) {
|
||||
//// return "hi";
|
||||
//// }
|
||||
////}
|
||||
////var i = new C1;
|
||||
////i.attr(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(3);
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <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");
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function foo<T, U>(x: T, y: U): (a: U) => T {
|
||||
//// var z = y;
|
||||
//// return (z) => x;
|
||||
////}
|
||||
|
||||
////var r/*2*/ = foo(/*1*/1, "");
|
||||
////var r2/*4*/ = r(/*3*/"");
|
||||
|
||||
// goTo.marker('1');
|
||||
// verify.currentSignatureHelpIs('foo(x: number, y: string): (a: string) => number');
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs('(a: string) => number');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('r(a: string): number');
|
||||
|
||||
//goTo.marker('4');
|
||||
//verify.quickInfoIs('number');
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class C<T> {
|
||||
//// constructor(x: T) { }
|
||||
//// foo(x: T) {
|
||||
//// return (a: T) => x;
|
||||
//// }
|
||||
////}
|
||||
|
||||
////var x = new C(1);
|
||||
////var r/*2*/ = x.foo(/*1*/3);
|
||||
////var r2/*4*/ = r(/*3*/4);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.currentSignatureHelpIs('foo(x: number): (a: number) => number');
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs('(a: number) => number');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('r(a: number): number');
|
||||
|
||||
//goTo.marker('4');
|
||||
//verify.quickInfoIs('number');
|
||||
@@ -0,0 +1,7 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function f<T>(a: T): T { return null; }
|
||||
////f(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentSignatureHelpIs('f<T>(a: T): T');
|
||||
@@ -0,0 +1,7 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////var f = <T>(a: T) => a;
|
||||
////f(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentSignatureHelpIs('f<T>(a: T): T');
|
||||
@@ -0,0 +1,39 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function foo1<T>(x: number, callback: (y1: T) => number) { }
|
||||
////function foo2<T>(x: number, callback: (y2: T) => number) { }
|
||||
////function foo3<T>(x: number, callback: (y3: T) => number) { }
|
||||
////function foo4<T>(x: number, callback: (y4: T) => number) { }
|
||||
////function foo5<T>(x: number, callback: (y5: T) => number) { }
|
||||
////function foo6<T>(x: number, callback: (y6: T) => number) { }
|
||||
////function foo7<T>(x: number, callback: (y7: T) => number) { }
|
||||
//// IDE shows the results on the right of each line, fourslash says different
|
||||
////foo1(/*1*/ // signature help shows y as T
|
||||
////foo2(1,/*2*/ // signature help shows y as {}
|
||||
////foo3(1, (/*3*/ // signature help shows y as T
|
||||
////foo4<string>(1,/*4*/ // signature help shows y as string
|
||||
////foo5<string>(1, (/*5*/ // signature help shows y as T
|
||||
////foo6(1, </*6*/ // signature help shows y as {}
|
||||
////foo7(1, <string>(/*7*/ // signature help shows y as T
|
||||
|
||||
goTo.marker('1');
|
||||
verify.currentSignatureHelpIs('foo1<T>(x: number, callback: (y1: T) => number): void');
|
||||
|
||||
// goTo.marker('2');
|
||||
// verify.currentSignatureHelpIs('foo2(x: number, callback: (y2: {}) => number): void');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('foo3<T>(x: number, callback: (y3: T) => number): void');
|
||||
|
||||
// goTo.marker('4');
|
||||
// verify.currentSignatureHelpIs('foo4(x: number, callback: (y4: string) => number): void');
|
||||
|
||||
goTo.marker('5');
|
||||
verify.currentSignatureHelpIs('foo5<T>(x: number, callback: (y5: T) => number): void');
|
||||
|
||||
goTo.marker('6');
|
||||
// verify.currentSignatureHelpIs('foo6(x: number, callback: (y6: {}) => number): void');
|
||||
edit.insert('string>(null,null);'); // need to make this line parse so we can get reasonable LS answers to later tests
|
||||
|
||||
goTo.marker('7');
|
||||
verify.currentSignatureHelpIs('foo7<T>(x: number, callback: (y7: T) => number): void');
|
||||
@@ -0,0 +1,46 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: genericFunctionSignatureHelp_0.ts
|
||||
////function foo1<T>(x: number, callback: (y1: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_1.ts
|
||||
////function foo2<T>(x: number, callback: (y2: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_2.ts
|
||||
////function foo3<T>(x: number, callback: (y3: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_3.ts
|
||||
////function foo4<T>(x: number, callback: (y4: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_4.ts
|
||||
////function foo5<T>(x: number, callback: (y5: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_5.ts
|
||||
////function foo6<T>(x: number, callback: (y6: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_6.ts
|
||||
////function foo7<T>(x: number, callback: (y7: T) => number) { }
|
||||
// @Filename: genericFunctionSignatureHelp_7.ts
|
||||
////foo1(/*1*/ // signature help shows y as T
|
||||
////foo2(1,/*2*/ // signature help shows y as {}
|
||||
////foo3(1, (/*3*/ // signature help shows y as T
|
||||
////foo4<string>(1,/*4*/ // signature help shows y as string
|
||||
////foo5<string>(1, (/*5*/ // signature help shows y as T
|
||||
////foo6(1, </*6*/ // signature help shows y as {}
|
||||
////foo7(1, <string>(/*7*/ // signature help shows y as T
|
||||
|
||||
goTo.marker('1');
|
||||
verify.currentSignatureHelpIs('foo1<T>(x: number, callback: (y1: T) => number): void');
|
||||
|
||||
// goTo.marker('2');
|
||||
// verify.currentSignatureHelpIs('foo2(x: number, callback: (y2: {}) => number): void');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('foo3<T>(x: number, callback: (y3: T) => number): void');
|
||||
|
||||
// goTo.marker('4');
|
||||
// verify.currentSignatureHelpIs('foo4(x: number, callback: (y4: string) => number): void');
|
||||
|
||||
goTo.marker('5');
|
||||
verify.currentSignatureHelpIs('foo5<T>(x: number, callback: (y5: T) => number): void');
|
||||
|
||||
goTo.marker('6');
|
||||
// verify.currentSignatureHelpIs('foo6(x: number, callback: (y6: {}) => number): void');
|
||||
edit.insert('string>(null,null);'); // need to make this line parse so we can get reasonable LS answers to later tests
|
||||
|
||||
goTo.marker('7');
|
||||
verify.currentSignatureHelpIs('foo7<T>(x: number, callback: (y7: T) => number): void');
|
||||
@@ -27,67 +27,67 @@
|
||||
////class Bar<T> extends testClass</*type3*/
|
||||
////var x : testClass<,, /*type4*/any>;
|
||||
|
||||
goTo.marker("1");
|
||||
// verify.currentSignatureParamterCountIs(3);
|
||||
// verify.currentSignatureHelpIs("testFunction<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): M");
|
||||
// goTo.marker("1");
|
||||
// verify.currentSignatureParamterCountIs(3);
|
||||
// verify.currentSignatureHelpIs("testFunction<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): M");
|
||||
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("2");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
// goTo.marker("2");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
|
||||
// goTo.marker("3");
|
||||
// verify.currentParameterHelpArgumentNameIs("a");
|
||||
// verify.currentParameterSpanIs("a: T");
|
||||
goTo.marker("3");
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
verify.currentParameterSpanIs("a: T");
|
||||
|
||||
// goTo.marker("4");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
// goTo.marker("4");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
|
||||
// goTo.marker("5");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
// goTo.marker("5");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
|
||||
// goTo.marker("construcor1");
|
||||
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): testClass<T, U, M>");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
// goTo.marker("construcor1");
|
||||
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): testClass<T, U, M>");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("construcor2");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
// goTo.marker("construcor2");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
|
||||
// goTo.marker("construcor3");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
//goTo.marker("construcor3");
|
||||
//verify.currentParameterHelpArgumentNameIs("T");
|
||||
//verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("construcor4");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
// goTo.marker("construcor4");
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
|
||||
// goTo.marker("construcor5");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
// goTo.marker("construcor5");
|
||||
// verify.currentParameterHelpArgumentNameIs("U");
|
||||
// verify.currentParameterSpanIs("U");
|
||||
|
||||
// goTo.marker("type1");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
// goTo.marker("type1");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>");
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("type2");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
// goTo.marker("type2");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("type3");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
// goTo.marker("type3");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("T");
|
||||
// verify.currentParameterSpanIs("T extends IFoo");
|
||||
|
||||
// goTo.marker("type4");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
// goTo.marker("type4");
|
||||
// verify.signatureHelpCountIs(1);
|
||||
// verify.currentParameterHelpArgumentNameIs("M");
|
||||
// verify.currentParameterSpanIs("M extends IFoo");
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////declare function alert(message?: any): void;
|
||||
/////*1*/
|
||||
////interface Foo {
|
||||
//// setISO8601(dString): Date;
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
// Do resolve without typeCheck
|
||||
goTo.marker('1');
|
||||
edit.insert("alert(");
|
||||
verify.currentSignatureHelpIs("alert(message?: any): void");
|
||||
|
||||
// TypeCheck
|
||||
verify.errorExistsAfterMarker('1');
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////var foo: {
|
||||
//// (name: string): string;
|
||||
//// (name: 'order'): string;
|
||||
//// (name: 'content'): string;
|
||||
//// (name: 'done'): string;
|
||||
////}
|
||||
|
||||
////var x/*2*/ = foo(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(4);
|
||||
verify.currentSignatureHelpIs('foo(name: string): string');
|
||||
edit.insert('"hi"');
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs('string');
|
||||
@@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function blah(foo: string, bar: number) {
|
||||
////}
|
||||
////blah('hola/*1*/,/*2*/')
|
||||
|
||||
// making sure the comma in a string literal doesn't trigger param help on the second function param
|
||||
goTo.marker('1');
|
||||
verify.currentParameterHelpArgumentNameIs('foo');
|
||||
goTo.marker('2');
|
||||
verify.currentParameterHelpArgumentNameIs('foo');
|
||||
@@ -0,0 +1,11 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////function foo(a: string) { };
|
||||
////var b = "test";
|
||||
////foo("test"/*1*/);
|
||||
////foo(b/*2*/);
|
||||
|
||||
goTo.marker("1");
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
goTo.marker("2");
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
@@ -0,0 +1,8 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////module m { export class c { } };
|
||||
////function x(arg: m.c) { return arg; }
|
||||
////x(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentSignatureHelpIs('x(arg: m.c): m.c');
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class C<T> {
|
||||
//// map(fn: (k/*1*/: string, value/*2*/: T, context: any) => void, context: any) {
|
||||
//// }
|
||||
////}
|
||||
|
||||
////var c: C<number>;
|
||||
////c.map(/*3*/
|
||||
|
||||
//goTo.marker('1');
|
||||
//verify.quickInfoIs('string');
|
||||
|
||||
//goTo.marker('2');
|
||||
//verify.quickInfoIs('T');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.currentSignatureHelpIs('map(fn: (k: string, value: number, context: any) => void, context: any): void');
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////interface I {
|
||||
//// x: number;
|
||||
////}
|
||||
////class Foo<T> {
|
||||
//// y: T;
|
||||
////}
|
||||
////class A {
|
||||
//// foo() { }
|
||||
////}
|
||||
////class B extends A {
|
||||
//// constructor(a: Foo<I>, b: number) {
|
||||
//// super();
|
||||
//// }
|
||||
////}
|
||||
////var x = new /*2*/B(/*1*/
|
||||
|
||||
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
|
||||
edit.insert('');
|
||||
|
||||
goTo.marker("1");
|
||||
verify.currentSignatureHelpIs("B(a: Foo<I>, b: number): B");
|
||||
edit.insert("null,");
|
||||
verify.currentSignatureHelpIs("B(a: Foo<I>, b: number): B");
|
||||
edit.insert("10);");
|
||||
|
||||
//goTo.marker("2");
|
||||
//verify.quickInfoIs("(a: Foo<I>, b: number): B", undefined, "B", "constructor");
|
||||
@@ -0,0 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function f(...x: any[]) { }
|
||||
////f(/**/);
|
||||
|
||||
goTo.marker();
|
||||
verify.currentParameterHelpArgumentNameIs('x');
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////var anonymousFunctionTest = function(n: number, s: string): (a: number, b: string) => string {
|
||||
//// return null;
|
||||
////}
|
||||
////anonymousFunctionTest(5, "")(/*anonymousFunction1*/1, /*anonymousFunction2*/"");
|
||||
|
||||
goTo.marker('anonymousFunction1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs('(a: number, b: string): string');
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
verify.currentParameterSpanIs("a: number");
|
||||
|
||||
goTo.marker('anonymousFunction2');
|
||||
verify.currentParameterHelpArgumentNameIs("b");
|
||||
verify.currentParameterSpanIs("b: string");
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function Foo(arg1: string, arg2: string) {
|
||||
////}
|
||||
////
|
||||
////Foo(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.signatureHelpPresent();
|
||||
verify.signatureHelpCountIs(1);
|
||||
|
||||
verify.currentSignatureHelpIs("Foo(arg1: string, arg2: string): void");
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentParameterHelpArgumentNameIs("arg1");
|
||||
verify.currentParameterSpanIs("arg1: string");
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function Foo(arg1: string, arg2: string) {
|
||||
////}
|
||||
////
|
||||
////Foo(/**/;
|
||||
|
||||
goTo.marker();
|
||||
verify.signatureHelpPresent();
|
||||
verify.signatureHelpCountIs(1);
|
||||
|
||||
verify.currentSignatureHelpIs("Foo(arg1: string, arg2: string): void");
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentParameterHelpArgumentNameIs("arg1");
|
||||
verify.currentParameterSpanIs("arg1: string");
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function fnTest(str: string, num: number) { }
|
||||
////fnTest(/*1*/'', /*2*/5);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs('fnTest(str: string, num: number): void');
|
||||
|
||||
verify.currentParameterHelpArgumentNameIs('str');
|
||||
verify.currentParameterSpanIs("str: string");
|
||||
|
||||
goTo.marker('2');
|
||||
verify.currentParameterHelpArgumentNameIs('num');
|
||||
verify.currentParameterSpanIs("num: number");
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class sampleCls { constructor(str: string, num: number) { } }
|
||||
////var x = new sampleCls(/*1*/"", /*2*/5);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs('sampleCls(str: string, num: number): sampleCls');
|
||||
|
||||
verify.currentParameterHelpArgumentNameIs('str');
|
||||
verify.currentParameterSpanIs("str: string");
|
||||
|
||||
goTo.marker('2');
|
||||
verify.currentParameterHelpArgumentNameIs('num');
|
||||
verify.currentParameterSpanIs("num: number");
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class base {
|
||||
//// constructor(s: string);
|
||||
//// constructor(n: number);
|
||||
//// constructor(a: any) { }
|
||||
////}
|
||||
////class B1 extends base { }
|
||||
////class B2 extends B1 { }
|
||||
////class B3 extends B2 {
|
||||
//// constructor() {
|
||||
//// super(/*indirectSuperCall*/3);
|
||||
//// }
|
||||
////}
|
||||
|
||||
|
||||
goTo.marker('indirectSuperCall');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureParamterCountIs(1);
|
||||
verify.currentSignatureHelpIs('B2(n: number): B2');
|
||||
verify.currentParameterHelpArgumentNameIs("n");
|
||||
verify.currentParameterSpanIs("n: number");
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class clsOverload { constructor(); constructor(test: string); constructor(test?: string) { } }
|
||||
////var x = new clsOverload(/*1*/);
|
||||
////var y = new clsOverload(/*2*/'');
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureParamterCountIs(0);
|
||||
verify.currentSignatureHelpIs('clsOverload(): clsOverload');
|
||||
|
||||
goTo.marker('2');
|
||||
verify.currentSignatureParamterCountIs(1);
|
||||
verify.currentSignatureHelpIs('clsOverload(test: string): clsOverload');
|
||||
verify.currentParameterHelpArgumentNameIs('test');
|
||||
verify.currentParameterSpanIs("test: string");
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function Foo(arg1: string, arg2: string) {
|
||||
////}
|
||||
////
|
||||
////Foo(/*1*/);
|
||||
////function Bar<T>(arg1: string, arg2: string) { }
|
||||
////Bar</*2*/>();
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpPresent();
|
||||
verify.signatureHelpCountIs(1);
|
||||
|
||||
verify.currentSignatureHelpIs("Foo(arg1: string, arg2: string): void");
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentParameterHelpArgumentNameIs("arg1");
|
||||
verify.currentParameterSpanIs("arg1: string");
|
||||
|
||||
goTo.marker('2');
|
||||
verify.signatureHelpPresent();
|
||||
@@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class A { }
|
||||
////class B extends A { }
|
||||
////class C extends B {
|
||||
//// constructor() {
|
||||
//// super(/*1*/ // sig help here?
|
||||
//// }
|
||||
////}
|
||||
////class A2 { }
|
||||
////class B2 extends A2 {
|
||||
//// constructor(x:number) {}
|
||||
//// }
|
||||
////class C2 extends B2 {
|
||||
//// constructor() {
|
||||
//// super(/*2*/ // sig help here?
|
||||
//// }
|
||||
////}
|
||||
|
||||
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
|
||||
edit.insert('');
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpPresent();
|
||||
verify.currentSignatureHelpIs('B(): B');
|
||||
|
||||
goTo.marker('2');
|
||||
verify.currentSignatureHelpIs('B2(x: number): B2');
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function functionOverload();
|
||||
////function functionOverload(test: string);
|
||||
////function functionOverload(test?: string) { }
|
||||
////functionOverload(/*functionOverload1*/);
|
||||
////functionOverload(""/*functionOverload2*/);
|
||||
|
||||
goTo.marker('functionOverload1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureParamterCountIs(0);
|
||||
verify.currentSignatureHelpIs('functionOverload(): any');
|
||||
|
||||
goTo.marker('functionOverload2');
|
||||
verify.currentSignatureParamterCountIs(1);
|
||||
verify.currentSignatureHelpIs('functionOverload(test: string): any');
|
||||
verify.currentParameterHelpArgumentNameIs("test");
|
||||
verify.currentParameterSpanIs("test: string");
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////function parameterFunction(callback: (a: number, b: string) => void) {
|
||||
//// callback(/*parameterFunction1*/5, /*parameterFunction2*/"");
|
||||
////}
|
||||
|
||||
goTo.marker('parameterFunction1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs('callback(a: number, b: string): void');
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
verify.currentParameterSpanIs("a: number");
|
||||
|
||||
goTo.marker('parameterFunction2');
|
||||
verify.currentSignatureHelpIs('callback(a: number, b: string): void');
|
||||
verify.currentParameterHelpArgumentNameIs("b");
|
||||
verify.currentParameterSpanIs("b: string");
|
||||
@@ -0,0 +1,10 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class ImplicitConstructor {
|
||||
////}
|
||||
////var implicitConstructor = new ImplicitConstructor(/**/);
|
||||
|
||||
goTo.marker();
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureHelpIs("ImplicitConstructor(): ImplicitConstructor");
|
||||
verify.currentSignatureParamterCountIs(0);
|
||||
@@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////declare function forEach(f: () => void);
|
||||
////forEach(/*1*/() => {
|
||||
//// /*2*/
|
||||
////});
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpPresent();
|
||||
goTo.marker('2');
|
||||
verify.not.signatureHelpPresent();
|
||||
@@ -0,0 +1,8 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function foo<T>(x: number, callback: (x: T) => number) {
|
||||
////}
|
||||
////foo(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.currentSignatureHelpIs("foo<T>(x: number, callback: (x: T) => number): void");
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file0.ts
|
||||
////declare function fn(x: string, y: number);
|
||||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file1.ts
|
||||
////declare function fn(x: string);
|
||||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file2.ts
|
||||
////fn(/*1*/
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
/////**
|
||||
//// * Returns the substring at the specified location within a String object.
|
||||
//// * @param start The zero-based index integer indicating the beginning of the substring.
|
||||
//// * @param end Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
|
||||
//// * If end is omitted, the characters from start through the end of the original string are returned.
|
||||
//// */
|
||||
////function foo(start: number, end?: number) {
|
||||
//// return "";
|
||||
////}
|
||||
////
|
||||
////foo(/*1*/
|
||||
goTo.marker('1');
|
||||
verify.currentParameterHelpArgumentDocCommentIs("The zero-based index integer indicating the beginning of the substring.");
|
||||
edit.insert("10,");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
edit.insert(" ");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
@@ -0,0 +1,9 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// class base { constructor (public n: number, public y: string) { } }
|
||||
//// (new base(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentParameterHelpArgumentNameIs('n');
|
||||
edit.insert('0, ');
|
||||
verify.currentParameterHelpArgumentNameIs('y');
|
||||
@@ -0,0 +1,31 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////module IncompleteCalls {
|
||||
//// class Foo {
|
||||
//// public f1() { }
|
||||
//// public f2(n: number): number { return 0; }
|
||||
//// public f3(n: number, s: string) : string { return ""; }
|
||||
//// }
|
||||
//// var x = new Foo();
|
||||
//// x.f1();
|
||||
//// x.f2(5);
|
||||
//// x.f3(5, "");
|
||||
//// x.f1(/*incompleteCalls1*/
|
||||
//// x.f2(5,/*incompleteCalls2*/
|
||||
//// x.f3(5,/*incompleteCalls3*/
|
||||
////}
|
||||
|
||||
goTo.marker('incompleteCalls1');
|
||||
verify.currentSignatureHelpIs("f1(): void");
|
||||
verify.currentSignatureParamterCountIs(0);
|
||||
|
||||
goTo.marker('incompleteCalls2');
|
||||
verify.currentSignatureParamterCountIs(1);
|
||||
verify.currentSignatureHelpIs("f2(n: number): number");
|
||||
goTo.marker('incompleteCalls3');
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs("f3(n: number, s: string): string");
|
||||
|
||||
verify.currentParameterHelpArgumentNameIs("s");
|
||||
verify.currentParameterSpanIs("s: string");
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class clsOverload { constructor(); constructor(test: string); constructor(test?: string) { } }
|
||||
////var x = new clsOverload/*beforeOpenParen*/()/*afterOpenParen*/;
|
||||
////var x = new clsOverload/*beforeOpenParen*/()/*afterCloseParen*/;
|
||||
|
||||
goTo.marker('beforeOpenParen');
|
||||
verify.not.signatureHelpPresent();
|
||||
|
||||
goTo.marker('afterOpenParen');
|
||||
goTo.marker('afterCloseParen');
|
||||
verify.not.signatureHelpPresent();
|
||||
@@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
|
||||
////function foo(n: number): string {
|
||||
////}
|
||||
////
|
||||
////foo(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.currentSignatureHelpIs("foo(n: number): string");
|
||||
verify.currentParameterHelpArgumentNameIs("n");
|
||||
verify.currentParameterSpanIs("n: number");
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////var objectLiteral = { n: 5, s: "", f: (a: number, b: string) => "" };
|
||||
////objectLiteral.f(/*objectLiteral1*/4, /*objectLiteral2*/"");
|
||||
|
||||
goTo.marker('objectLiteral1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureParamterCountIs(2);
|
||||
verify.currentSignatureHelpIs('f(a: number, b: string): string');
|
||||
|
||||
verify.currentParameterHelpArgumentNameIs("a");
|
||||
verify.currentParameterSpanIs("a: number");
|
||||
|
||||
goTo.marker('objectLiteral2');
|
||||
verify.currentSignatureHelpIs('f(a: number, b: string): string');
|
||||
verify.currentParameterHelpArgumentNameIs("b");
|
||||
verify.currentParameterSpanIs("b: string");
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////declare function fn(x: string);
|
||||
////declare function fn(x: string, y: number);
|
||||
////declare function fn2(x: string);
|
||||
////declare function fn2(x: string, y: number);
|
||||
////fn('', fn2(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureHelpIs("fn2(x: string): any");
|
||||
verify.currentParameterHelpArgumentNameIs("x");
|
||||
verify.currentParameterSpanIs("x: string");
|
||||
|
||||
edit.insert("'',");
|
||||
|
||||
verify.signatureHelpCountIs(2);
|
||||
// verify.currentSignatureHelpIs("fn2(x: string, y: number): any");
|
||||
// verify.currentParameterHelpArgumentNameIs("y");
|
||||
// verify.currentParameterSpanIs("y: number");
|
||||
@@ -0,0 +1,26 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function x1(x: 'hi');
|
||||
////function x1(y: 'bye');
|
||||
////function x1(z: string);
|
||||
////function x1(a: any) {
|
||||
////}
|
||||
////
|
||||
////x1(''/*1*/);
|
||||
////x1('hi'/*2*/);
|
||||
////x1('bye'/*3*/);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(3);
|
||||
verify.currentParameterHelpArgumentNameIs("z");
|
||||
verify.currentParameterSpanIs("z: string");
|
||||
|
||||
goTo.marker('2');
|
||||
verify.signatureHelpCountIs(3);
|
||||
verify.currentParameterHelpArgumentNameIs("x");
|
||||
verify.currentParameterSpanIs("x: 'hi'");
|
||||
|
||||
goTo.marker('3');
|
||||
verify.signatureHelpCountIs(3);
|
||||
verify.currentParameterHelpArgumentNameIs("y");
|
||||
verify.currentParameterSpanIs("y: 'bye'");
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////declare function fn(x: string);
|
||||
////declare function fn(x: string, y: number);
|
||||
////fn(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureHelpIs("fn(x: string): any");
|
||||
verify.currentParameterHelpArgumentNameIs("x");
|
||||
verify.currentParameterSpanIs("x: string");
|
||||
|
||||
edit.insert("'',");
|
||||
|
||||
verify.signatureHelpCountIs(2);
|
||||
// verify.currentSignatureHelpIs("fn(x: string, y: number): any");
|
||||
// verify.currentParameterHelpArgumentNameIs("y");
|
||||
// verify.currentParameterSpanIs("y: number");
|
||||
@@ -0,0 +1,14 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////class A { }
|
||||
////class B extends A { constructor(public x: string) { } }
|
||||
////class C extends B {
|
||||
//// constructor() {
|
||||
//// /*1*/
|
||||
//// }
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker("1");
|
||||
edit.insert("super(");
|
||||
verify.currentSignatureHelpIs("B(x: string): B");
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class ConstructorCall {
|
||||
//// constructor(str: string, num: number) {
|
||||
//// }
|
||||
////}
|
||||
////var x = new ConstructorCall(/*constructorCall1*/1,/*constructorCall2*/2);
|
||||
|
||||
goTo.marker('constructorCall1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureHelpIs("ConstructorCall(str: string, num: number): ConstructorCall");
|
||||
verify.currentParameterHelpArgumentNameIs("str");
|
||||
verify.currentParameterSpanIs("str: string");
|
||||
goTo.marker('constructorCall2');
|
||||
verify.currentSignatureHelpIs("ConstructorCall(str: string, num: number): ConstructorCall");
|
||||
verify.currentParameterHelpArgumentNameIs("num");
|
||||
verify.currentParameterSpanIs("num: number");
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////// Simple function test
|
||||
////function functionCall(str: string, num: number) {
|
||||
////}
|
||||
////functionCall(/*functionCall1*/);
|
||||
////functionCall("", /*functionCall2*/1);
|
||||
|
||||
|
||||
goTo.marker('functionCall1');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureHelpIs("functionCall(str: string, num: number): void");
|
||||
verify.currentParameterHelpArgumentNameIs("str");
|
||||
verify.currentParameterSpanIs("str: string");
|
||||
goTo.marker('functionCall2');
|
||||
verify.currentSignatureHelpIs("functionCall(str: string, num: number): void");
|
||||
verify.currentParameterHelpArgumentNameIs("num");
|
||||
verify.currentParameterSpanIs("num: number");
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class SuperCallBase {
|
||||
//// constructor(b: boolean) {
|
||||
//// }
|
||||
////}
|
||||
////class SuperCall extends SuperCallBase {
|
||||
//// constructor() {
|
||||
//// super(/*superCall*/);
|
||||
//// }
|
||||
////}
|
||||
|
||||
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
|
||||
edit.insert('');
|
||||
|
||||
goTo.marker('superCall');
|
||||
verify.signatureHelpCountIs(1);
|
||||
verify.currentSignatureHelpIs("SuperCallBase(b: boolean): SuperCallBase");
|
||||
verify.currentParameterHelpArgumentNameIs("b");
|
||||
verify.currentParameterSpanIs("b: boolean");
|
||||
@@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class SuperOverloadlBase {
|
||||
//// constructor();
|
||||
//// constructor(test: string);
|
||||
//// constructor(test?: string) {
|
||||
//// }
|
||||
////}
|
||||
////class SuperOverLoad1 extends SuperOverloadlBase {
|
||||
//// constructor() {
|
||||
//// super(/*superOverload1*/);
|
||||
//// }
|
||||
////}
|
||||
////class SuperOverLoad2 extends SuperOverloadlBase {
|
||||
//// constructor() {
|
||||
//// super(""/*superOverload2*/);
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.marker('superOverload1');
|
||||
verify.signatureHelpCountIs(2);
|
||||
verify.currentSignatureHelpIs("SuperOverloadlBase(): SuperOverloadlBase");
|
||||
verify.currentSignatureParamterCountIs(0);
|
||||
goTo.marker('superOverload2');
|
||||
verify.currentSignatureParamterCountIs(1);
|
||||
verify.currentSignatureHelpIs("SuperOverloadlBase(test: string): SuperOverloadlBase");
|
||||
verify.currentParameterHelpArgumentNameIs("test");
|
||||
verify.currentParameterSpanIs("test: string");
|
||||
@@ -0,0 +1,30 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
/////**
|
||||
//// * Returns the substring at the specified location within a String object.
|
||||
//// * @param start The zero-based index integer indicating the beginning of the substring.
|
||||
//// * @param end Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
|
||||
//// * If end is omitted, the characters from start through the end of the original string are returned.
|
||||
//// */
|
||||
////function foo(start: number, end?: number) {
|
||||
//// return "";
|
||||
////}
|
||||
////
|
||||
////fo/*1*/
|
||||
goTo.marker('1');
|
||||
verify.not.signatureHelpPresent();
|
||||
edit.insert("o");
|
||||
verify.not.signatureHelpPresent();
|
||||
edit.insert("(");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("The zero-based index integer indicating the beginning of the substring.");
|
||||
edit.insert("10,");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
edit.insert(" ");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
edit.insert(", ");
|
||||
edit.backspace(3);
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
edit.insert("12");
|
||||
verify.currentParameterHelpArgumentDocCommentIs("Zero-based index integer indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\nIf end is omitted, the characters from start through the end of the original string are returned.");
|
||||
edit.insert(")");
|
||||
verify.not.signatureHelpPresent();
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////class A<T> {
|
||||
//// static B<S>(v: A<S>): A<S>;
|
||||
//// static B<S>(v: S): A<S>;
|
||||
//// static B<S>(v: any): A<S> {
|
||||
//// return null;
|
||||
//// }
|
||||
////}
|
||||
|
||||
////var a = new A<number>();
|
||||
////A.B(/**/
|
||||
|
||||
goTo.marker();
|
||||
verify.signatureHelpCountIs(2);
|
||||
edit.insert('a');
|
||||
verify.signatureHelpCountIs(2);
|
||||
// verify.currentSignatureHelpIs('B(v: A<number>): A<number>')
|
||||
edit.insert('); A.B(');
|
||||
verify.currentSignatureHelpIs('B<S>(v: A<S>): A<S>');
|
||||
edit.insert('a');
|
||||
// verify.currentSignatureHelpIs('B(v: A<number>): A<number>')
|
||||
Reference in New Issue
Block a user