Merge pull request #960 from Microsoft/templates

Support for ES6 Templates
This commit is contained in:
Daniel Rosenwasser 2014-10-31 15:19:52 -07:00
commit 0a97f5f766
304 changed files with 3226 additions and 206 deletions

View File

@ -427,7 +427,7 @@ module ts {
if (result.flags & SymbolFlags.BlockScopedVariable) {
// Block-scoped variables cannot be used before their definition
var declaration = forEach(result.declarations, d => d.flags & NodeFlags.BlockScoped ? d : undefined);
Debug.assert(declaration, "Block-scoped variable declaration is undefined");
Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
var declarationSourceFile = getSourceFileOfNode(declaration);
var referenceSourceFile = getSourceFileOfNode(errorLocation);
if (declarationSourceFile === referenceSourceFile) {
@ -472,7 +472,7 @@ module ts {
function getSymbolOfPartOfRightHandSideOfImport(entityName: EntityName, importDeclaration?: ImportDeclaration): Symbol {
if (!importDeclaration) {
importDeclaration = getAncestor(entityName, SyntaxKind.ImportDeclaration);
Debug.assert(importDeclaration);
Debug.assert(importDeclaration !== undefined);
}
// There are three things we might try to look for. In the following examples,
// the search term is enclosed in |...|:
@ -3334,7 +3334,6 @@ module ts {
}
if (reportErrors) {
headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
Debug.assert(headMessage);
reportError(headMessage, typeToString(source), typeToString(target));
}
return Ternary.False;
@ -4912,7 +4911,7 @@ module ts {
}
return createArrayType(getUnionType(elementTypes));
}
function isNumericName(name: string) {
// The intent of numeric names is that
// - they are names with text in a numeric form, and that
@ -4937,7 +4936,7 @@ module ts {
// with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively.
return (+name).toString() === name;
}
function checkObjectLiteral(node: ObjectLiteral, contextualMapper?: TypeMapper): Type {
var members = node.symbol.members;
var properties: SymbolTable = {};
@ -5660,6 +5659,13 @@ module ts {
return getReturnTypeOfSignature(signature);
}
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
// TODO (drosen): Make sure substitutions are assignable to the tag's arguments.
checkExpression(node.tag);
checkExpression(node.template);
return anyType;
}
function checkTypeAssertion(node: TypeAssertion): Type {
var exprType = checkExpression(node.operand);
var targetType = getTypeFromTypeNode(node.type);
@ -6170,6 +6176,19 @@ module ts {
return getUnionType([type1, type2]);
}
function checkTemplateExpression(node: TemplateExpression): Type {
// We just want to check each expressions, but we are unconcerned with
// the type of each expression, as any value may be coerced into a string.
// It is worth asking whether this is what we really want though.
// A place where we actually *are* concerned with the expressions' types are
// in tagged templates.
forEach((<TemplateExpression>node).templateSpans, templateSpan => {
checkExpression(templateSpan.expression);
});
return stringType;
}
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper?: TypeMapper): Type {
var saveContextualType = node.contextualType;
node.contextualType = contextualType;
@ -6223,7 +6242,10 @@ module ts {
return booleanType;
case SyntaxKind.NumericLiteral:
return numberType;
case SyntaxKind.TemplateExpression:
return checkTemplateExpression(<TemplateExpression>node);
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return stringType;
case SyntaxKind.RegularExpressionLiteral:
return globalRegExpType;
@ -6240,6 +6262,8 @@ module ts {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return checkCallExpression(<CallExpression>node);
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.TypeAssertion:
return checkTypeAssertion(<TypeAssertion>node);
case SyntaxKind.ParenExpression:
@ -7549,17 +7573,17 @@ module ts {
errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
}
else {
Debug.assert(derived.flags & SymbolFlags.Property);
Debug.assert((derived.flags & SymbolFlags.Property) !== 0);
errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
}
}
else if (base.flags & SymbolFlags.Property) {
Debug.assert(derived.flags & SymbolFlags.Method);
Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
}
else {
Debug.assert(base.flags & SymbolFlags.Accessor);
Debug.assert(derived.flags & SymbolFlags.Method);
Debug.assert((base.flags & SymbolFlags.Accessor) !== 0);
Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
}
@ -8016,6 +8040,7 @@ module ts {
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.PrefixOperator:
@ -8293,6 +8318,9 @@ module ts {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return (<CallExpression>parent).typeArguments && (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
case SyntaxKind.TaggedTemplateExpression:
// TODO (drosen): TaggedTemplateExpressions may eventually support type arguments.
return false;
}
}

View File

@ -19,6 +19,12 @@ module ts {
[index: string]: T;
}
export enum Comparison {
LessThan = -1,
EqualTo = 0,
GreaterThan = 1
}
export interface StringSet extends Map<any> { }
export function forEach<T, U>(array: T[], callback: (element: T) => U): U {
@ -93,6 +99,7 @@ module ts {
export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!array2 || !array2.length) return array1;
if (!array1 || !array1.length) return array2;
return array1.concat(array2);
}
@ -326,11 +333,11 @@ module ts {
};
}
export function compareValues<T>(a: T, b: T): number {
if (a === b) return 0;
if (a === undefined) return -1;
if (b === undefined) return 1;
return a < b ? -1 : 1;
export function compareValues<T>(a: T, b: T): Comparison {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}
function getDiagnosticFilename(diagnostic: Diagnostic): string {
@ -355,7 +362,7 @@ module ts {
var previousDiagnostic = diagnostics[0];
for (var i = 1; i < diagnostics.length; i++) {
var currentDiagnostic = diagnostics[i];
var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === 0;
var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
if (!isDupe) {
newDiagnostics.push(currentDiagnostic);
previousDiagnostic = currentDiagnostic;
@ -644,7 +651,7 @@ module ts {
return currentAssertionLevel >= level;
}
export function assert(expression: any, message?: string, verboseDebugInfo?: () => string): void {
export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void {
if (!expression) {
var verboseDebugString = "";
if (verboseDebugInfo) {

View File

@ -121,6 +121,8 @@ module ts {
const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
Aliased_type_cannot_be_an_object_type_literal_Use_an_interface_declaration_instead: { code: 1158, category: DiagnosticCategory.Error, key: "Aliased type cannot be an object type literal. Use an interface declaration instead." },
Invalid_template_literal_expected: { code: 1159, category: DiagnosticCategory.Error, key: "Invalid template literal; expected '}'" },
Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1160, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },

View File

@ -475,6 +475,14 @@
"category": "Error",
"code": 1158
},
"Invalid template literal; expected '}'": {
"category": "Error",
"code": 1159
},
"Tagged templates are only available when targeting ECMAScript 6 and higher.": {
"category": "Error",
"code": 1160
},
"Duplicate identifier '{0}'.": {
"category": "Error",

View File

@ -786,14 +786,123 @@ module ts {
}
}
function emitLiteral(node: LiteralExpression) {
var text = getSourceTextOfLocalNode(node);
if (node.kind === SyntaxKind.StringLiteral && compilerOptions.sourceMap) {
function emitLiteral(node: LiteralExpression): void {
var text = getLiteralText();
if (compilerOptions.sourceMap && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
writer.writeLiteral(text);
}
else {
write(text);
}
function getLiteralText() {
if (compilerOptions.target < ScriptTarget.ES6 && isTemplateLiteralKind(node.kind)) {
return getTemplateLiteralAsStringLiteral(node)
}
return getSourceTextOfLocalNode(node);
}
}
function getTemplateLiteralAsStringLiteral(node: LiteralExpression): string {
return '"' + escapeString(node.text) + '"';
}
function emitTemplateExpression(node: TemplateExpression): void {
// In ES6 mode and above, we can simply emit each portion of a template in order, but in
// ES3 & ES5 we must convert the template expression into a series of string concatenations.
if (compilerOptions.target >= ScriptTarget.ES6) {
forEachChild(node, emit);
return;
}
Debug.assert(node.parent.kind !== SyntaxKind.TaggedTemplateExpression);
var templateNeedsParens = isExpression(node.parent)
&& node.parent.kind !== SyntaxKind.ParenExpression
&& comparePrecedenceToBinaryPlus(node.parent) !== Comparison.LessThan;
if (templateNeedsParens) {
write("(");
}
emitLiteral(node.head);
forEach(node.templateSpans, templateSpan => {
// Check if the expression has operands and binds its operands less closely than binary '+'.
// If it does, we need to wrap the expression in parentheses. Otherwise, something like
// `abc${ 1 << 2}`
// becomes
// "abc" + 1 << 2 + ""
// which is really
// ("abc" + 1) << (2 + "")
// rather than
// "abc" + (1 << 2) + ""
var needsParens = templateSpan.expression.kind !== SyntaxKind.ParenExpression
&& comparePrecedenceToBinaryPlus(templateSpan.expression) !== Comparison.GreaterThan;
write(" + ");
if (needsParens) {
write("(");
}
emit(templateSpan.expression);
if (needsParens) {
write(")");
}
// Only emit if the literal is non-empty.
// The binary '+' operator is left-associative, so the first string concatenation will force
// the result up to this point to be a string. Emitting a '+ ""' has no semantic effect.
if (templateSpan.literal.text.length !== 0) {
write(" + ")
emitLiteral(templateSpan.literal);
}
});
if (templateNeedsParens) {
write(")");
}
/**
* Returns whether the expression has lesser, greater,
* or equal precedence to the binary '+' operator
*/
function comparePrecedenceToBinaryPlus(expression: Expression): Comparison {
// All binary expressions have lower precedence than '+' apart from '*', '/', and '%'.
// All unary operators have a higher precedence apart from yield.
// Arrow functions and conditionals have a lower precedence,
// although we convert the former into regular function expressions in ES5 mode,
// and in ES6 mode this function won't get called anyway.
//
// TODO (drosen): Note that we need to account for the upcoming 'yield' and
// spread ('...') unary operators that are anticipated for ES6.
Debug.assert(compilerOptions.target <= ScriptTarget.ES5);
switch (expression.kind) {
case SyntaxKind.BinaryExpression:
switch ((<BinaryExpression>expression).operator) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
return Comparison.GreaterThan;
case SyntaxKind.PlusToken:
return Comparison.EqualTo;
default:
return Comparison.LessThan;
}
case SyntaxKind.ConditionalExpression:
return Comparison.LessThan;
default:
return Comparison.GreaterThan;
}
}
}
function emitTemplateSpan(span: TemplateSpan) {
emit(span.expression);
emit(span.literal);
}
// This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
@ -977,6 +1086,13 @@ module ts {
}
}
function emitTaggedTemplateExpression(node: TaggedTemplateExpression): void {
Debug.assert(compilerOptions.target >= ScriptTarget.ES6, "Trying to emit a tagged template in pre-ES6 mode.");
emit(node.tag);
write(" ");
emit(node.template);
}
function emitParenExpression(node: ParenExpression) {
if (node.expression.kind === SyntaxKind.TypeAssertion) {
var operand = (<TypeAssertion>node.expression).operand;
@ -2085,7 +2201,15 @@ module ts {
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail:
return emitLiteral(<LiteralExpression>node);
case SyntaxKind.TemplateExpression:
return emitTemplateExpression(<TemplateExpression>node);
case SyntaxKind.TemplateSpan:
return emitTemplateSpan(<TemplateSpan>node);
case SyntaxKind.QualifiedName:
return emitPropertyAccess(<QualifiedName>node);
case SyntaxKind.ArrayLiteral:
@ -2102,6 +2226,8 @@ module ts {
return emitCallExpression(<CallExpression>node);
case SyntaxKind.NewExpression:
return emitNewExpression(<NewExpression>node);
case SyntaxKind.TaggedTemplateExpression:
return emitTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.TypeAssertion:
return emit((<TypeAssertion>node).operand);
case SyntaxKind.ParenExpression:

View File

@ -67,77 +67,6 @@ module ts {
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier);
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.PropertyAccess:
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// Fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
return (<VariableDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).operand;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
@ -315,6 +244,9 @@ module ts {
return child((<CallExpression>node).func) ||
children((<CallExpression>node).typeArguments) ||
children((<CallExpression>node).arguments);
case SyntaxKind.TaggedTemplateExpression:
return child((<TaggedTemplateExpression>node).tag) ||
child((<TaggedTemplateExpression>node).template);
case SyntaxKind.TypeAssertion:
return child((<TypeAssertion>node).type) ||
child((<TypeAssertion>node).operand);
@ -422,6 +354,10 @@ module ts {
child((<ImportDeclaration>node).externalModuleName);
case SyntaxKind.ExportAssignment:
return child((<ExportAssignment>node).exportName);
case SyntaxKind.TemplateExpression:
return child((<TemplateExpression>node).head) || children((<TemplateExpression>node).templateSpans);
case SyntaxKind.TemplateSpan:
return child((<TemplateSpan>node).expression) || child((<TemplateSpan>node).literal);
}
}
@ -526,10 +462,96 @@ module ts {
}
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.PropertyAccess:
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.TemplateExpression:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
return (<VariableDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).operand;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
}
export function isLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
}
export function isInAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
@ -538,6 +560,7 @@ module ts {
return false;
}
export function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
@ -955,6 +978,10 @@ module ts {
return token = scanner.reScanSlashToken();
}
function reScanTemplateToken(): SyntaxKind {
return token = scanner.reScanTemplateToken();
}
function lookAheadHelper<T>(callback: () => T, alwaysResetState: boolean): T {
// Keep track of the state we'll need to rollback to if lookahead fails (or if the
// caller asked us to always reset our state).
@ -1100,7 +1127,9 @@ module ts {
}
function isPropertyName(): boolean {
return token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral;
return token >= SyntaxKind.Identifier ||
token === SyntaxKind.StringLiteral ||
token === SyntaxKind.NumericLiteral;
}
function parsePropertyName(): Identifier {
@ -1136,7 +1165,7 @@ module ts {
case ParsingContext.SwitchClauses:
return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
case ParsingContext.TypeMembers:
return isTypeMember();
return isStartOfTypeMember();
case ParsingContext.ClassMembers:
return lookAhead(isClassMemberStart);
case ParsingContext.EnumMembers:
@ -1148,14 +1177,14 @@ module ts {
case ParsingContext.TypeParameters:
return isIdentifier();
case ParsingContext.ArgumentExpressions:
return token === SyntaxKind.CommaToken || isExpression();
return token === SyntaxKind.CommaToken || isStartOfExpression();
case ParsingContext.ArrayLiteralMembers:
return token === SyntaxKind.CommaToken || isExpression();
return token === SyntaxKind.CommaToken || isStartOfExpression();
case ParsingContext.Parameters:
return isParameter();
return isStartOfParameter();
case ParsingContext.TypeArguments:
case ParsingContext.TupleElementTypes:
return token === SyntaxKind.CommaToken || isType();
return token === SyntaxKind.CommaToken || isStartOfType();
}
Debug.fail("Non-exhaustive case in 'isListElement'.");
@ -1375,7 +1404,48 @@ module ts {
return finishNode(node);
}
function parseLiteralNode(internName?:boolean): LiteralExpression {
function parseTemplateExpression() {
var template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
template.head = parseLiteralNode();
Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
var templateSpans = <NodeArray<TemplateSpan>>[];
templateSpans.pos = getNodePos();
do {
templateSpans.push(parseTemplateSpan());
}
while (templateSpans[templateSpans.length - 1].literal.kind === SyntaxKind.TemplateMiddle)
templateSpans.end = getNodeEnd();
template.templateSpans = templateSpans;
return finishNode(template);
}
function parseTemplateSpan(): TemplateSpan {
var span = <TemplateSpan>createNode(SyntaxKind.TemplateSpan);
span.expression = parseExpression(/*noIn*/ false);
var literal: LiteralExpression;
if (token === SyntaxKind.CloseBraceToken) {
reScanTemplateToken()
literal = parseLiteralNode();
}
else {
error(Diagnostics.Invalid_template_literal_expected);
literal = <LiteralExpression>createMissingNode();
literal.text = "";
}
span.literal = literal;
return finishNode(span);
}
function parseLiteralNode(internName?: boolean): LiteralExpression {
var node = <LiteralExpression>createNode(token);
var text = scanner.getTokenValue();
node.text = internName ? internIdentifier(text) : text;
@ -1387,7 +1457,7 @@ module ts {
// Octal literals are not allowed in strict mode or ES5
// Note that theoretically the following condition would hold true literals like 009,
// which is not octal.But because of how the scanner separates the tokens, we would
// never get a token like this.Instead, we would get 00 and 9 as two separate tokens.
// never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
// We also do not need to check for negatives because any prefix operator would be part of a
// parent unary expression.
if (node.kind === SyntaxKind.NumericLiteral
@ -1406,7 +1476,9 @@ module ts {
}
function parseStringLiteral(): LiteralExpression {
if (token === SyntaxKind.StringLiteral) return parseLiteralNode(/*internName:*/ true);
if (token === SyntaxKind.StringLiteral) {
return parseLiteralNode(/*internName:*/ true);
}
error(Diagnostics.String_literal_expected);
return <LiteralExpression>createMissingNode();
}
@ -1437,7 +1509,7 @@ module ts {
// user writes a constraint that is an expression and not an actual type, then parse
// it out as an expression (so we can recover well), but report that a type is needed
// instead.
if (isType() || !isExpression()) {
if (isStartOfType() || !isStartOfExpression()) {
node.constraint = parseType();
}
else {
@ -1473,7 +1545,7 @@ module ts {
return parseOptional(SyntaxKind.ColonToken) ? token === SyntaxKind.StringLiteral ? parseStringLiteral() : parseType() : undefined;
}
function isParameter(): boolean {
function isStartOfParameter(): boolean {
return token === SyntaxKind.DotDotDotToken || isIdentifier() || isModifier(token);
}
@ -1681,7 +1753,7 @@ module ts {
return finishNode(node);
}
function isTypeMember(): boolean {
function isStartOfTypeMember(): boolean {
switch (token) {
case SyntaxKind.OpenParenToken:
case SyntaxKind.LessThanToken:
@ -1788,7 +1860,7 @@ module ts {
return <TypeNode>createMissingNode();
}
function isType(): boolean {
function isStartOfType(): boolean {
switch (token) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.StringKeyword:
@ -1806,7 +1878,7 @@ module ts {
// or something that starts a type. We don't want to consider things like '(1)' a type.
return lookAhead(() => {
nextToken();
return token === SyntaxKind.CloseParenToken || isParameter() || isType();
return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
});
default:
return isIdentifier();
@ -1840,7 +1912,7 @@ module ts {
return type;
}
function isFunctionType(): boolean {
function isStartOfFunctionType(): boolean {
return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => {
nextToken();
if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) {
@ -1873,7 +1945,7 @@ module ts {
}
function parseType(): TypeNode {
if (isFunctionType()) {
if (isStartOfFunctionType()) {
return parseFunctionType(SyntaxKind.CallSignature);
}
if (token === SyntaxKind.NewKeyword) {
@ -1888,7 +1960,7 @@ module ts {
// EXPRESSIONS
function isExpression(): boolean {
function isStartOfExpression(): boolean {
switch (token) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
@ -1897,6 +1969,8 @@ module ts {
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.OpenParenToken:
case SyntaxKind.OpenBracketToken:
case SyntaxKind.OpenBraceToken:
@ -1921,9 +1995,9 @@ module ts {
}
}
function isExpressionStatement(): boolean {
function isStartOfExpressionStatement(): boolean {
// As per the grammar, neither '{' nor 'function' can start an expression statement.
return token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.FunctionKeyword && isExpression();
return token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.FunctionKeyword && isStartOfExpression();
}
function parseExpression(noIn?: boolean): Expression {
@ -1944,7 +2018,7 @@ module ts {
// it's more likely that a { would be a allowed (as an object literal). While this
// is also allowed for parameters, the risk is that we consume the { as an object
// literal when it really will be for the block following the parameter.
if (scanner.hasPrecedingLineBreak() || (inParameter && token === SyntaxKind.OpenBraceToken) || !isExpression()) {
if (scanner.hasPrecedingLineBreak() || (inParameter && token === SyntaxKind.OpenBraceToken) || !isStartOfExpression()) {
// preceding line break, open brace in a parameter (likely a function body) or current token is not an expression -
// do not try to parse initializer
return undefined;
@ -1988,8 +2062,8 @@ module ts {
}
// Now see if we might be in cases '2' or '3'.
// If the expression was a LHS expression, and we have an assignment operator, then
// we're in '2' or '3'. Consume the assignment and return.
// If the expression was a LHS expression, and we have an assignment operator, then
// we're in '2' or '3'. Consume the assignment and return.
if (isLeftHandSideExpression(expr) && isAssignmentOperator()) {
if (isInStrictMode && isEvalOrArgumentsIdentifier(expr)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
@ -2012,6 +2086,7 @@ module ts {
case SyntaxKind.IndexedAccess:
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ParenExpression:
case SyntaxKind.ObjectLiteral:
@ -2021,6 +2096,8 @@ module ts {
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisKeyword:
@ -2189,7 +2266,7 @@ module ts {
if (token === SyntaxKind.OpenBraceToken) {
body = parseBody(/* ignoreMissingOpenBrace */ false);
}
else if (isStatement(/* inErrorRecovery */ true) && !isExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
else if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
// Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations)
//
// Here we try to recover from a potential error situation in the case where the
@ -2376,7 +2453,7 @@ module ts {
function parseCallAndAccess(expr: Expression, inNewExpression: boolean): Expression {
while (true) {
var dotStart = scanner.getTokenPos();
var dotOrBracketStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.DotToken)) {
var propertyAccess = <PropertyAccess>createNode(SyntaxKind.PropertyAccess, expr.pos);
// Technically a keyword is valid here as all keywords are identifier names.
@ -2399,7 +2476,7 @@ module ts {
// In the first case though, ASI will not take effect because there is not a
// line terminator after the keyword.
if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord() && lookAhead(() => scanner.isReservedWord())) {
grammarErrorAtPos(dotStart, scanner.getStartPos() - dotStart, Diagnostics.Identifier_expected);
grammarErrorAtPos(dotOrBracketStart, scanner.getStartPos() - dotOrBracketStart, Diagnostics.Identifier_expected);
var id = <Identifier>createMissingNode();
}
else {
@ -2412,7 +2489,6 @@ module ts {
continue;
}
var bracketStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.OpenBracketToken)) {
var indexedAccess = <IndexedAccess>createNode(SyntaxKind.IndexedAccess, expr.pos);
@ -2422,7 +2498,7 @@ module ts {
// Check for that common pattern and report a better error message.
if (inNewExpression && parseOptional(SyntaxKind.CloseBracketToken)) {
indexedAccess.index = createMissingNode();
grammarErrorAtPos(bracketStart, scanner.getStartPos() - bracketStart, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
grammarErrorAtPos(dotOrBracketStart, scanner.getStartPos() - dotOrBracketStart, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
}
else {
indexedAccess.index = parseExpression();
@ -2455,6 +2531,22 @@ module ts {
expr = finishNode(callExpr);
continue;
}
if (token === SyntaxKind.NoSubstitutionTemplateLiteral || token === SyntaxKind.TemplateHead) {
var tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expr.pos);
tagExpression.tag = expr;
tagExpression.template = token === SyntaxKind.NoSubstitutionTemplateLiteral
? parseLiteralNode()
: parseTemplateExpression();
expr = finishNode(tagExpression);
if (languageVersion < ScriptTarget.ES6) {
grammarErrorOnNode(expr, Diagnostics.Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
continue;
}
return expr;
}
}
@ -2501,6 +2593,7 @@ module ts {
return parseTokenNode();
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return parseLiteralNode();
case SyntaxKind.OpenParenToken:
return parseParenExpression();
@ -2518,6 +2611,9 @@ module ts {
return parseLiteralNode();
}
break;
case SyntaxKind.TemplateHead:
return parseTemplateExpression();
default:
if (isIdentifier()) {
return parseIdentifier();
@ -3176,7 +3272,7 @@ module ts {
case SyntaxKind.TypeKeyword:
// When followed by an identifier, these do not start a statement but might
// instead be following declarations
if (isDeclaration()) {
if (isDeclarationStart()) {
return false;
}
case SyntaxKind.PublicKeyword:
@ -3189,7 +3285,7 @@ module ts {
return false;
}
default:
return isExpression();
return isStartOfExpression();
}
}
@ -3920,7 +4016,7 @@ module ts {
return finishNode(node);
}
function isDeclaration(): boolean {
function isDeclarationStart(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
@ -3939,14 +4035,14 @@ module ts {
return lookAhead(() => nextToken() >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral);
case SyntaxKind.ExportKeyword:
// Check for export assignment or modifier on source element
return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclaration());
return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclarationStart());
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// Check for modifier on source element
return lookAhead(() => { nextToken(); return isDeclaration(); });
return lookAhead(() => { nextToken(); return isDeclarationStart(); });
}
}
@ -4010,7 +4106,7 @@ module ts {
}
function isSourceElement(inErrorRecovery: boolean): boolean {
return isDeclaration() || isStatement(inErrorRecovery);
return isDeclarationStart() || isStatement(inErrorRecovery);
}
function parseSourceElement() {
@ -4022,7 +4118,7 @@ module ts {
}
function parseSourceElementOrModuleElement(modifierContext: ModifierContext): Statement {
if (isDeclaration()) {
if (isDeclarationStart()) {
return parseDeclaration(modifierContext);
}

View File

@ -24,6 +24,7 @@ module ts {
isReservedWord(): boolean;
reScanGreaterToken(): SyntaxKind;
reScanSlashToken(): SyntaxKind;
reScanTemplateToken(): SyntaxKind;
scan(): SyntaxKind;
setText(text: string): void;
setTextPos(textPos: number): void;
@ -466,7 +467,7 @@ module ts {
var len: number; // Length of text
var startPos: number; // Start position of whitespace before current token
var tokenPos: number; // Start position of text of current token
var token: number;
var token: SyntaxKind;
var tokenValue: string;
var precedingLineBreak: boolean;
@ -519,10 +520,10 @@ module ts {
return +(text.substring(start, pos));
}
function scanHexDigits(count: number, exact?: boolean): number {
function scanHexDigits(count: number, mustMatchCount?: boolean): number {
var digits = 0;
var value = 0;
while (digits < count || !exact) {
while (digits < count || !mustMatchCount) {
var ch = text.charCodeAt(pos);
if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
value = value * 16 + ch - CharacterCodes._0;
@ -563,60 +564,7 @@ module ts {
}
if (ch === CharacterCodes.backslash) {
result += text.substring(start, pos);
pos++;
if (pos >= len) {
error(Diagnostics.Unexpected_end_of_text);
break;
}
ch = text.charCodeAt(pos++);
switch (ch) {
case CharacterCodes._0:
result += "\0";
break;
case CharacterCodes.b:
result += "\b";
break;
case CharacterCodes.t:
result += "\t";
break;
case CharacterCodes.n:
result += "\n";
break;
case CharacterCodes.v:
result += "\v";
break;
case CharacterCodes.f:
result += "\f";
break;
case CharacterCodes.r:
result += "\r";
break;
case CharacterCodes.singleQuote:
result += "\'";
break;
case CharacterCodes.doubleQuote:
result += "\"";
break;
case CharacterCodes.x:
case CharacterCodes.u:
var ch = scanHexDigits(ch === CharacterCodes.x ? 2 : 4, true);
if (ch >= 0) {
result += String.fromCharCode(ch);
}
else {
error(Diagnostics.Hexadecimal_digit_expected);
}
break;
case CharacterCodes.carriageReturn:
if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) pos++;
break;
case CharacterCodes.lineFeed:
case CharacterCodes.lineSeparator:
case CharacterCodes.paragraphSeparator:
break;
default:
result += String.fromCharCode(ch);
}
result += scanEscapeSequence();
start = pos;
continue;
}
@ -630,13 +578,136 @@ module ts {
return result;
}
/**
* Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
* a literal component of a TemplateExpression.
*/
function scanTemplateAndSetTokenValue(): SyntaxKind {
var startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick;
pos++;
var start = pos;
var contents = ""
var resultingToken: SyntaxKind;
while (true) {
if (pos >= len) {
contents += text.substring(start, pos);
error(Diagnostics.Unexpected_end_of_text);
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
break;
}
var currChar = text.charCodeAt(pos);
// '`'
if (currChar === CharacterCodes.backtick) {
contents += text.substring(start, pos);
pos++;
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
break;
}
// '${'
if (currChar === CharacterCodes.$ && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) {
contents += text.substring(start, pos);
pos += 2;
resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle;
break;
}
// Escape character
if (currChar === CharacterCodes.backslash) {
contents += text.substring(start, pos);
contents += scanEscapeSequence();
start = pos;
continue;
}
// Speculated ECMAScript 6 Spec 11.8.6.1:
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for Template Values
// An explicit EscapeSequence is needed to include a <CR> or <CR><LF> sequence.
if (currChar === CharacterCodes.carriageReturn) {
contents += text.substring(start, pos);
if (pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
pos++;
}
pos++;
contents += "\n";
start = pos;
continue;
}
pos++;
}
Debug.assert(resultingToken !== undefined);
tokenValue = contents;
return resultingToken;
}
function scanEscapeSequence(): string {
pos++;
if (pos >= len) {
error(Diagnostics.Unexpected_end_of_text);
return "";
}
var ch = text.charCodeAt(pos++);
switch (ch) {
case CharacterCodes._0:
return "\0";
case CharacterCodes.b:
return "\b";
case CharacterCodes.t:
return "\t";
case CharacterCodes.n:
return "\n";
case CharacterCodes.v:
return "\v";
case CharacterCodes.f:
return "\f";
case CharacterCodes.r:
return "\r";
case CharacterCodes.singleQuote:
return "\'";
case CharacterCodes.doubleQuote:
return "\"";
case CharacterCodes.x:
case CharacterCodes.u:
var ch = scanHexDigits(ch === CharacterCodes.x ? 2 : 4, /*mustMatchCount*/ true);
if (ch >= 0) {
return String.fromCharCode(ch);
}
else {
error(Diagnostics.Hexadecimal_digit_expected);
return ""
}
// when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
// the line terminator is interpreted to be "the empty code unit sequence".
case CharacterCodes.carriageReturn:
if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
pos++;
}
// fall through
case CharacterCodes.lineFeed:
case CharacterCodes.lineSeparator:
case CharacterCodes.paragraphSeparator:
return ""
default:
return String.fromCharCode(ch);
}
}
// Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX'
// and return code point value if valid Unicode escape is found. Otherwise return -1.
function peekUnicodeEscape(): number {
if (pos + 5 < len && text.charCodeAt(pos + 1) === CharacterCodes.u) {
var start = pos;
pos += 2;
var value = scanHexDigits(4, true);
var value = scanHexDigits(4, /*mustMatchCount*/ true);
pos = start;
return value;
}
@ -735,6 +806,8 @@ module ts {
case CharacterCodes.singleQuote:
tokenValue = scanString();
return token = SyntaxKind.StringLiteral;
case CharacterCodes.backtick:
return token = scanTemplateAndSetTokenValue()
case CharacterCodes.percent:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PercentEqualsToken;
@ -852,7 +925,7 @@ module ts {
case CharacterCodes._0:
if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) {
pos += 2;
var value = scanHexDigits(1, false);
var value = scanHexDigits(1, /*mustMatchCount*/ false);
if (value < 0) {
error(Diagnostics.Hexadecimal_digit_expected);
value = 0;
@ -1038,6 +1111,15 @@ module ts {
return token;
}
/**
* Unconditionally back up and scan a template expression portion.
*/
function reScanTemplateToken(): SyntaxKind {
Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'");
pos = tokenPos;
return token = scanTemplateAndSetTokenValue();
}
function tryScan<T>(callback: () => T): T {
var savePos = pos;
var saveStartPos = startPos;
@ -1086,10 +1168,11 @@ module ts {
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
reScanGreaterToken: reScanGreaterToken,
reScanSlashToken: reScanSlashToken,
reScanTemplateToken: reScanTemplateToken,
scan: scan,
setText: setText,
setTextPos: setTextPos,
tryScan: tryScan
tryScan: tryScan,
};
}
}

View File

@ -20,6 +20,11 @@ module ts {
NumericLiteral,
StringLiteral,
RegularExpressionLiteral,
NoSubstitutionTemplateLiteral,
// Pseudo-literals
TemplateHead,
TemplateMiddle,
TemplateTail,
// Punctuation
OpenBraceToken,
CloseBraceToken,
@ -165,6 +170,7 @@ module ts {
IndexedAccess,
CallExpression,
NewExpression,
TaggedTemplateExpression,
TypeAssertion,
ParenExpression,
FunctionExpression,
@ -173,6 +179,8 @@ module ts {
PostfixOperator,
BinaryExpression,
ConditionalExpression,
TemplateExpression,
TemplateSpan,
OmittedExpression,
// Element
Block,
@ -234,7 +242,11 @@ module ts {
FirstToken = EndOfFileToken,
LastToken = TypeKeyword,
FirstTriviaToken = SingleLineCommentTrivia,
LastTriviaToken = WhitespaceTrivia
LastTriviaToken = WhitespaceTrivia,
FirstLiteralToken = NumericLiteral,
LastLiteralToken = NoSubstitutionTemplateLiteral,
FirstTemplateToken = NoSubstitutionTemplateLiteral,
LastTemplateToken = TemplateTail
}
export enum NodeFlags {
@ -379,13 +391,25 @@ module ts {
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
}
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral
// this means quotes have been removed and escapes have been converted to actual characters. For a NumericLiteral, the
// stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
export interface LiteralExpression extends Expression {
text: string;
}
export interface TemplateExpression extends Expression {
head: LiteralExpression;
templateSpans: NodeArray<TemplateSpan>;
}
// Each of these corresponds to a substitution expression and a template literal, in that order.
// The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
export interface TemplateSpan extends Node {
expression: Expression;
literal: LiteralExpression;
}
export interface ParenExpression extends Expression {
expression: Expression;
}
@ -416,6 +440,11 @@ module ts {
export interface NewExpression extends CallExpression { }
export interface TaggedTemplateExpression extends Expression {
tag: Expression;
template: LiteralExpression | TemplateExpression;
}
export interface TypeAssertion extends Expression {
type: TypeNode;
operand: Expression;
@ -776,7 +805,6 @@ module ts {
ExportValue = 0x00200000, // Exported value marker
ExportType = 0x00400000, // Exported type marker
ExportNamespace = 0x00800000, // Exported namespace marker
Import = 0x01000000, // Import
Instantiated = 0x02000000, // Instantiated symbol
Merged = 0x04000000, // Merged symbol (created during program binding)
@ -1218,6 +1246,7 @@ module ts {
asterisk = 0x2A, // *
at = 0x40, // @
backslash = 0x5C, // \
backtick = 0x60, // `
bar = 0x7C, // |
caret = 0x5E, // ^
closeBrace = 0x7D, // }

View File

@ -92,7 +92,7 @@ class TypeWriterWalker {
private getTypeOfNode(node: ts.Node): ts.Type {
var type = this.checker.getTypeOfNode(node);
ts.Debug.assert(type, "type doesn't exist");
ts.Debug.assert(type !== undefined, "type doesn't exist");
return type;
}
}

View File

@ -175,7 +175,7 @@ module ts.formatting {
function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFile): boolean {
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
var elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
Debug.assert(elseKeyword);
Debug.assert(elseKeyword !== undefined);
var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
return elseKeywordStartLine === childStartLine;

View File

@ -1639,7 +1639,7 @@ module ts {
}
if (syntaxTree !== null) {
Debug.assert(sourceFile);
Debug.assert(sourceFile !== undefined);
// All done, ensure state is up to date
this.currentFileVersion = version;
this.currentFilename = filename;
@ -1847,9 +1847,9 @@ module ts {
): SourceFile {
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
Debug.assert(bucket);
Debug.assert(bucket !== undefined);
var entry = lookUp(bucket, filename);
Debug.assert(entry);
Debug.assert(entry !== undefined);
if (entry.sourceFile.isOpen === isOpen && entry.sourceFile.version === version) {
return entry.sourceFile;
@ -1861,7 +1861,7 @@ module ts {
function releaseDocument(filename: string, compilationSettings: CompilerOptions): void {
var bucket = getBucketForCompilationSettings(compilationSettings, false);
Debug.assert(bucket);
Debug.assert(bucket !== undefined);
var entry = lookUp(bucket, filename);
entry.refCount--;
@ -2471,31 +2471,54 @@ module ts {
}
function isCompletionListBlocker(previousToken: Node): boolean {
return isInStringOrRegularExpressionLiteral(previousToken) ||
return isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
isIdentifierDefinitionLocation(previousToken) ||
isRightOfIllegalDot(previousToken);
}
function isInStringOrRegularExpressionLiteral(previousToken: Node): boolean {
if (previousToken.kind === SyntaxKind.StringLiteral) {
function isInStringOrRegularExpressionOrTemplateLiteral(previousToken: Node): boolean {
if (previousToken.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(previousToken.kind)) {
// The position has to be either: 1. entirely within the token text, or
// 2. at the end position, and the string literal is not terminated
var start = previousToken.getStart();
var end = previousToken.getEnd();
if (start < position && position < end) {
return true;
}
else if (position === end) {
var width = end - start;
var text = previousToken.getSourceFile().text;
return width <= 1 ||
text.charCodeAt(start) !== text.charCodeAt(end - 1) ||
text.charCodeAt(end - 2) === CharacterCodes.backslash;
// If the token is a single character, or its second-to-last charcter indicates an escape code,
// then we can immediately say that we are in the middle of an unclosed string.
if (width <= 1 || text.charCodeAt(end - 2) === CharacterCodes.backslash) {
return true;
}
// Now check if the last character is a closing character for the token.
switch (previousToken.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return text.charCodeAt(start) !== text.charCodeAt(end - 1);
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
return text.charCodeAt(end - 1) !== CharacterCodes.openBrace
|| text.charCodeAt(end - 2) !== CharacterCodes.$;
case SyntaxKind.TemplateTail:
return text.charCodeAt(end - 1) !== CharacterCodes.backtick;
}
return false;
}
}
else if (previousToken.kind === SyntaxKind.RegularExpressionLiteral) {
return previousToken.getStart() < position && position < previousToken.getEnd();
}
return false;
}
@ -2647,7 +2670,7 @@ module ts {
var symbol = lookUp(activeCompletionSession.symbols, entryName);
if (symbol) {
var type = session.typeChecker.getTypeOfSymbol(symbol);
Debug.assert(type, "Could not find type for symbol");
Debug.assert(type !== undefined, "Could not find type for symbol");
var completionEntry = createCompletionEntry(symbol, session.typeChecker);
// TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
// which is permissible given that it is backwards compatible; but really we should consider
@ -2748,7 +2771,7 @@ module ts {
}
if (rootSymbolFlags & SymbolFlags.GetAccessor) return ScriptElementKind.memberVariableElement;
if (rootSymbolFlags & SymbolFlags.SetAccessor) return ScriptElementKind.memberVariableElement;
Debug.assert(rootSymbolFlags & SymbolFlags.Method);
Debug.assert((rootSymbolFlags & SymbolFlags.Method) !== undefined);
}) || ScriptElementKind.memberFunctionElement;
}
return ScriptElementKind.memberVariableElement;
@ -4927,6 +4950,10 @@ module ts {
// TODO: we should get another classification type for these literals.
return ClassificationTypeNames.stringLiteral;
}
else if (isTemplateLiteralKind(tokenKind)) {
// TODO (drosen): we should *also* get another classification type for these literals.
return ClassificationTypeNames.stringLiteral;
}
else if (tokenKind === SyntaxKind.Identifier) {
switch (token.parent.kind) {
case SyntaxKind.ClassDeclaration:
@ -5163,7 +5190,7 @@ module ts {
descriptor = descriptors[i];
}
}
Debug.assert(descriptor);
Debug.assert(descriptor !== undefined);
// We don't want to match something like 'TODOBY', so we make sure a non
// letter/digit follows the match.

View File

@ -219,7 +219,7 @@ module ts.SignatureHelp {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
Debug.assert(list);
Debug.assert(list !== undefined);
return {
list: list,
listItemIndex: 0

View File

@ -197,7 +197,7 @@ module ts {
}
}
Debug.assert(startNode || n.kind === SyntaxKind.SourceFile);
Debug.assert(startNode !== undefined || 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.

View File

@ -0,0 +1,64 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(12,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(14,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(16,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(18,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(20,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(22,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(24,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(24,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(26,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts(26,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTags.ts (10 errors) ====
interface I {
(stringParts: string[], ...rest: boolean[]): I;
g: I;
h: I;
member: I;
thisIsNotATag(x: string): void
[x: number]: I;
}
var f: I;
f `abc`
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`.member
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`.member;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`["member"];
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"];
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`[0].member `abc${1}def${2}ghi`;
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,45 @@
//// [taggedTemplateStringsWithIncompatibleTypedTagsES6.ts]
interface I {
(stringParts: string[], ...rest: boolean[]): I;
g: I;
h: I;
member: I;
thisIsNotATag(x: string): void
[x: number]: I;
}
var f: I;
f `abc`
f `abc${1}def${2}ghi`;
f `abc`.member
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`[0].member `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);
//// [taggedTemplateStringsWithIncompatibleTypedTagsES6.js]
var f;
f `abc`;
f `abc${1}def${2}ghi`;
f `abc`.member;
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`[0].member `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,82 @@
=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithIncompatibleTypedTagsES6.ts ===
interface I {
>I : I
(stringParts: string[], ...rest: boolean[]): I;
>stringParts : string[]
>rest : boolean[]
>I : I
g: I;
>g : I
>I : I
h: I;
>h : I
>I : I
member: I;
>member : I
>I : I
thisIsNotATag(x: string): void
>thisIsNotATag : (x: string) => void
>x : string
[x: number]: I;
>x : number
>I : I
}
var f: I;
>f : I
>I : I
f `abc`
>f : I
f `abc${1}def${2}ghi`;
>f : I
f `abc`.member
>f `abc`.member : any
>f : I
>member : any
f `abc${1}def${2}ghi`.member;
>f `abc${1}def${2}ghi`.member : any
>f : I
>member : any
f `abc`["member"];
>f `abc`["member"] : any
>f : I
f `abc${1}def${2}ghi`["member"];
>f `abc${1}def${2}ghi`["member"] : any
>f : I
f `abc`[0].member `abc${1}def${2}ghi`;
>f `abc`[0].member : any
>f `abc`[0] : any
>f : I
>member : any
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
>f `abc${1}def${2}ghi`["member"].member : any
>f `abc${1}def${2}ghi`["member"] : any
>f : I
>member : any
f.thisIsNotATag(`abc`);
>f.thisIsNotATag(`abc`) : void
>f.thisIsNotATag : (x: string) => void
>f : I
>thisIsNotATag : (x: string) => void
f.thisIsNotATag(`abc${1}def${2}ghi`);
>f.thisIsNotATag(`abc${1}def${2}ghi`) : void
>f.thisIsNotATag : (x: string) => void
>f : I
>thisIsNotATag : (x: string) => void

View File

@ -0,0 +1,21 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsWithManyCallAndMemberExpressions.ts(13,21): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithManyCallAndMemberExpressions.ts (1 errors) ====
interface I {
(strs: string[], subs: number[]): I;
member: {
new (s: string): {
new (n: number): {
new (): boolean;
}
}
};
}
var f: I;
var x = new new new f `abc${ 0 }def`.member("hello")(42) === true;
~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.

View File

@ -0,0 +1,20 @@
//// [taggedTemplateStringsWithManyCallAndMemberExpressionsES6.ts]
interface I {
(strs: string[], subs: number[]): I;
member: {
new (s: string): {
new (n: number): {
new (): boolean;
}
}
};
}
var f: I;
var x = new new new f `abc${ 0 }def`.member("hello")(42) === true;
//// [taggedTemplateStringsWithManyCallAndMemberExpressionsES6.js]
var f;
var x = new new new f `abc${0}def`.member("hello")(42) === true;

View File

@ -0,0 +1,38 @@
=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithManyCallAndMemberExpressionsES6.ts ===
interface I {
>I : I
(strs: string[], subs: number[]): I;
>strs : string[]
>subs : number[]
>I : I
member: {
>member : new (s: string) => new (n: number) => new () => boolean
new (s: string): {
>s : string
new (n: number): {
>n : number
new (): boolean;
}
}
};
}
var f: I;
>f : I
>I : I
var x = new new new f `abc${ 0 }def`.member("hello")(42) === true;
>x : boolean
>new new new f `abc${ 0 }def`.member("hello")(42) === true : boolean
>new new new f `abc${ 0 }def`.member("hello")(42) : any
>new new f `abc${ 0 }def`.member("hello")(42) : any
>new f `abc${ 0 }def`.member("hello") : any
>f `abc${ 0 }def`.member : any
>f : I
>member : any

View File

@ -0,0 +1,64 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(3,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(5,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(7,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(9,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(11,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(13,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(15,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(17,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(19,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(19,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(21,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts(21,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAny.ts (12 errors) ====
var f: any;
f `abc`
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f.g.h `abc`
~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f.g.h `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`.member
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`.member;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`["member"];
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"];
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`["member"].someOtherTag `abc${1}def${2}ghi`;
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"].someOtherTag `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,40 @@
//// [taggedTemplateStringsWithTagsTypedAsAnyES6.ts]
var f: any;
f `abc`
f `abc${1}def${2}ghi`;
f.g.h `abc`
f.g.h `abc${1}def${2}ghi`;
f `abc`.member
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`["member"].someOtherTag `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].someOtherTag `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);
//// [taggedTemplateStringsWithTagsTypedAsAnyES6.js]
var f;
f `abc`;
f `abc${1}def${2}ghi`;
f.g.h `abc`;
f.g.h `abc${1}def${2}ghi`;
f `abc`.member;
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`["member"].someOtherTag `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].someOtherTag `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,66 @@
=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTagsTypedAsAnyES6.ts ===
var f: any;
>f : any
f `abc`
>f : any
f `abc${1}def${2}ghi`;
>f : any
f.g.h `abc`
>f.g.h : any
>f.g : any
>f : any
>g : any
>h : any
f.g.h `abc${1}def${2}ghi`;
>f.g.h : any
>f.g : any
>f : any
>g : any
>h : any
f `abc`.member
>f `abc`.member : any
>f : any
>member : any
f `abc${1}def${2}ghi`.member;
>f `abc${1}def${2}ghi`.member : any
>f : any
>member : any
f `abc`["member"];
>f `abc`["member"] : any
>f : any
f `abc${1}def${2}ghi`["member"];
>f `abc${1}def${2}ghi`["member"] : any
>f : any
f `abc`["member"].someOtherTag `abc${1}def${2}ghi`;
>f `abc`["member"].someOtherTag : any
>f `abc`["member"] : any
>f : any
>someOtherTag : any
f `abc${1}def${2}ghi`["member"].someOtherTag `abc${1}def${2}ghi`;
>f `abc${1}def${2}ghi`["member"].someOtherTag : any
>f `abc${1}def${2}ghi`["member"] : any
>f : any
>someOtherTag : any
f.thisIsNotATag(`abc`);
>f.thisIsNotATag(`abc`) : any
>f.thisIsNotATag : any
>f : any
>thisIsNotATag : any
f.thisIsNotATag(`abc${1}def${2}ghi`);
>f.thisIsNotATag(`abc${1}def${2}ghi`) : any
>f.thisIsNotATag : any
>f : any
>thisIsNotATag : any

View File

@ -0,0 +1,64 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(12,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(14,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(16,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(18,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(20,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(22,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(24,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(24,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(26,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts(26,1): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTags.ts (10 errors) ====
interface I {
(stringParts: string[], ...rest: number[]): I;
g: I;
h: I;
member: I;
thisIsNotATag(x: string): void
[x: number]: I;
}
var f: I;
f `abc`
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`.member
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`.member;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`["member"];
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"];
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc`[0].member `abc${1}def${2}ghi`;
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,45 @@
//// [taggedTemplateStringsWithTypedTagsES6.ts]
interface I {
(stringParts: string[], ...rest: number[]): I;
g: I;
h: I;
member: I;
thisIsNotATag(x: string): void
[x: number]: I;
}
var f: I;
f `abc`
f `abc${1}def${2}ghi`;
f `abc`.member
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`[0].member `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);
//// [taggedTemplateStringsWithTypedTagsES6.js]
var f;
f `abc`;
f `abc${1}def${2}ghi`;
f `abc`.member;
f `abc${1}def${2}ghi`.member;
f `abc`["member"];
f `abc${1}def${2}ghi`["member"];
f `abc`[0].member `abc${1}def${2}ghi`;
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
f.thisIsNotATag(`abc`);
f.thisIsNotATag(`abc${1}def${2}ghi`);

View File

@ -0,0 +1,82 @@
=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypedTagsES6.ts ===
interface I {
>I : I
(stringParts: string[], ...rest: number[]): I;
>stringParts : string[]
>rest : number[]
>I : I
g: I;
>g : I
>I : I
h: I;
>h : I
>I : I
member: I;
>member : I
>I : I
thisIsNotATag(x: string): void
>thisIsNotATag : (x: string) => void
>x : string
[x: number]: I;
>x : number
>I : I
}
var f: I;
>f : I
>I : I
f `abc`
>f : I
f `abc${1}def${2}ghi`;
>f : I
f `abc`.member
>f `abc`.member : any
>f : I
>member : any
f `abc${1}def${2}ghi`.member;
>f `abc${1}def${2}ghi`.member : any
>f : I
>member : any
f `abc`["member"];
>f `abc`["member"] : any
>f : I
f `abc${1}def${2}ghi`["member"];
>f `abc${1}def${2}ghi`["member"] : any
>f : I
f `abc`[0].member `abc${1}def${2}ghi`;
>f `abc`[0].member : any
>f `abc`[0] : any
>f : I
>member : any
f `abc${1}def${2}ghi`["member"].member `abc${1}def${2}ghi`;
>f `abc${1}def${2}ghi`["member"].member : any
>f `abc${1}def${2}ghi`["member"] : any
>f : I
>member : any
f.thisIsNotATag(`abc`);
>f.thisIsNotATag(`abc`) : void
>f.thisIsNotATag : (x: string) => void
>f : I
>thisIsNotATag : (x: string) => void
f.thisIsNotATag(`abc${1}def${2}ghi`);
>f.thisIsNotATag(`abc${1}def${2}ghi`) : void
>f.thisIsNotATag : (x: string) => void
>f : I
>thisIsNotATag : (x: string) => void

View File

@ -0,0 +1,5 @@
//// [templateStringInArray.ts]
var x = [1, 2, `abc${ 123 }def`];
//// [templateStringInArray.js]
var x = [1, 2, ("abc" + 123 + "def")];

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInArray.ts ===
var x = [1, 2, `abc${ 123 }def`];
>x : (string | number)[]
>[1, 2, `abc${ 123 }def`] : (string | number)[]

View File

@ -0,0 +1,5 @@
//// [templateStringInArrowFunction.ts]
var x = x => `abc${ x }def`;
//// [templateStringInArrowFunction.js]
var x = function (x) { return ("abc" + x + "def"); };

View File

@ -0,0 +1,7 @@
=== tests/cases/conformance/es6/templates/templateStringInArrowFunction.ts ===
var x = x => `abc${ x }def`;
>x : (x: any) => string
>x => `abc${ x }def` : (x: any) => string
>x : any
>x : unknown

View File

@ -0,0 +1,5 @@
//// [templateStringInArrowFunctionES6.ts]
var x = x => `abc${ x }def`;
//// [templateStringInArrowFunctionES6.js]
var x = function (x) { return `abc${x}def`; };

View File

@ -0,0 +1,7 @@
=== tests/cases/conformance/es6/templates/templateStringInArrowFunctionES6.ts ===
var x = x => `abc${ x }def`;
>x : (x: any) => string
>x => `abc${ x }def` : (x: any) => string
>x : any
>x : unknown

View File

@ -0,0 +1,5 @@
//// [templateStringInBinaryAddition.ts]
var x = 10 + `abc${ 10 }def`;
//// [templateStringInBinaryAddition.js]
var x = 10 + ("abc" + 10 + "def");

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInBinaryAddition.ts ===
var x = 10 + `abc${ 10 }def`;
>x : string
>10 + `abc${ 10 }def` : string

View File

@ -0,0 +1,5 @@
//// [templateStringInBinaryAdditionES6.ts]
var x = 10 + `abc${ 10 }def`;
//// [templateStringInBinaryAdditionES6.js]
var x = 10 + `abc${10}def`;

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInBinaryAdditionES6.ts ===
var x = 10 + `abc${ 10 }def`;
>x : string
>10 + `abc${ 10 }def` : string

View File

@ -0,0 +1,5 @@
//// [templateStringInConditional.ts]
var x = `abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def`;
//// [templateStringInConditional.js]
var x = "abc" + " " + "def" ? "abc" + " " + "def" : "abc" + " " + "def";

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInConditional.ts ===
var x = `abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def`;
>x : string
>`abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def` : string

View File

@ -0,0 +1,5 @@
//// [templateStringInConditionalES6.ts]
var x = `abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def`;
//// [templateStringInConditionalES6.js]
var x = `abc${" "}def` ? `abc${" "}def` : `abc${" "}def`;

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInConditionalES6.ts ===
var x = `abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def`;
>x : string
>`abc${ " " }def` ? `abc${ " " }def` : `abc${ " " }def` : string

View File

@ -0,0 +1,5 @@
//// [templateStringInDeleteExpression.ts]
delete `abc${0}abc`;
//// [templateStringInDeleteExpression.js]
delete ("abc" + 0 + "abc");

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/templates/templateStringInDeleteExpression.ts ===
delete `abc${0}abc`;
>delete `abc${0}abc` : boolean

View File

@ -0,0 +1,5 @@
//// [templateStringInDeleteExpressionES6.ts]
delete `abc${0}abc`;
//// [templateStringInDeleteExpressionES6.js]
delete `abc${0}abc`;

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/templates/templateStringInDeleteExpressionES6.ts ===
delete `abc${0}abc`;
>delete `abc${0}abc` : boolean

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInDivision.ts(1,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/es6/templates/templateStringInDivision.ts (1 errors) ====
var x = `abc${ 1 }def` / 1;
~~~~~~~~~~~~~~
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

View File

@ -0,0 +1,5 @@
//// [templateStringInDivision.ts]
var x = `abc${ 1 }def` / 1;
//// [templateStringInDivision.js]
var x = ("abc" + 1 + "def") / 1;

View File

@ -0,0 +1,8 @@
//// [templateStringInEqualityChecks.ts]
var x = `abc${0}abc` === `abc` ||
`abc` !== `abc${0}abc` &&
`abc${0}abc` == "abc0abc" &&
"abc0abc" !== `abc${0}abc`;
//// [templateStringInEqualityChecks.js]
var x = "abc" + 0 + "abc" === "abc" || "abc" !== "abc" + 0 + "abc" && "abc" + 0 + "abc" == "abc0abc" && "abc0abc" !== "abc" + 0 + "abc";

View File

@ -0,0 +1,17 @@
=== tests/cases/conformance/es6/templates/templateStringInEqualityChecks.ts ===
var x = `abc${0}abc` === `abc` ||
>x : boolean
>`abc${0}abc` === `abc` || `abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" && "abc0abc" !== `abc${0}abc` : boolean
>`abc${0}abc` === `abc` : boolean
`abc` !== `abc${0}abc` &&
>`abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" && "abc0abc" !== `abc${0}abc` : boolean
>`abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" : boolean
>`abc` !== `abc${0}abc` : boolean
`abc${0}abc` == "abc0abc" &&
>`abc${0}abc` == "abc0abc" : boolean
"abc0abc" !== `abc${0}abc`;
>"abc0abc" !== `abc${0}abc` : boolean

View File

@ -0,0 +1,8 @@
//// [templateStringInEqualityChecksES6.ts]
var x = `abc${0}abc` === `abc` ||
`abc` !== `abc${0}abc` &&
`abc${0}abc` == "abc0abc" &&
"abc0abc" !== `abc${0}abc`;
//// [templateStringInEqualityChecksES6.js]
var x = `abc${0}abc` === `abc` || `abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" && "abc0abc" !== `abc${0}abc`;

View File

@ -0,0 +1,17 @@
=== tests/cases/conformance/es6/templates/templateStringInEqualityChecksES6.ts ===
var x = `abc${0}abc` === `abc` ||
>x : boolean
>`abc${0}abc` === `abc` || `abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" && "abc0abc" !== `abc${0}abc` : boolean
>`abc${0}abc` === `abc` : boolean
`abc` !== `abc${0}abc` &&
>`abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" && "abc0abc" !== `abc${0}abc` : boolean
>`abc` !== `abc${0}abc` && `abc${0}abc` == "abc0abc" : boolean
>`abc` !== `abc${0}abc` : boolean
`abc${0}abc` == "abc0abc" &&
>`abc${0}abc` == "abc0abc" : boolean
"abc0abc" !== `abc${0}abc`;
>"abc0abc" !== `abc${0}abc` : boolean

View File

@ -0,0 +1,11 @@
//// [templateStringInFunctionExpression.ts]
var x = function y() {
`abc${ 0 }def`
return `abc${ 0 }def`;
};
//// [templateStringInFunctionExpression.js]
var x = function y() {
"abc" + 0 + "def";
return "abc" + 0 + "def";
};

View File

@ -0,0 +1,9 @@
=== tests/cases/conformance/es6/templates/templateStringInFunctionExpression.ts ===
var x = function y() {
>x : () => string
>function y() { `abc${ 0 }def` return `abc${ 0 }def`;} : () => string
>y : () => string
`abc${ 0 }def`
return `abc${ 0 }def`;
};

View File

@ -0,0 +1,11 @@
//// [templateStringInFunctionExpressionES6.ts]
var x = function y() {
`abc${ 0 }def`
return `abc${ 0 }def`;
};
//// [templateStringInFunctionExpressionES6.js]
var x = function y() {
`abc${0}def`;
return `abc${0}def`;
};

View File

@ -0,0 +1,9 @@
=== tests/cases/conformance/es6/templates/templateStringInFunctionExpressionES6.ts ===
var x = function y() {
>x : () => string
>function y() { `abc${ 0 }def` return `abc${ 0 }def`;} : () => string
>y : () => string
`abc${ 0 }def`
return `abc${ 0 }def`;
};

View File

@ -0,0 +1,20 @@
tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,12): error TS1138: Parameter declaration expected.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,19): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,1): error TS2394: Overload signature is not compatible with function implementation.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts(1,10): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterType.ts (4 errors) ====
function f(`hello`);
~~~~~~~
!!! error TS1138: Parameter declaration expected.
~
!!! error TS1005: ';' expected.
~~~~~~~~~~~
!!! error TS2394: Overload signature is not compatible with function implementation.
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
function f(x: string);
function f(x: string) {
return x;
}

View File

@ -0,0 +1,20 @@
tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,12): error TS1138: Parameter declaration expected.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,19): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,1): error TS2394: Overload signature is not compatible with function implementation.
tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts(1,10): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/conformance/es6/templates/templateStringInFunctionParameterTypeES6.ts (4 errors) ====
function f(`hello`);
~~~~~~~
!!! error TS1138: Parameter declaration expected.
~
!!! error TS1005: ';' expected.
~~~~~~~~~~~
!!! error TS2394: Overload signature is not compatible with function implementation.
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
function f(x: string);
function f(x: string) {
return x;
}

View File

@ -0,0 +1,5 @@
//// [templateStringInInOperator.ts]
var x = `${ "hi" }` in { hi: 10, hello: 20};
//// [templateStringInInOperator.js]
var x = "" + "hi" in { hi: 10, hello: 20 };

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInInOperator.ts ===
var x = `${ "hi" }` in { hi: 10, hello: 20};
>x : boolean
>`${ "hi" }` in { hi: 10, hello: 20} : boolean
>{ hi: 10, hello: 20} : { hi: number; hello: number; }
>hi : number
>hello : number

View File

@ -0,0 +1,5 @@
//// [templateStringInInOperatorES6.ts]
var x = `${ "hi" }` in { hi: 10, hello: 20};
//// [templateStringInInOperatorES6.js]
var x = `${"hi"}` in { hi: 10, hello: 20 };

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInInOperatorES6.ts ===
var x = `${ "hi" }` in { hi: 10, hello: 20};
>x : boolean
>`${ "hi" }` in { hi: 10, hello: 20} : boolean
>{ hi: 10, hello: 20} : { hi: number; hello: number; }
>hi : number
>hello : number

View File

@ -0,0 +1,5 @@
//// [templateStringInIndexExpression.ts]
`abc${0}abc`[`0`];
//// [templateStringInIndexExpression.js]
("abc" + 0 + "abc")["0"];

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/templates/templateStringInIndexExpression.ts ===
`abc${0}abc`[`0`];
>`abc${0}abc`[`0`] : any

View File

@ -0,0 +1,5 @@
//// [templateStringInIndexExpressionES6.ts]
`abc${0}abc`[`0`];
//// [templateStringInIndexExpressionES6.js]
`abc${0}abc`[`0`];

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/templates/templateStringInIndexExpressionES6.ts ===
`abc${0}abc`[`0`];
>`abc${0}abc`[`0`] : any

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInInstanceOf.ts(1,9): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
==== tests/cases/conformance/es6/templates/templateStringInInstanceOf.ts (1 errors) ====
var x = `abc${ 0 }def` instanceof String;
~~~~~~~~~~~~~~
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.

View File

@ -0,0 +1,5 @@
//// [templateStringInInstanceOf.ts]
var x = `abc${ 0 }def` instanceof String;
//// [templateStringInInstanceOf.js]
var x = "abc" + 0 + "def" instanceof String;

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInInstanceOfES6.ts(1,9): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
==== tests/cases/conformance/es6/templates/templateStringInInstanceOfES6.ts (1 errors) ====
var x = `abc${ 0 }def` instanceof String;
~~~~~~~~~~~~~~
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.

View File

@ -0,0 +1,5 @@
//// [templateStringInInstanceOfES6.ts]
var x = `abc${ 0 }def` instanceof String;
//// [templateStringInInstanceOfES6.js]
var x = `abc${0}def` instanceof String;

View File

@ -0,0 +1,38 @@
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,21): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,24): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,1): error TS2304: Cannot find name 'declare'.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS2304: Cannot find name 'module'.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,1): error TS2304: Cannot find name 'declare'.
tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS2304: Cannot find name 'module'.
==== tests/cases/conformance/es6/templates/templateStringInModuleName.ts (10 errors) ====
declare module `M1` {
~~~~~~
!!! error TS1005: ';' expected.
~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~
!!! error TS1005: ';' expected.
~~~~~~~
!!! error TS2304: Cannot find name 'declare'.
~~~~~~
!!! error TS2304: Cannot find name 'module'.
}
declare module `M${2}` {
~~~~~~
!!! error TS1005: ';' expected.
~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~
!!! error TS1005: ';' expected.
~~~~~~~
!!! error TS2304: Cannot find name 'declare'.
~~~~~~
!!! error TS2304: Cannot find name 'module'.
}

View File

@ -0,0 +1,32 @@
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,9): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,21): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,9): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,24): error TS1005: ';' expected.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,1): error TS2304: Cannot find name 'declare'.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,9): error TS2304: Cannot find name 'module'.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,1): error TS2304: Cannot find name 'declare'.
tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,9): error TS2304: Cannot find name 'module'.
==== tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts (8 errors) ====
declare module `M1` {
~~~~~~
!!! error TS1005: ';' expected.
~
!!! error TS1005: ';' expected.
~~~~~~~
!!! error TS2304: Cannot find name 'declare'.
~~~~~~
!!! error TS2304: Cannot find name 'module'.
}
declare module `M${2}` {
~~~~~~
!!! error TS1005: ';' expected.
~
!!! error TS1005: ';' expected.
~~~~~~~
!!! error TS2304: Cannot find name 'declare'.
~~~~~~
!!! error TS2304: Cannot find name 'module'.
}

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInModulo.ts(1,13): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/es6/templates/templateStringInModulo.ts (1 errors) ====
var x = 1 % `abc${ 1 }def`;
~~~~~~~~~~~~~~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

View File

@ -0,0 +1,5 @@
//// [templateStringInModulo.ts]
var x = 1 % `abc${ 1 }def`;
//// [templateStringInModulo.js]
var x = 1 % ("abc" + 1 + "def");

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInModuloES6.ts(1,13): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/es6/templates/templateStringInModuloES6.ts (1 errors) ====
var x = 1 % `abc${ 1 }def`;
~~~~~~~~~~~~~~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

View File

@ -0,0 +1,5 @@
//// [templateStringInModuloES6.ts]
var x = 1 % `abc${ 1 }def`;
//// [templateStringInModuloES6.js]
var x = 1 % `abc${1}def`;

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInMultiplication.ts(1,13): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/es6/templates/templateStringInMultiplication.ts (1 errors) ====
var x = 1 * `abc${ 1 }def`;
~~~~~~~~~~~~~~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

View File

@ -0,0 +1,5 @@
//// [templateStringInMultiplication.ts]
var x = 1 * `abc${ 1 }def`;
//// [templateStringInMultiplication.js]
var x = 1 * ("abc" + 1 + "def");

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInMultiplicationES6.ts(1,13): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/es6/templates/templateStringInMultiplicationES6.ts (1 errors) ====
var x = 1 * `abc${ 1 }def`;
~~~~~~~~~~~~~~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

View File

@ -0,0 +1,5 @@
//// [templateStringInMultiplicationES6.ts]
var x = 1 * `abc${ 1 }def`;
//// [templateStringInMultiplicationES6.js]
var x = 1 * `abc${1}def`;

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInNewOperator.ts(1,9): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
==== tests/cases/conformance/es6/templates/templateStringInNewOperator.ts (1 errors) ====
var x = new `abc${ 1 }def`;
~~~~~~~~~~~~~~~~~~
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

View File

@ -0,0 +1,5 @@
//// [templateStringInNewOperator.ts]
var x = new `abc${ 1 }def`;
//// [templateStringInNewOperator.js]
var x = new ("abc" + 1 + "def");

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/templates/templateStringInNewOperatorES6.ts(1,9): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
==== tests/cases/conformance/es6/templates/templateStringInNewOperatorES6.ts (1 errors) ====
var x = new `abc${ 1 }def`;
~~~~~~~~~~~~~~~~~~
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

View File

@ -0,0 +1,5 @@
//// [templateStringInNewOperatorES6.ts]
var x = new `abc${ 1 }def`;
//// [templateStringInNewOperatorES6.js]
var x = new `abc${1}def`;

View File

@ -0,0 +1,24 @@
tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts(1,9): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts(3,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts(3,8): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts(3,10): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts(4,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInObjectLiteral.ts (5 errors) ====
var x = {
~
a: `abc${ 123 }def`,
~~~~~~~~~~~~~~~~~~~~~~~~
`b`: 321
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,19 @@
tests/cases/conformance/es6/templates/templateStringInObjectLiteralES6.ts(3,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteralES6.ts(3,8): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteralES6.ts(3,10): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInObjectLiteralES6.ts(4,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInObjectLiteralES6.ts (4 errors) ====
var x = {
a: `abc${ 123 }def`,
`b`: 321
~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,5 @@
//// [templateStringInParentheses.ts]
var x = (`abc${0}abc`);
//// [templateStringInParentheses.js]
var x = ("abc" + 0 + "abc");

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInParentheses.ts ===
var x = (`abc${0}abc`);
>x : string
>(`abc${0}abc`) : string

View File

@ -0,0 +1,5 @@
//// [templateStringInParenthesesES6.ts]
var x = (`abc${0}abc`);
//// [templateStringInParenthesesES6.js]
var x = (`abc${0}abc`);

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/templates/templateStringInParenthesesES6.ts ===
var x = (`abc${0}abc`);
>x : string
>(`abc${0}abc`) : string

View File

@ -0,0 +1,9 @@
//// [templateStringInPropertyAssignment.ts]
var x = {
a: `abc${ 123 }def${ 456 }ghi`
}
//// [templateStringInPropertyAssignment.js]
var x = {
a: "abc" + 123 + "def" + 456 + "ghi"
};

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInPropertyAssignment.ts ===
var x = {
>x : { a: string; }
>{ a: `abc${ 123 }def${ 456 }ghi`} : { a: string; }
a: `abc${ 123 }def${ 456 }ghi`
>a : string
}

View File

@ -0,0 +1,9 @@
//// [templateStringInPropertyAssignmentES6.ts]
var x = {
a: `abc${ 123 }def${ 456 }ghi`
}
//// [templateStringInPropertyAssignmentES6.js]
var x = {
a: `abc${123}def${456}ghi`
};

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInPropertyAssignmentES6.ts ===
var x = {
>x : { a: string; }
>{ a: `abc${ 123 }def${ 456 }ghi`} : { a: string; }
a: `abc${ 123 }def${ 456 }ghi`
>a : string
}

View File

@ -0,0 +1,22 @@
tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts(1,9): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts(2,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts(2,8): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts(2,10): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInPropertyName1.ts (5 errors) ====
var x = {
~
`a`: 321
~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,22 @@
tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts(1,9): error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts(2,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts(2,32): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts(2,34): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInPropertyName2.ts (5 errors) ====
var x = {
~
`abc${ 123 }def${ 456 }ghi`: 321
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1160: Tagged templates are only available when targeting ECMAScript 6 and higher.
~~~~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,18 @@
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_1.ts(2,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_1.ts(2,8): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_1.ts(2,10): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_1.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_1.ts (4 errors) ====
var x = {
`a`: 321
~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,18 @@
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_2.ts(2,5): error TS1136: Property assignment expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_2.ts(2,32): error TS1005: ',' expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_2.ts(2,34): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_2.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/templates/templateStringInPropertyNameES6_2.ts (4 errors) ====
var x = {
`abc${ 123 }def${ 456 }ghi`: 321
~~~~~~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~~~
!!! error TS1134: Variable declaration expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,15 @@
//// [templateStringInSwitchAndCase.ts]
switch (`abc${0}abc`) {
case `abc`:
case `123`:
case `abc${0}abc`:
`def${1}def`;
}
//// [templateStringInSwitchAndCase.js]
switch ("abc" + 0 + "abc") {
case "abc":
case "123":
case "abc" + 0 + "abc":
"def" + 1 + "def";
}

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInSwitchAndCase.ts ===
switch (`abc${0}abc`) {
No type information for this code. case `abc`:
No type information for this code. case `123`:
No type information for this code. case `abc${0}abc`:
No type information for this code. `def${1}def`;
No type information for this code.}
No type information for this code.

View File

@ -0,0 +1,15 @@
//// [templateStringInSwitchAndCaseES6.ts]
switch (`abc${0}abc`) {
case `abc`:
case `123`:
case `abc${0}abc`:
`def${1}def`;
}
//// [templateStringInSwitchAndCaseES6.js]
switch (`abc${0}abc`) {
case `abc`:
case `123`:
case `abc${0}abc`:
`def${1}def`;
}

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/templates/templateStringInSwitchAndCaseES6.ts ===
switch (`abc${0}abc`) {
No type information for this code. case `abc`:
No type information for this code. case `123`:
No type information for this code. case `abc${0}abc`:
No type information for this code. `def${1}def`;
No type information for this code.}
No type information for this code.

View File

@ -0,0 +1,5 @@
//// [templateStringInTypeAssertion.ts]
var x = <any>`abc${ 123 }def`;
//// [templateStringInTypeAssertion.js]
var x = ("abc" + 123 + "def");

Some files were not shown because too many files have changed in this diff Show More