mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-22 16:52:14 -06:00
Fixed issues with incomplete calls, cleaned some code up.
This commit is contained in:
parent
80b8062a01
commit
986a0b7343
@ -56,8 +56,6 @@ module ts {
|
||||
return stringWriters.pop();
|
||||
}
|
||||
|
||||
type CallLikeExpression = CallExpression | TaggedTemplateExpression;
|
||||
|
||||
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
|
||||
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
|
||||
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
|
||||
@ -5204,20 +5202,30 @@ module ts {
|
||||
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature) {
|
||||
var adjustedArgCount: number;
|
||||
var typeArguments: NodeArray<TypeNode>;
|
||||
var callIsIncomplete = false;
|
||||
var callIsIncomplete: boolean;
|
||||
|
||||
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
var tagExpression = <TaggedTemplateExpression>node;
|
||||
|
||||
// Even if the call is incomplete, we'll have a missing expression as our last argument,
|
||||
// so we can say the count is just the arg list length
|
||||
adjustedArgCount = args.length;
|
||||
typeArguments = undefined;
|
||||
|
||||
if (tagExpression.kind === SyntaxKind.TemplateExpression) {
|
||||
if (tagExpression.template.kind === SyntaxKind.TemplateExpression) {
|
||||
// If a tagged template expression lacks a tail literal, the call is incomplete.
|
||||
var template = <TemplateExpression>tagExpression.template;
|
||||
var lastSpan = lastOrUndefined(template.templateSpans);
|
||||
// Specifically, a template only can end in a TemplateTail or a Missing literal.
|
||||
var templateExpression = <TemplateExpression>tagExpression.template;
|
||||
var lastSpan = lastOrUndefined(templateExpression.templateSpans);
|
||||
Debug.assert(lastSpan !== undefined); // we should always have at least one span.
|
||||
callIsIncomplete = lastSpan === undefined || lastSpan.literal.kind !== SyntaxKind.TemplateTail;
|
||||
callIsIncomplete = lastSpan.literal.kind === SyntaxKind.Missing || isUnterminatedTemplateEnd(lastSpan.literal);
|
||||
}
|
||||
else {
|
||||
// If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
|
||||
// then this might actually turn out to be a TemplateHead in the future;
|
||||
// so we consider the call to be incomplete.
|
||||
var templateLiteral = <LiteralExpression>tagExpression.template;
|
||||
callIsIncomplete = isUnterminatedTemplateEnd(templateLiteral);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -5228,17 +5236,17 @@ module ts {
|
||||
|
||||
return signature.minArgumentCount === 0;
|
||||
}
|
||||
else {
|
||||
// For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
|
||||
adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
|
||||
|
||||
// For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
|
||||
adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
|
||||
|
||||
// If we are missing the close paren, the call is incomplete.
|
||||
callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
|
||||
}
|
||||
// If we are missing the close paren, the call is incomplete.
|
||||
callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
|
||||
|
||||
typeArguments = callExpression.typeArguments;
|
||||
}
|
||||
|
||||
|
||||
return checkArity(adjustedArgCount, typeArguments, callIsIncomplete, signature);
|
||||
|
||||
/**
|
||||
@ -5420,7 +5428,9 @@ module ts {
|
||||
}
|
||||
|
||||
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
|
||||
var typeArguments = (<CallExpression>node).typeArguments;
|
||||
var isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
|
||||
|
||||
var typeArguments = isTaggedTemplate ? undefined : (<CallExpression>node).typeArguments;
|
||||
forEach(typeArguments, checkSourceElement);
|
||||
|
||||
var candidates = candidatesOutArray || [];
|
||||
@ -5432,7 +5442,6 @@ module ts {
|
||||
}
|
||||
|
||||
var args = getEffectiveCallArguments(node);
|
||||
var isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
|
||||
|
||||
// The following applies to any value of 'excludeArgument[i]':
|
||||
// - true: the argument at 'i' is susceptible to a one-time permanent contextual typing.
|
||||
@ -5440,8 +5449,8 @@ module ts {
|
||||
// - false: the argument at 'i' *was* and *has been* permanently contextually typed.
|
||||
//
|
||||
// The idea is that we will perform type argument inference & assignability checking once
|
||||
// without using the susceptible parameters, and once more for each susceptible parameter,
|
||||
// contextually typing each as we go along.
|
||||
// without using the susceptible parameters that are functions, and once more for each of those
|
||||
// parameters, contextually typing each as we go along.
|
||||
//
|
||||
// For a tagged template, then the first argument be 'undefined' if necessary
|
||||
// because it represents a TemplateStringsArray.
|
||||
@ -5492,14 +5501,14 @@ module ts {
|
||||
// is just important for choosing the best signature. So in the case where there is only one
|
||||
// signature, the subtype pass is useless. So skipping it is an optimization.
|
||||
if (candidates.length > 1) {
|
||||
result = chooseOverload(candidates, subtypeRelation, excludeArgument);
|
||||
result = chooseOverload(candidates, subtypeRelation);
|
||||
}
|
||||
if (!result) {
|
||||
// Reinitialize these pointers for round two
|
||||
candidateForArgumentError = undefined;
|
||||
candidateForTypeArgumentError = undefined;
|
||||
resultOfFailedInference = undefined;
|
||||
result = chooseOverload(candidates, assignableRelation, excludeArgument);
|
||||
result = chooseOverload(candidates, assignableRelation);
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
@ -5552,7 +5561,7 @@ module ts {
|
||||
|
||||
return resolveErrorCall(node);
|
||||
|
||||
function chooseOverload(candidates: Signature[], relation: Map<Ternary>, excludeArgument: boolean[]) {
|
||||
function chooseOverload(candidates: Signature[], relation: Map<Ternary>) {
|
||||
for (var i = 0; i < candidates.length; i++) {
|
||||
if (!hasCorrectArity(node, args, candidates[i])) {
|
||||
continue;
|
||||
@ -5566,9 +5575,9 @@ module ts {
|
||||
if (candidate.typeParameters) {
|
||||
var typeArgumentTypes: Type[];
|
||||
var typeArgumentsAreValid: boolean;
|
||||
if ((<CallExpression>node).typeArguments) {
|
||||
if (typeArguments) {
|
||||
typeArgumentTypes = new Array<Type>(candidate.typeParameters.length);
|
||||
typeArgumentsAreValid = checkTypeArguments(candidate, (<CallExpression>node).typeArguments, typeArgumentTypes, /*reportErrors*/ false)
|
||||
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
|
||||
}
|
||||
else {
|
||||
inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
|
||||
@ -5602,7 +5611,7 @@ module ts {
|
||||
}
|
||||
else {
|
||||
candidateForTypeArgumentError = originalCandidate;
|
||||
if (!(<CallExpression>node).typeArguments) {
|
||||
if (!typeArguments) {
|
||||
resultOfFailedInference = inferenceResult;
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,7 +564,6 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export function isDeclaration(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeParameter:
|
||||
@ -752,6 +751,20 @@ module ts {
|
||||
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
|
||||
}
|
||||
|
||||
export function isUnterminatedTemplateEnd(node: LiteralExpression) {
|
||||
Debug.assert(node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail);
|
||||
var sourceText = getSourceFileOfNode(node).text;
|
||||
|
||||
// If we're not at the EOF, we know we must be terminated.
|
||||
if (node.end !== sourceText.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we didn't end in a backtick, we must still be in the middle of a template.
|
||||
// If we did, make sure that it's not the *initial* backtick.
|
||||
return sourceText.charCodeAt(node.end - 1) !== CharacterCodes.backtick || node.text.length === 0;
|
||||
}
|
||||
|
||||
export function isModifier(token: SyntaxKind): boolean {
|
||||
switch (token) {
|
||||
case SyntaxKind.PublicKeyword:
|
||||
|
||||
@ -445,6 +445,8 @@ module ts {
|
||||
template: LiteralExpression | TemplateExpression;
|
||||
}
|
||||
|
||||
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
|
||||
|
||||
export interface TypeAssertion extends Expression {
|
||||
type: TypeNode;
|
||||
operand: Expression;
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts(6,15): error TS1126: Unexpected end of text.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts (1 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw
|
||||
|
||||
!!! error TS1126: Unexpected end of text.
|
||||
@ -0,0 +1,12 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts(6,4): error TS1126: Unexpected end of text.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts (1 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters, at EOF.
|
||||
f `
|
||||
|
||||
!!! error TS1126: Unexpected end of text.
|
||||
@ -0,0 +1,12 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions1.ts(6,17): error TS1109: Expression expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions1.ts (1 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw${
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
@ -0,0 +1,15 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions2.ts(6,18): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions2.ts(6,21): error TS1109: Expression expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions2.ts (2 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, enough parameters.
|
||||
f `123qdawdrqw${ }${
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
@ -0,0 +1,15 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions3.ts(6,23): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions3.ts(6,18): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions3.ts (2 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw${ 1 }${
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
~
|
||||
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
@ -0,0 +1,18 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions4.ts(6,24): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions4.ts(6,28): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions4.ts(6,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions4.ts (3 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, but too many parameters.
|
||||
f `123qdawdrqw${ 1 }${ }${
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||
@ -0,0 +1,15 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions5.ts(6,30): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions5.ts(6,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions5.ts (2 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, but too many parameters.
|
||||
f `123qdawdrqw${ 1 }${ 2 }${
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||
@ -0,0 +1,15 @@
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions6.ts(6,23): error TS1109: Expression expected.
|
||||
tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions6.ts(6,18): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/taggedTemplatesWithIncompleteTemplateExpressions6.ts (2 errors) ====
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters, at EOF.
|
||||
f `123qdawdrqw${ 1 }${
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
~
|
||||
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters, at EOF.
|
||||
f `
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw${
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, enough parameters.
|
||||
f `123qdawdrqw${ }${
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters.
|
||||
f `123qdawdrqw${ 1 }${
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, but too many parameters.
|
||||
f `123qdawdrqw${ 1 }${ }${
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, but too many parameters.
|
||||
f `123qdawdrqw${ 1 }${ 2 }${
|
||||
@ -0,0 +1,7 @@
|
||||
// @target: es6
|
||||
|
||||
function f(x: TemplateStringsArray, y: string, z: string) {
|
||||
}
|
||||
|
||||
// Incomplete call, not enough parameters, at EOF.
|
||||
f `123qdawdrqw${ 1 }${
|
||||
Loading…
x
Reference in New Issue
Block a user