diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index e4ffa396fb7..2b5b5550c06 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -85,12 +85,12 @@ class PreferConstWalker extends Lint.RuleWalker { visitBinaryExpression(node: ts.BinaryExpression) { if (isAssignmentOperator(node.operatorToken.kind)) { - this.visitLHSExpressions(node.left); + this.visitLeftHandSideExpression(node.left); } super.visitBinaryExpression(node); } - private visitLHSExpressions(node: ts.Expression) { + private visitLeftHandSideExpression(node: ts.Expression) { while (node.kind === ts.SyntaxKind.ParenthesizedExpression) { node = (node as ts.ParenthesizedExpression).expression; } @@ -106,18 +106,23 @@ class PreferConstWalker extends Lint.RuleWalker { if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { const pattern = node as ts.ObjectLiteralExpression; for (const element of pattern.properties) { - if (element.name.kind === ts.SyntaxKind.Identifier) { - this.markAssignment(element.name as ts.Identifier); + const kind = element.kind; + + if (kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + this.markAssignment((element as ts.ShorthandPropertyAssignment).name); } - else if (isBindingPattern(element.name)) { - this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern); + else if (kind === ts.SyntaxKind.PropertyAssignment) { + this.visitLeftHandSideExpression((element as ts.PropertyAssignment).initializer); + } + else { + // Should we throw an exception? } } } else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) { const pattern = node as ts.ArrayLiteralExpression; for (const element of pattern.elements) { - this.visitLHSExpressions(element); + this.visitLeftHandSideExpression(element); } } } @@ -145,7 +150,7 @@ class PreferConstWalker extends Lint.RuleWalker { private visitAnyUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) { if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) { - this.visitLHSExpressions(node.operand); + this.visitLeftHandSideExpression(node.operand); } } @@ -211,12 +216,12 @@ class PreferConstWalker extends Lint.RuleWalker { } } - private collectNameIdentifiers(value: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map) { + private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map) { if (node.kind === ts.SyntaxKind.Identifier) { - table[(node as ts.Identifier).text] = {declaration: value, usages: 0}; + table[(node as ts.Identifier).text] = { declaration, usages: 0 }; } else { - this.collectBindingPatternIdentifiers(value, node as ts.BindingPattern, table); + this.collectBindingPatternIdentifiers(declaration, node as ts.BindingPattern, table); } } diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8b88da5b749..6b04e22551d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -139,6 +139,8 @@ namespace ts { file.classifiableNames = classifiableNames; } + file = undefined; + options = undefined; parent = undefined; container = undefined; blockScopeContainer = undefined; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 378fd85265f..009447df19a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -476,15 +476,41 @@ namespace ts { // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = getSymbol(location.locals, name, meaning)) { - // Type parameters of a function are in scope in the entire function declaration, including the parameter - // list and return type. However, local types are only in scope in the function body. - if (!(meaning & SymbolFlags.Type) || - !(result.flags & (SymbolFlags.Type & ~SymbolFlags.TypeParameter)) || - !isFunctionLike(location) || - lastLocation === (location).body) { + let useResult = true; + if (isFunctionLike(location) && lastLocation && lastLocation !== (location).body) { + // symbol lookup restrictions for function-like declarations + // - Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + // - parameters are only in the scope of function body + if (meaning & result.flags & SymbolFlags.Type) { + useResult = result.flags & SymbolFlags.TypeParameter + // type parameters are visible in parameter list, return type and type parameter list + ? lastLocation === (location).type || + lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.TypeParameter + // local types not visible outside the function body + : false; + } + if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { + // parameters are visible only inside function body, parameter list and return type + // technically for parameter list case here we might mix parameters and variables declared in function, + // however it is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. + useResult = + lastLocation.kind === SyntaxKind.Parameter || + ( + lastLocation === (location).type && + result.valueDeclaration.kind === SyntaxKind.Parameter + ); + } + } + + if (useResult) { break loop; } - result = undefined; + else { + result = undefined; + } } } switch (location.kind) { @@ -9879,7 +9905,7 @@ namespace ts { return type; } - function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) { + function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const isAsync = isAsyncFunctionLike(node); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e4cd57542a7..bdeac582bbf 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -516,7 +516,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let decorateEmitted: boolean; let paramEmitted: boolean; let awaiterEmitted: boolean; - let tempFlags: TempFlags; + let tempFlags: TempFlags = 0; let tempVariables: Identifier[]; let tempParameters: Identifier[]; let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; @@ -584,33 +584,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return doEmit; function doEmit(jsFilePath: string, rootFile?: SourceFile) { - // reset the state - writer.reset(); - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; - exportFunctionForFile = undefined; generatedNameSet = {}; nodeToGeneratedName = []; - computedPropertyNamesToGeneratedNames = undefined; - convertedLoopState = undefined; - - extendsEmitted = false; - decorateEmitted = false; - paramEmitted = false; - awaiterEmitted = false; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStars = undefined; - detachedCommentsInfo = undefined; - sourceMapData = undefined; - isEs6Module = false; - renamedDependencies = undefined; - isCurrentFileExternalModule = false; root = rootFile; if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { @@ -634,6 +609,34 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM); + + // reset the state + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = undefined; + nodeToGeneratedName = undefined; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = undefined; } function emitSourceFile(sourceFile: SourceFile): void { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9a72593d3b0..1ffea764bfa 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1157,7 +1157,7 @@ namespace ts { } function parseAnyContextualModifier(): boolean { - return isModifier(token) && tryParse(nextTokenCanFollowModifier); + return isModifierKind(token) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier(): boolean { @@ -2004,7 +2004,7 @@ namespace ts { } function isStartOfParameter(): boolean { - return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifier(token) || token === SyntaxKind.AtToken; + return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken; } function setModifiers(node: Node, modifiers: ModifiersArray) { @@ -2025,7 +2025,7 @@ namespace ts { node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) { + if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifierKind(token)) { // in cases like // 'use strict' // function foo(static) @@ -2132,8 +2132,8 @@ namespace ts { parseSemicolon(); } - function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration { - const node = createNode(kind); + function parseSignatureMember(kind: SyntaxKind): CallSignatureDeclaration | ConstructSignatureDeclaration { + const node = createNode(kind); if (kind === SyntaxKind.ConstructSignature) { parseExpected(SyntaxKind.NewKeyword); } @@ -2172,7 +2172,7 @@ namespace ts { return true; } - if (isModifier(token)) { + if (isModifierKind(token)) { nextToken(); if (isIdentifier()) { return true; @@ -2215,13 +2215,13 @@ namespace ts { return finishNode(node); } - function parsePropertyOrMethodSignature(): Declaration { + function parsePropertyOrMethodSignature(): PropertySignature | MethodSignature { const fullStart = scanner.getStartPos(); const name = parsePropertyName(); const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { - const method = createNode(SyntaxKind.MethodSignature, fullStart); + const method = createNode(SyntaxKind.MethodSignature, fullStart); method.name = name; method.questionToken = questionToken; @@ -2232,7 +2232,7 @@ namespace ts { return finishNode(method); } else { - const property = createNode(SyntaxKind.PropertySignature, fullStart); + const property = createNode(SyntaxKind.PropertySignature, fullStart); property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -2248,7 +2248,7 @@ namespace ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - if (isModifier(token)) { + if (isModifierKind(token)) { const result = lookAhead(isStartOfIndexSignatureDeclaration); if (result) { return result; @@ -2260,7 +2260,7 @@ namespace ts { } function isStartOfIndexSignatureDeclaration() { - while (isModifier(token)) { + while (isModifierKind(token)) { nextToken(); } @@ -2276,7 +2276,7 @@ namespace ts { canParseSemicolon(); } - function parseTypeMember(): Declaration { + function parseTypeMember(): TypeElement { switch (token) { case SyntaxKind.OpenParenToken: case SyntaxKind.LessThanToken: @@ -2301,7 +2301,7 @@ namespace ts { // when incrementally parsing as the parser will produce the Index declaration // if it has the same text regardless of whether it is inside a class or an // object type. - if (isModifier(token)) { + if (isModifierKind(token)) { const result = tryParse(parseIndexSignatureWithModifiers); if (result) { return result; @@ -2334,14 +2334,14 @@ namespace ts { return finishNode(node); } - function parseObjectTypeMembers(): NodeArray { - let members: NodeArray; + function parseObjectTypeMembers(): NodeArray { + let members: NodeArray; if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, parseTypeMember); parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } return members; @@ -2483,11 +2483,11 @@ namespace ts { // ( ... return true; } - if (isIdentifier() || isModifier(token)) { + if (isIdentifier() || isModifierKind(token)) { nextToken(); if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || - isIdentifier() || isModifier(token)) { + isIdentifier() || isModifierKind(token)) { // ( id : // ( id , // ( id ? @@ -2894,7 +2894,7 @@ namespace ts { } // This *could* be a parenthesized arrow function. - // Return Unknown to const the caller know. + // Return Unknown to let the caller know. return Tristate.Unknown; } else { @@ -2993,7 +2993,7 @@ namespace ts { // user meant to supply a block. For example, if the user wrote: // // a => - // const v = 0; + // let v = 0; // } // // they may be missing an open brace. Check to see if that's the case so we can @@ -3220,7 +3220,7 @@ namespace ts { /** * Parse ES7 unary expression and await expression - * + * * ES7 UnaryExpression: * 1) SimpleUnaryExpression[?yield] * 2) IncrementExpression[?yield] ** UnaryExpression[?yield] @@ -4720,7 +4720,7 @@ namespace ts { return finishNode(node); } - function parseMethodDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, asteriskToken: Node, name: DeclarationName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration { + function parseMethodDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration { const method = createNode(SyntaxKind.MethodDeclaration, fullStart); method.decorators = decorators; setModifiers(method, modifiers); @@ -4734,7 +4734,7 @@ namespace ts { return finishNode(method); } - function parsePropertyDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, name: DeclarationName, questionToken: Node): ClassElement { + function parsePropertyDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement { const property = createNode(SyntaxKind.PropertyDeclaration, fullStart); property.decorators = decorators; setModifiers(property, modifiers); @@ -4808,7 +4808,7 @@ namespace ts { } // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. - while (isModifier(token)) { + while (isModifierKind(token)) { idToken = token; // If the idToken is a class modifier (protected, private, public, and static), it is // certain that we are starting to parse class member. This allows better error recovery @@ -5018,8 +5018,8 @@ namespace ts { // implements is a future reserved word so // 'class implements' might mean either // - class expression with omitted name, 'implements' starts heritage clause - // - class with name 'implements' - // 'isImplementsClause' helps to disambiguate between these two cases + // - class with name 'implements' + // 'isImplementsClause' helps to disambiguate between these two cases return isIdentifier() && !isImplementsClause() ? parseIdentifier() : undefined; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 57207d0564a..dc31dfb5213 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -904,7 +904,7 @@ namespace ts { function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string { let commonPathComponents: string[]; - forEach(files, sourceFile => { + const failed = forEach(files, sourceFile => { // Each file contributes into common source file path if (isDeclarationFile(sourceFile)) { return; @@ -920,10 +920,10 @@ namespace ts { } for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { if (i === 0) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; + // Failed to find any common path component + return true; } // New common path found that is 0 -> i-1 @@ -938,6 +938,11 @@ namespace ts { } }); + // A common path can not be found when paths span multiple drives on windows, for example + if (failed) { + return ""; + } + if (!commonPathComponents) { // Can happen when all input files are .d.ts files return currentDirectory; } @@ -1059,6 +1064,10 @@ namespace ts { else { // Compute the commonSourceDirectory from the input files commonSourceDirectory = computeCommonSourceDirectory(files); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure + if (options.outDir && commonSourceDirectory === "" && forEach(files, file => getRootLength(file.fileName) > 1)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + } } if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5f9f82d9a64..34be02c5ba5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -348,7 +348,7 @@ namespace ts { LastKeyword = OfKeyword, FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, - FirstTypeNode = TypeReference, + FirstTypeNode = TypePredicate, LastTypeNode = ParenthesizedType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, @@ -474,15 +474,29 @@ namespace ts { hasTrailingComma?: boolean; } - export interface ModifiersArray extends NodeArray { + export interface ModifiersArray extends NodeArray { flags: number; } + // @kind(SyntaxKind.AbstractKeyword) + // @kind(SyntaxKind.AsyncKeyword) + // @kind(SyntaxKind.ConstKeyword) + // @kind(SyntaxKind.DeclareKeyword) + // @kind(SyntaxKind.DefaultKeyword) + // @kind(SyntaxKind.ExportKeyword) + // @kind(SyntaxKind.PublicKeyword) + // @kind(SyntaxKind.PrivateKeyword) + // @kind(SyntaxKind.ProtectedKeyword) + // @kind(SyntaxKind.StaticKeyword) + export interface Modifier extends Node { } + + // @kind(SyntaxKind.Identifier) export interface Identifier extends PrimaryExpression { text: string; // Text of identifier (with escapes converted to characters) originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later } + // @kind(SyntaxKind.QualifiedName) export interface QualifiedName extends Node { // Must have same layout as PropertyAccess left: EntityName; @@ -492,6 +506,7 @@ namespace ts { export type EntityName = Identifier | QualifiedName; export type PropertyName = Identifier | LiteralExpression | ComputedPropertyName; + export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; export interface Declaration extends Node { @@ -499,14 +514,21 @@ namespace ts { name?: DeclarationName; } + export interface DeclarationStatement extends Declaration, Statement { + name?: Identifier; + } + + // @kind(SyntaxKind.ComputedPropertyName) export interface ComputedPropertyName extends Node { expression: Expression; } + // @kind(SyntaxKind.Decorator) export interface Decorator extends Node { expression: LeftHandSideExpression; } + // @kind(SyntaxKind.TypeParameter) export interface TypeParameterDeclaration extends Declaration { name: Identifier; constraint?: TypeNode; @@ -516,12 +538,19 @@ namespace ts { } export interface SignatureDeclaration extends Declaration { + name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; type?: TypeNode; } - // SyntaxKind.VariableDeclaration + // @kind(SyntaxKind.CallSignature) + export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement { } + + // @kind(SyntaxKind.ConstructSignature) + export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { } + + // @kind(SyntaxKind.VariableDeclaration) export interface VariableDeclaration extends Declaration { parent?: VariableDeclarationList; name: Identifier | BindingPattern; // Declared variable name @@ -529,11 +558,12 @@ namespace ts { initializer?: Expression; // Optional initializer } + // @kind(SyntaxKind.VariableDeclarationList) export interface VariableDeclarationList extends Node { declarations: NodeArray; } - // SyntaxKind.Parameter + // @kind(SyntaxKind.Parameter) export interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; // Present on rest parameter name: Identifier | BindingPattern; // Declared parameter name @@ -542,7 +572,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - // SyntaxKind.BindingElement + // @kind(SyntaxKind.BindingElement) export interface BindingElement extends Declaration { propertyName?: PropertyName; // Binding property name (in object binding pattern) dotDotDotToken?: Node; // Present on rest binding element @@ -550,27 +580,35 @@ namespace ts { initializer?: Expression; // Optional initializer } - // SyntaxKind.Property - export interface PropertyDeclaration extends Declaration, ClassElement { - name: DeclarationName; // Declared property name + // @kind(SyntaxKind.PropertySignature) + export interface PropertySignature extends TypeElement { + name: PropertyName; // Declared property name questionToken?: Node; // Present on optional property type?: TypeNode; // Optional type annotation + } + + // @kind(SyntaxKind.PropertyDeclaration) + export interface PropertyDeclaration extends ClassElement { + questionToken?: Node; // Present for use with reporting a grammar error + name: PropertyName; + type?: TypeNode; initializer?: Expression; // Optional initializer } export interface ObjectLiteralElement extends Declaration { _objectLiteralBrandBrand: any; - } + name?: PropertyName; + } - // SyntaxKind.PropertyAssignment + // @kind(SyntaxKind.PropertyAssignment) export interface PropertyAssignment extends ObjectLiteralElement { _propertyAssignmentBrand: any; - name: DeclarationName; + name: PropertyName; questionToken?: Node; initializer: Expression; } - // SyntaxKind.ShorthandPropertyAssignment + // @kind(SyntaxKind.ShorthandPropertyAssignment) export interface ShorthandPropertyAssignment extends ObjectLiteralElement { name: Identifier; questionToken?: Node; @@ -596,10 +634,20 @@ namespace ts { initializer?: Expression; } + export interface PropertyLikeDeclaration extends Declaration { + name: PropertyName; + } + export interface BindingPattern extends Node { elements: NodeArray; } + // @kind(SyntaxKind.ObjectBindingPattern) + export interface ObjectBindingPattern extends BindingPattern { } + + // @kind(SyntaxKind.ArrayBindingPattern) + export interface ArrayBindingPattern extends BindingPattern { } + /** * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. @@ -616,9 +664,15 @@ namespace ts { body?: Block | Expression; } - export interface FunctionDeclaration extends FunctionLikeDeclaration, Statement { + // @kind(SyntaxKind.FunctionDeclaration) + export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement { name?: Identifier; - body?: Block; + body?: FunctionBody; + } + + // @kind(SyntaxKind.MethodSignature) + export interface MethodSignature extends SignatureDeclaration, TypeElement { + name: PropertyName; } // Note that a MethodDeclaration is considered both a ClassElement and an ObjectLiteralElement. @@ -630,15 +684,19 @@ namespace ts { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration + // @kind(SyntaxKind.MethodDeclaration) export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { - body?: Block; + name: PropertyName; + body?: FunctionBody; } + // @kind(SyntaxKind.Constructor) export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { - body?: Block; + body?: FunctionBody; } // For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. + // @kind(SyntaxKind.SemicolonClassElement) export interface SemicolonClassElement extends ClassElement { _semicolonClassElementBrand: any; } @@ -647,13 +705,27 @@ namespace ts { // ClassElement and an ObjectLiteralElement. export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { _accessorDeclarationBrand: any; - body: Block; + name: PropertyName; + body: FunctionBody; } - export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement { + // @kind(SyntaxKind.GetAccessor) + export interface GetAccessorDeclaration extends AccessorDeclaration { } + + // @kind(SyntaxKind.SetAccessor) + export interface SetAccessorDeclaration extends AccessorDeclaration { } + + // @kind(SyntaxKind.IndexSignature) + export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement { _indexSignatureDeclarationBrand: any; } + // @kind(SyntaxKind.AnyKeyword) + // @kind(SyntaxKind.NumberKeyword) + // @kind(SyntaxKind.BooleanKeyword) + // @kind(SyntaxKind.StringKeyword) + // @kind(SyntaxKind.SymbolKeyword) + // @kind(SyntaxKind.VoidKeyword) export interface TypeNode extends Node { _typeNodeBrand: any; } @@ -662,29 +734,41 @@ namespace ts { _functionOrConstructorTypeNodeBrand: any; } + // @kind(SyntaxKind.FunctionType) + export interface FunctionTypeNode extends FunctionOrConstructorTypeNode { } + + // @kind(SyntaxKind.ConstructorType) + export interface ConstructorTypeNode extends FunctionOrConstructorTypeNode { } + + // @kind(SyntaxKind.TypeReference) export interface TypeReferenceNode extends TypeNode { typeName: EntityName; typeArguments?: NodeArray; } + // @kind(SyntaxKind.TypePredicate) export interface TypePredicateNode extends TypeNode { parameterName: Identifier; type: TypeNode; } + // @kind(SyntaxKind.TypeQuery) export interface TypeQueryNode extends TypeNode { exprName: EntityName; } // A TypeLiteral is the declaration node for an anonymous symbol. + // @kind(SyntaxKind.TypeLiteral) export interface TypeLiteralNode extends TypeNode, Declaration { - members: NodeArray; + members: NodeArray; } + // @kind(SyntaxKind.ArrayType) export interface ArrayTypeNode extends TypeNode { elementType: TypeNode; } + // @kind(SyntaxKind.TupleType) export interface TupleTypeNode extends TypeNode { elementTypes: NodeArray; } @@ -693,16 +777,20 @@ namespace ts { types: NodeArray; } + // @kind(SyntaxKind.UnionType) export interface UnionTypeNode extends UnionOrIntersectionTypeNode { } + // @kind(SyntaxKind.IntersectionType) export interface IntersectionTypeNode extends UnionOrIntersectionTypeNode { } + // @kind(SyntaxKind.ParenthesizedType) export interface ParenthesizedTypeNode extends TypeNode { type: TypeNode; } // Note that a StringLiteral AST node is both an Expression and a TypeNode. The latter is // because string literals can appear in type annotations as well. + // @kind(SyntaxKind.StringLiteral) export interface StringLiteral extends LiteralExpression, TypeNode { _stringLiteralBrand: any; } @@ -719,6 +807,9 @@ namespace ts { contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution } + // @kind(SyntaxKind.OmittedExpression) + export interface OmittedExpression extends Expression { } + export interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } @@ -727,11 +818,13 @@ namespace ts { _incrementExpressionBrand: any; } + // @kind(SyntaxKind.PrefixUnaryExpression) export interface PrefixUnaryExpression extends IncrementExpression { operator: SyntaxKind; operand: UnaryExpression; } + // @kind(SyntaxKind.PostfixUnaryExpression) export interface PostfixUnaryExpression extends IncrementExpression { operand: LeftHandSideExpression; operator: SyntaxKind; @@ -749,31 +842,42 @@ namespace ts { _memberExpressionBrand: any; } + // @kind(SyntaxKind.TrueKeyword) + // @kind(SyntaxKind.FalseKeyword) + // @kind(SyntaxKind.NullKeyword) + // @kind(SyntaxKind.ThisKeyword) + // @kind(SyntaxKind.SuperKeyword) export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } + // @kind(SyntaxKind.DeleteExpression) export interface DeleteExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.TypeOfExpression) export interface TypeOfExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.VoidExpression) export interface VoidExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.AwaitExpression) export interface AwaitExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.YieldExpression) export interface YieldExpression extends Expression { asteriskToken?: Node; expression?: Expression; } + // @kind(SyntaxKind.BinaryExpression) // Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files export interface BinaryExpression extends Expression, Declaration { left: Expression; @@ -781,6 +885,7 @@ namespace ts { right: Expression; } + // @kind(SyntaxKind.ConditionalExpression) export interface ConditionalExpression extends Expression { condition: Expression; questionToken: Node; @@ -789,24 +894,37 @@ namespace ts { whenFalse: Expression; } + export type FunctionBody = Block; + export type ConciseBody = FunctionBody | Expression; + + // @kind(SyntaxKind.FunctionExpression) export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration { name?: Identifier; - body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional + body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } + // @kind(SyntaxKind.ArrowFunction) export interface ArrowFunction extends Expression, FunctionLikeDeclaration { equalsGreaterThanToken: Node; + body: ConciseBody; } // 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". + // @kind(SyntaxKind.NumericLiteral) + // @kind(SyntaxKind.RegularExpressionLiteral) + // @kind(SyntaxKind.NoSubstitutionTemplateLiteral) + // @kind(SyntaxKind.TemplateHead) + // @kind(SyntaxKind.TemplateMiddle) + // @kind(SyntaxKind.TemplateTail) export interface LiteralExpression extends PrimaryExpression { text: string; isUnterminated?: boolean; hasExtendedUnicodeEscape?: boolean; } + // @kind(SyntaxKind.TemplateExpression) export interface TemplateExpression extends PrimaryExpression { head: LiteralExpression; templateSpans: NodeArray; @@ -814,52 +932,63 @@ namespace ts { // Each of these corresponds to a substitution expression and a template literal, in that order. // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. + // @kind(SyntaxKind.TemplateSpan) export interface TemplateSpan extends Node { expression: Expression; literal: LiteralExpression; } + // @kind(SyntaxKind.ParenthesizedExpression) export interface ParenthesizedExpression extends PrimaryExpression { expression: Expression; } + // @kind(SyntaxKind.ArrayLiteralExpression) export interface ArrayLiteralExpression extends PrimaryExpression { elements: NodeArray; } + // @kind(SyntaxKind.SpreadElementExpression) export interface SpreadElementExpression extends Expression { expression: Expression; } // An ObjectLiteralExpression is the declaration node for an anonymous symbol. + // @kind(SyntaxKind.ObjectLiteralExpression) export interface ObjectLiteralExpression extends PrimaryExpression, Declaration { properties: NodeArray; } + // @kind(SyntaxKind.PropertyAccessExpression) export interface PropertyAccessExpression extends MemberExpression, Declaration { expression: LeftHandSideExpression; dotToken: Node; name: Identifier; } + // @kind(SyntaxKind.ElementAccessExpression) export interface ElementAccessExpression extends MemberExpression { expression: LeftHandSideExpression; argumentExpression?: Expression; } + // @kind(SyntaxKind.CallExpression) export interface CallExpression extends LeftHandSideExpression { expression: LeftHandSideExpression; typeArguments?: NodeArray; arguments: NodeArray; } + // @kind(SyntaxKind.ExpressionWithTypeArguments) export interface ExpressionWithTypeArguments extends TypeNode { expression: LeftHandSideExpression; typeArguments?: NodeArray; } + // @kind(SyntaxKind.NewExpression) export interface NewExpression extends CallExpression, PrimaryExpression { } + // @kind(SyntaxKind.TaggedTemplateExpression) export interface TaggedTemplateExpression extends MemberExpression { tag: LeftHandSideExpression; template: LiteralExpression | TemplateExpression; @@ -867,11 +996,13 @@ namespace ts { export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator; + // @kind(SyntaxKind.AsExpression) export interface AsExpression extends Expression { expression: Expression; type: TypeNode; } + // @kind(SyntaxKind.TypeAssertionExpression) export interface TypeAssertion extends UnaryExpression { type: TypeNode; expression: UnaryExpression; @@ -880,6 +1011,7 @@ namespace ts { export type AssertionExpression = TypeAssertion | AsExpression; /// A JSX expression of the form ... + // @kind(SyntaxKind.JsxElement) export interface JsxElement extends PrimaryExpression { openingElement: JsxOpeningElement; children: NodeArray; @@ -887,6 +1019,7 @@ namespace ts { } /// The opening element of a ... JsxElement + // @kind(SyntaxKind.JsxOpeningElement) export interface JsxOpeningElement extends Expression { _openingElementBrand?: any; tagName: EntityName; @@ -894,6 +1027,7 @@ namespace ts { } /// A JSX expression of the form + // @kind(SyntaxKind.JsxSelfClosingElement) export interface JsxSelfClosingElement extends PrimaryExpression, JsxOpeningElement { _selfClosingElementBrand?: any; } @@ -901,24 +1035,29 @@ namespace ts { /// Either the opening tag in a ... pair, or the lone in a self-closing form export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; + // @kind(SyntaxKind.JsxAttribute) export interface JsxAttribute extends Node { name: Identifier; /// JSX attribute initializers are optional; is sugar for initializer?: Expression; } + // @kind(SyntaxKind.JsxSpreadAttribute) export interface JsxSpreadAttribute extends Node { expression: Expression; } + // @kind(SyntaxKind.JsxClosingElement) export interface JsxClosingElement extends Node { tagName: EntityName; } + // @kind(SyntaxKind.JsxExpression) export interface JsxExpression extends Expression { expression?: Expression; } + // @kind(SyntaxKind.JsxText) export interface JsxText extends Node { _jsxTextExpressionBrand: any; } @@ -929,18 +1068,36 @@ namespace ts { _statementBrand: any; } + // @kind(SyntaxKind.EmptyStatement) + export interface EmptyStatement extends Statement { } + + // @kind(SyntaxKind.DebuggerStatement) + export interface DebuggerStatement extends Statement { } + + // @kind(SyntaxKind.MissingDeclaration) + // @factoryhidden("name", true) + export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + name?: Identifier; + } + + export type BlockLike = SourceFile | Block | ModuleBlock | CaseClause; + + // @kind(SyntaxKind.Block) export interface Block extends Statement { statements: NodeArray; } + // @kind(SyntaxKind.VariableStatement) export interface VariableStatement extends Statement { declarationList: VariableDeclarationList; } + // @kind(SyntaxKind.ExpressionStatement) export interface ExpressionStatement extends Statement { expression: Expression; } + // @kind(SyntaxKind.IfStatement) export interface IfStatement extends Statement { expression: Expression; thenStatement: Statement; @@ -951,78 +1108,101 @@ namespace ts { statement: Statement; } + // @kind(SyntaxKind.DoStatement) export interface DoStatement extends IterationStatement { expression: Expression; } + // @kind(SyntaxKind.WhileStatement) export interface WhileStatement extends IterationStatement { expression: Expression; } + // @kind(SyntaxKind.ForStatement) export interface ForStatement extends IterationStatement { initializer?: VariableDeclarationList | Expression; condition?: Expression; incrementor?: Expression; } + // @kind(SyntaxKind.ForInStatement) export interface ForInStatement extends IterationStatement { initializer: VariableDeclarationList | Expression; expression: Expression; } + // @kind(SyntaxKind.ForOfStatement) export interface ForOfStatement extends IterationStatement { initializer: VariableDeclarationList | Expression; expression: Expression; } - export interface BreakOrContinueStatement extends Statement { + // @kind(SyntaxKind.BreakStatement) + export interface BreakStatement extends Statement { label?: Identifier; } + // @kind(SyntaxKind.ContinueStatement) + export interface ContinueStatement extends Statement { + label?: Identifier; + } + + export type BreakOrContinueStatement = BreakStatement | ContinueStatement; + + // @kind(SyntaxKind.ReturnStatement) export interface ReturnStatement extends Statement { expression?: Expression; } + // @kind(SyntaxKind.WithStatement) export interface WithStatement extends Statement { expression: Expression; statement: Statement; } + // @kind(SyntaxKind.SwitchStatement) export interface SwitchStatement extends Statement { expression: Expression; caseBlock: CaseBlock; } + // @kind(SyntaxKind.CaseBlock) export interface CaseBlock extends Node { clauses: NodeArray; } + // @kind(SyntaxKind.CaseClause) export interface CaseClause extends Node { expression?: Expression; statements: NodeArray; } + // @kind(SyntaxKind.DefaultClause) export interface DefaultClause extends Node { statements: NodeArray; } export type CaseOrDefaultClause = CaseClause | DefaultClause; + // @kind(SyntaxKind.LabeledStatement) export interface LabeledStatement extends Statement { label: Identifier; statement: Statement; } + // @kind(SyntaxKind.ThrowStatement) export interface ThrowStatement extends Statement { expression: Expression; } + // @kind(SyntaxKind.TryStatement) export interface TryStatement extends Statement { tryBlock: Block; catchClause?: CatchClause; finallyBlock?: Block; } + // @kind(SyntaxKind.CatchClause) export interface CatchClause extends Node { variableDeclaration: VariableDeclaration; block: Block; @@ -1035,34 +1215,49 @@ namespace ts { members: NodeArray; } - export interface ClassDeclaration extends ClassLikeDeclaration, Statement { + // @kind(SyntaxKind.ClassDeclaration) + export interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement { + name?: Identifier; } + // @kind(SyntaxKind.ClassExpression) export interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression { } export interface ClassElement extends Declaration { _classElementBrand: any; + name?: PropertyName; } - export interface InterfaceDeclaration extends Declaration, Statement { + export interface TypeElement extends Declaration { + _typeElementBrand: any; + name?: PropertyName; + // @factoryparam + questionToken?: Node; + } + + // @kind(SyntaxKind.InterfaceDeclaration) + export interface InterfaceDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; - members: NodeArray; + members: NodeArray; } + // @kind(SyntaxKind.HeritageClause) export interface HeritageClause extends Node { token: SyntaxKind; types?: NodeArray; } - export interface TypeAliasDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.TypeAliasDeclaration) + export interface TypeAliasDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; type: TypeNode; } + // @kind(SyntaxKind.EnumMember) export interface EnumMember extends Declaration { // This does include ComputedPropertyName, but the parser will give an error // if it parses a ComputedPropertyName in an EnumMember @@ -1070,21 +1265,27 @@ namespace ts { initializer?: Expression; } - export interface EnumDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.EnumDeclaration) + export interface EnumDeclaration extends DeclarationStatement { name: Identifier; members: NodeArray; } - export interface ModuleDeclaration extends Declaration, Statement { + export type ModuleBody = ModuleBlock | ModuleDeclaration; + + // @kind(SyntaxKind.ModuleDeclaration) + export interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } + // @kind(SyntaxKind.ModuleBlock) export interface ModuleBlock extends Node, Statement { statements: NodeArray; } - export interface ImportEqualsDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.ImportEqualsDeclaration) + export interface ImportEqualsDeclaration extends DeclarationStatement { name: Identifier; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external @@ -1092,6 +1293,7 @@ namespace ts { moduleReference: EntityName | ExternalModuleReference; } + // @kind(SyntaxKind.ExternalModuleReference) export interface ExternalModuleReference extends Node { expression?: Expression; } @@ -1100,6 +1302,7 @@ namespace ts { // import "mod" => importClause = undefined, moduleSpecifier = "mod" // In rest of the cases, module specifier is string literal corresponding to module // ImportClause information is shown at its declaration below. + // @kind(SyntaxKind.ImportDeclaration) export interface ImportDeclaration extends Statement { importClause?: ImportClause; moduleSpecifier: Expression; @@ -1111,36 +1314,51 @@ namespace ts { // import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns } // import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} + // @kind(SyntaxKind.ImportClause) export interface ImportClause extends Declaration { name?: Identifier; // Default binding namedBindings?: NamespaceImport | NamedImports; } + // @kind(SyntaxKind.NamespaceImport) export interface NamespaceImport extends Declaration { name: Identifier; } - export interface ExportDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.ExportDeclaration) + export interface ExportDeclaration extends DeclarationStatement { exportClause?: NamedExports; moduleSpecifier?: Expression; } - export interface NamedImportsOrExports extends Node { - elements: NodeArray; + // @kind(SyntaxKind.NamedImports) + export interface NamedImports extends Node { + elements: NodeArray; } - export type NamedImports = NamedImportsOrExports; - export type NamedExports = NamedImportsOrExports; + // @kind(SyntaxKind.NamedExports) + export interface NamedExports extends Node { + elements: NodeArray; + } - export interface ImportOrExportSpecifier extends Declaration { + export type NamedImportsOrExports = NamedImports | NamedExports; + + // @kind(SyntaxKind.ImportSpecifier) + export interface ImportSpecifier extends Declaration { propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } - export type ImportSpecifier = ImportOrExportSpecifier; - export type ExportSpecifier = ImportOrExportSpecifier; + // @kind(SyntaxKind.ExportSpecifier) + export interface ExportSpecifier extends Declaration { + propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) + name: Identifier; // Declared name + } - export interface ExportAssignment extends Declaration, Statement { + export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; + + // @kind(SyntaxKind.ExportAssignment) + export interface ExportAssignment extends DeclarationStatement { isExportEquals?: boolean; expression: Expression; } @@ -1155,6 +1373,7 @@ namespace ts { } // represents a top level: { type } expression in a JSDoc comment. + // @kind(SyntaxKind.JSDocTypeExpression) export interface JSDocTypeExpression extends Node { type: JSDocType; } @@ -1163,90 +1382,111 @@ namespace ts { _jsDocTypeBrand: any; } + // @kind(SyntaxKind.JSDocAllType) export interface JSDocAllType extends JSDocType { _JSDocAllTypeBrand: any; } + // @kind(SyntaxKind.JSDocUnknownType) export interface JSDocUnknownType extends JSDocType { _JSDocUnknownTypeBrand: any; } + // @kind(SyntaxKind.JSDocArrayType) export interface JSDocArrayType extends JSDocType { elementType: JSDocType; } + // @kind(SyntaxKind.JSDocUnionType) export interface JSDocUnionType extends JSDocType { types: NodeArray; } + // @kind(SyntaxKind.JSDocTupleType) export interface JSDocTupleType extends JSDocType { types: NodeArray; } + // @kind(SyntaxKind.JSDocNonNullableType) export interface JSDocNonNullableType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocNullableType) export interface JSDocNullableType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocRecordType) export interface JSDocRecordType extends JSDocType, TypeLiteralNode { members: NodeArray; } + // @kind(SyntaxKind.JSDocTypeReference) export interface JSDocTypeReference extends JSDocType { name: EntityName; typeArguments: NodeArray; } + // @kind(SyntaxKind.JSDocOptionalType) export interface JSDocOptionalType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocFunctionType) export interface JSDocFunctionType extends JSDocType, SignatureDeclaration { parameters: NodeArray; type: JSDocType; } + // @kind(SyntaxKind.JSDocVariadicType) export interface JSDocVariadicType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocConstructorType) export interface JSDocConstructorType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocThisType) export interface JSDocThisType extends JSDocType { type: JSDocType; } - export interface JSDocRecordMember extends PropertyDeclaration { + // @kind(SyntaxKind.JSDocRecordMember) + export interface JSDocRecordMember extends PropertySignature { name: Identifier | LiteralExpression; type?: JSDocType; } + // @kind(SyntaxKind.JSDocComment) export interface JSDocComment extends Node { tags: NodeArray; } + // @kind(SyntaxKind.JSDocTag) export interface JSDocTag extends Node { atToken: Node; tagName: Identifier; } + // @kind(SyntaxKind.JSDocTemplateTag) export interface JSDocTemplateTag extends JSDocTag { typeParameters: NodeArray; } + // @kind(SyntaxKind.JSDocReturnTag) export interface JSDocReturnTag extends JSDocTag { typeExpression: JSDocTypeExpression; } + // @kind(SyntaxKind.JSDocTypeTag) export interface JSDocTypeTag extends JSDocTag { typeExpression: JSDocTypeExpression; } + // @kind(SyntaxKind.JSDocParameterTag) export interface JSDocParameterTag extends JSDocTag { preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; @@ -1254,7 +1494,13 @@ namespace ts { isBracketed: boolean; } + export interface AmdDependency { + path: string; + name: string; + } + // Source files are declarations when they are external modules. + // @kind(SyntaxKind.SourceFile) export interface SourceFile extends Declaration { statements: NodeArray; endOfFileToken: Node; @@ -1263,7 +1509,7 @@ namespace ts { /* internal */ path: Path; text: string; - amdDependencies: {path: string; name: string}[]; + amdDependencies: AmdDependency[]; moduleName: string; referencedFiles: FileReference[]; languageVariant: LanguageVariant; @@ -2341,7 +2587,7 @@ namespace ts { export interface ModuleResolutionHost { fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' - // to determine location of bundled typings for node module + // to determine location of bundled typings for node module readFile(fileName: string): string; } @@ -2349,7 +2595,7 @@ namespace ts { resolvedFileName: string; /* * Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be proper external module: - * - be a .d.ts file + * - be a .d.ts file * - use top level imports\exports * - don't use tripleslash references */ @@ -2372,11 +2618,11 @@ namespace ts { getNewLine(): string; /* - * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of - * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler + * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of + * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler * will appply built-in module resolution logic and use members of ModuleResolutionHost to ask host specific questions). - * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just - * 'throw new Error("NotImplemented")' + * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just + * 'throw new Error("NotImplemented")' */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ed7242a785e..1e4ee1bed47 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1327,7 +1327,7 @@ namespace ts { } // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationName(name: Node): boolean { + export function isDeclarationName(name: Node): name is Identifier | StringLiteral | LiteralExpression { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -1545,7 +1545,7 @@ namespace ts { return node.kind === SyntaxKind.Identifier && (node).text === "Symbol"; } - export function isModifier(token: SyntaxKind): boolean { + export function isModifierKind(token: SyntaxKind): boolean { switch (token) { case SyntaxKind.AbstractKeyword: case SyntaxKind.AsyncKeyword: diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 399f8a272dd..425fa888013 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -40,19 +40,18 @@ class CompilerBaselineRunner extends RunnerBase { this.basePath += "/" + this.testSuiteName; } + private makeUnitName(name: string, root: string) { + return ts.isRootedDiskPath(name) ? name : ts.combinePaths(root, name); + }; + public checkTestCodeOutput(fileName: string) { describe("compiler tests for " + fileName, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let justName: string; - let content: string; - let testCaseContent: { settings: Harness.TestCaseParser.CompilerSettings; testUnitData: Harness.TestCaseParser.TestUnitData[]; }; - - let units: Harness.TestCaseParser.TestUnitData[]; - let harnessSettings: Harness.TestCaseParser.CompilerSettings; let lastUnit: Harness.TestCaseParser.TestUnitData; - let rootDir: string; + let harnessSettings: Harness.TestCaseParser.CompilerSettings; let result: Harness.Compiler.CompilerResult; let options: ts.CompilerOptions; @@ -63,28 +62,28 @@ class CompilerBaselineRunner extends RunnerBase { before(() => { justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path. - content = Harness.IO.readFile(fileName); - testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); - units = testCaseContent.testUnitData; + const content = Harness.IO.readFile(fileName); + const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); + const units = testCaseContent.testUnitData; harnessSettings = testCaseContent.settings; lastUnit = units[units.length - 1]; - rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; + const rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. toBeCompiled = []; otherFiles = []; if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) { - toBeCompiled.push({ unitName: ts.combinePaths(rootDir, lastUnit.name), content: lastUnit.content }); + toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content }); units.forEach(unit => { if (unit.name !== lastUnit.name) { - otherFiles.push({ unitName: ts.combinePaths(rootDir, unit.name), content: unit.content }); + otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content }); } }); } else { toBeCompiled = units.map(unit => { - return { unitName: ts.combinePaths(rootDir, unit.name), content: unit.content }; + return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content }; }); } @@ -99,12 +98,7 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. justName = undefined; - content = undefined; - testCaseContent = undefined; - units = undefined; - harnessSettings = undefined; lastUnit = undefined; - rootDir = undefined; result = undefined; options = undefined; toBeCompiled = undefined; diff --git a/src/services/services.ts b/src/services/services.ts index d1c87d17239..f345cf647cc 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -132,43 +132,43 @@ namespace ts { let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); let emptyArray: any[] = []; - + const jsDocTagNames = [ - "augments", - "author", - "argument", - "borrows", - "class", - "constant", - "constructor", - "constructs", - "default", - "deprecated", - "description", - "event", - "example", - "extends", - "field", - "fileOverview", - "function", - "ignore", - "inner", - "lends", - "link", - "memberOf", - "name", - "namespace", - "param", - "private", - "property", - "public", - "requires", - "returns", - "see", - "since", - "static", - "throws", - "type", + "augments", + "author", + "argument", + "borrows", + "class", + "constant", + "constructor", + "constructs", + "default", + "deprecated", + "description", + "event", + "example", + "extends", + "field", + "fileOverview", + "function", + "ignore", + "inner", + "lends", + "link", + "memberOf", + "name", + "namespace", + "param", + "private", + "property", + "public", + "requires", + "returns", + "see", + "since", + "static", + "throws", + "type", "version" ]; let jsDocCompletionEntries: CompletionEntry[]; @@ -817,7 +817,7 @@ namespace ts { constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end) } - + public update(newText: string, textChangeRange: TextChangeRange): SourceFile { return updateSourceFile(this, newText, textChangeRange); } @@ -1031,7 +1031,7 @@ namespace ts { /* * LS host can optionally implement this method if it wants to be completely in charge of module name resolution. - * if implementation is omitted then language service will use built-in module resolution logic and get answers to + * if implementation is omitted then language service will use built-in module resolution logic and get answers to * host specific questions using 'getScriptSnapshot'. */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; @@ -1861,7 +1861,7 @@ namespace ts { * - allowNonTsExtensions = true * - noLib = true * - noResolve = true - */ + */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); @@ -2670,7 +2670,7 @@ namespace ts { } } - export function createLanguageService(host: LanguageServiceHost, + export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); @@ -2758,10 +2758,10 @@ namespace ts { getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => currentDirectory, - fileExists: (fileName): boolean => { + fileExists: (fileName): boolean => { // stub missing host functionality Debug.assert(!host.resolveModuleNames); - return hostCache.getOrCreateEntry(fileName) !== undefined; + return hostCache.getOrCreateEntry(fileName) !== undefined; }, readFile: (fileName): string => { // stub missing host functionality @@ -3167,7 +3167,7 @@ namespace ts { log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { - // The current position is next to the '@' sign, when no tag name being provided yet. + // The current position is next to the '@' sign, when no tag name being provided yet. // Provide a full list of tag names if (hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { isJsDocTagName = true; @@ -3200,7 +3200,7 @@ namespace ts { } if (!insideJsDocTagExpression) { - // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal // comment or the plain text part of a jsDoc comment, so no completion should be available log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); return undefined; @@ -3721,8 +3721,8 @@ namespace ts { case SyntaxKind.CloseBraceToken: if (parent && - parent.kind === SyntaxKind.JsxExpression && - parent.parent && + parent.kind === SyntaxKind.JsxExpression && + parent.parent && (parent.parent.kind === SyntaxKind.JsxAttribute)) { return parent.parent.parent; } @@ -3771,7 +3771,7 @@ namespace ts { containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface Ax : Symbol(x, Decl(bar.ts, 0, 3)) + +=== A:/foo/baz.ts === +var y: number; +>y : Symbol(y, Decl(baz.ts, 0, 3)) + diff --git a/tests/baselines/reference/commonSourceDir1.types b/tests/baselines/reference/commonSourceDir1.types new file mode 100644 index 00000000000..6c9864c02cc --- /dev/null +++ b/tests/baselines/reference/commonSourceDir1.types @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : number + +=== A:/foo/baz.ts === +var y: number; +>y : number + diff --git a/tests/baselines/reference/commonSourceDir2.errors.txt b/tests/baselines/reference/commonSourceDir2.errors.txt new file mode 100644 index 00000000000..85bcf5d9c72 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir2.errors.txt @@ -0,0 +1,9 @@ +error TS5009: Cannot find the common subdirectory path for the input files. + + +!!! error TS5009: Cannot find the common subdirectory path for the input files. +==== A:/foo/bar.ts (0 errors) ==== + var x: number; + +==== B:/foo/baz.ts (0 errors) ==== + var y: number; \ No newline at end of file diff --git a/tests/baselines/reference/commonSourceDir2.js b/tests/baselines/reference/commonSourceDir2.js new file mode 100644 index 00000000000..cf263b51fb6 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir2.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir2.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/commonSourceDir3.js b/tests/baselines/reference/commonSourceDir3.js new file mode 100644 index 00000000000..0535d51f4bf --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir3.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/commonSourceDir3.symbols b/tests/baselines/reference/commonSourceDir3.symbols new file mode 100644 index 00000000000..b8783523dfd --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.symbols @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : Symbol(x, Decl(bar.ts, 0, 3)) + +=== a:/foo/baz.ts === +var y: number; +>y : Symbol(y, Decl(baz.ts, 0, 3)) + diff --git a/tests/baselines/reference/commonSourceDir3.types b/tests/baselines/reference/commonSourceDir3.types new file mode 100644 index 00000000000..a0b95275897 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.types @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : number + +=== a:/foo/baz.ts === +var y: number; +>y : number + diff --git a/tests/baselines/reference/commonSourceDir4.errors.txt b/tests/baselines/reference/commonSourceDir4.errors.txt new file mode 100644 index 00000000000..f3493504e4d --- /dev/null +++ b/tests/baselines/reference/commonSourceDir4.errors.txt @@ -0,0 +1,9 @@ +error TS5009: Cannot find the common subdirectory path for the input files. + + +!!! error TS5009: Cannot find the common subdirectory path for the input files. +==== A:/foo/bar.ts (0 errors) ==== + var x: number; + +==== a:/foo/baz.ts (0 errors) ==== + var y: number; \ No newline at end of file diff --git a/tests/baselines/reference/commonSourceDir4.js b/tests/baselines/reference/commonSourceDir4.js new file mode 100644 index 00000000000..2f2af9f68b2 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir4.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir4.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt new file mode 100644 index 00000000000..93a35292b70 --- /dev/null +++ b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts(1,24): error TS2304: Cannot find name 'b'. + + +==== tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts (1 errors) ==== + function bar(): typeof b { + ~ +!!! error TS2304: Cannot find name 'b'. + var b = 1; + return undefined; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js new file mode 100644 index 00000000000..191255e52c2 --- /dev/null +++ b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js @@ -0,0 +1,11 @@ +//// [functionVariableInReturnTypeAnnotation.ts] +function bar(): typeof b { + var b = 1; + return undefined; +} + +//// [functionVariableInReturnTypeAnnotation.js] +function bar() { + var b = 1; + return undefined; +} diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt new file mode 100644 index 00000000000..54ddb963f94 --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt @@ -0,0 +1,44 @@ +tests/cases/compiler/parameterNamesInTypeParameterList.ts(1,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(5,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(9,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(14,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(17,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(20,22): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/parameterNamesInTypeParameterList.ts (6 errors) ==== + function f0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + class A { + m0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.js b/tests/baselines/reference/parameterNamesInTypeParameterList.js new file mode 100644 index 00000000000..2fbd7fad3cb --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.js @@ -0,0 +1,53 @@ +//// [parameterNamesInTypeParameterList.ts] +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} + +//// [parameterNamesInTypeParameterList.js] +function f0(a) { + a.b; +} +function f1(_a) { + var a = _a.a; + a.b; +} +function f2(_a) { + var a = _a[0]; + a.b; +} +var A = (function () { + function A() { + } + A.prototype.m0 = function (a) { + a.b; + }; + A.prototype.m1 = function (_a) { + var a = _a.a; + a.b; + }; + A.prototype.m2 = function (_a) { + var a = _a[0]; + a.b; + }; + return A; +})(); diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt new file mode 100644 index 00000000000..872a0a10923 --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt @@ -0,0 +1,17 @@ +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,10): error TS2304: Cannot find name 'T'. +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,13): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/typeParametersAndParametersInComputedNames.ts (2 errors) ==== + function foo(a: T) : string { + return ""; + } + + class A { + [foo(a)](a: T) { + ~ +!!! error TS2304: Cannot find name 'T'. + ~ +!!! error TS2304: Cannot find name 'a'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.js b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js new file mode 100644 index 00000000000..1cb53663fbd --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js @@ -0,0 +1,21 @@ +//// [typeParametersAndParametersInComputedNames.ts] +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} + +//// [typeParametersAndParametersInComputedNames.js] +function foo(a) { + return ""; +} +var A = (function () { + function A() { + } + A.prototype[foo(a)] = function (a) { + }; + return A; +})(); diff --git a/tests/cases/compiler/commonSourceDir1.ts b/tests/cases/compiler/commonSourceDir1.ts new file mode 100644 index 00000000000..1a178ac0226 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir1.ts @@ -0,0 +1,6 @@ +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: A:/foo/baz.ts +var y: number; diff --git a/tests/cases/compiler/commonSourceDir2.ts b/tests/cases/compiler/commonSourceDir2.ts new file mode 100644 index 00000000000..68dab0727a3 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir2.ts @@ -0,0 +1,6 @@ +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: B:/foo/baz.ts +var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/commonSourceDir3.ts b/tests/cases/compiler/commonSourceDir3.ts new file mode 100644 index 00000000000..54b6e8c89b7 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir3.ts @@ -0,0 +1,7 @@ +// @useCaseSensitiveFileNames: false +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: a:/foo/baz.ts +var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/commonSourceDir4.ts b/tests/cases/compiler/commonSourceDir4.ts new file mode 100644 index 00000000000..41ee7a0344a --- /dev/null +++ b/tests/cases/compiler/commonSourceDir4.ts @@ -0,0 +1,7 @@ +// @useCaseSensitiveFileNames: true +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: a:/foo/baz.ts +var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts b/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts new file mode 100644 index 00000000000..c8936034a25 --- /dev/null +++ b/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts @@ -0,0 +1,4 @@ +function bar(): typeof b { + var b = 1; + return undefined; +} \ No newline at end of file diff --git a/tests/cases/compiler/parameterNamesInTypeParameterList.ts b/tests/cases/compiler/parameterNamesInTypeParameterList.ts new file mode 100644 index 00000000000..dba122db866 --- /dev/null +++ b/tests/cases/compiler/parameterNamesInTypeParameterList.ts @@ -0,0 +1,23 @@ +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} \ No newline at end of file diff --git a/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts new file mode 100644 index 00000000000..273dcb2a3ea --- /dev/null +++ b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts @@ -0,0 +1,8 @@ +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} \ No newline at end of file diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index 06c2cadbfe9..c1d283ca8cd 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -20,7 +20,10 @@ module ts { } describe('VersionCache TS code', () => { - var testContent = `/// + let validateEditAtLineCharIndex: (line: number, char: number, deleteLength: number, insertString: string) => void; + + before(() => { + let testContent = `/// var x = 10; var y = { zebra: 12, giraffe: "ell" }; z.a; @@ -31,16 +34,21 @@ k=y; var p:Point=new Point(); var q:Point=p;` - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + let {lines, lineMap} = server.LineIndex.linesFromText(testContent); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); + let lineIndex = new server.LineIndex(); + lineIndex.load(lines); - function validateEditAtLineCharIndex(line: number, char: number, deleteLength: number, insertString: string): void { - let position = lineColToPosition(lineIndex, line, char); - validateEdit(lineIndex, testContent, position, deleteLength, insertString); - } + validateEditAtLineCharIndex = (line: number, char: number, deleteLength: number, insertString: string) => { + let position = lineColToPosition(lineIndex, line, char); + validateEdit(lineIndex, testContent, position, deleteLength, insertString); + }; + }); + + after(() => { + validateEditAtLineCharIndex = undefined; + }) it('change 9 1 0 1 {"y"}', () => { validateEditAtLineCharIndex(9, 1, 0, "y"); @@ -68,22 +76,35 @@ var q:Point=p;` }); describe('VersionCache simple text', () => { - let testContent = `in this story: + let validateEditAtPosition: (position: number, deleteLength: number, insertString: string) => void; + let testContent: string; + let lines: string[]; + let lineMap: number[]; + before(() => { + testContent = `in this story: the lazy brown fox jumped over the cow that ate the grass that was purple at the tips and grew 1cm per day`; - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); + let lineIndex = new server.LineIndex(); + lineIndex.load(lines); - function validateEditAtPosition(position: number, deleteLength: number, insertString: string): void { - validateEdit(lineIndex, testContent, position, deleteLength, insertString); - } + validateEditAtPosition = (position: number, deleteLength: number, insertString: string) => { + validateEdit(lineIndex, testContent, position, deleteLength, insertString); + } + }); + + after(() => { + validateEditAtPosition = undefined; + testContent = undefined; + lines = undefined; + lineMap = undefined; + }); it('Insert at end of file', () => { validateEditAtPosition(testContent.length, 0, "hmmmm...\r\n"); @@ -159,50 +180,69 @@ and grew 1cm per day`; }); describe('VersionCache stress test', () => { - const iterationCount = 20; - //const interationCount = 20000; // uncomment for testing - - // Use scanner.ts, decent size, does not change frequentlly - let testFileName = "src/compiler/scanner.ts"; - let testContent = Harness.IO.readFile(testFileName); - let totalChars = testContent.length; - assert.isTrue(totalChars > 0, "Failed to read test file."); - - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); - let rsa: number[] = []; let la: number[] = []; let las: number[] = []; let elas: number[] = []; let ersa: number[] = []; let ela: number[] = []; - let etotalChars = totalChars; + const iterationCount = 20; + //const iterationCount = 20000; // uncomment for testing + let lines: string[]; + let lineMap: number[]; + let lineIndex: server.LineIndex; + let testContent: string; - for (let j = 0; j < 100000; j++) { - rsa[j] = Math.floor(Math.random() * totalChars); - la[j] = Math.floor(Math.random() * (totalChars - rsa[j])); - if (la[j] > 4) { - las[j] = 4; - } - else { - las[j] = la[j]; - } - if (j < 4000) { - ersa[j] = Math.floor(Math.random() * etotalChars); - ela[j] = Math.floor(Math.random() * (etotalChars - ersa[j])); - if (ela[j] > 4) { - elas[j] = 4; + before(() => { + // Use scanner.ts, decent size, does not change frequently + let testFileName = "src/compiler/scanner.ts"; + testContent = Harness.IO.readFile(testFileName); + let totalChars = testContent.length; + assert.isTrue(totalChars > 0, "Failed to read test file."); + + ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + + lineIndex = new server.LineIndex(); + lineIndex.load(lines); + + let etotalChars = totalChars; + + for (let j = 0; j < 100000; j++) { + rsa[j] = Math.floor(Math.random() * totalChars); + la[j] = Math.floor(Math.random() * (totalChars - rsa[j])); + if (la[j] > 4) { + las[j] = 4; } else { - elas[j] = ela[j]; + las[j] = la[j]; + } + if (j < 4000) { + ersa[j] = Math.floor(Math.random() * etotalChars); + ela[j] = Math.floor(Math.random() * (etotalChars - ersa[j])); + if (ela[j] > 4) { + elas[j] = 4; + } + else { + elas[j] = ela[j]; + } + etotalChars += (las[j] - elas[j]); } - etotalChars += (las[j] - elas[j]); } - } + }); + + after(() => { + rsa = undefined; + la = undefined; + las = undefined; + elas = undefined; + ersa = undefined; + ela = undefined; + lines = undefined; + lineMap = undefined; + lineIndex = undefined; + testContent = undefined; + }); it("Range (average length 1/4 file size)", () => { for (let i = 0; i < iterationCount; i++) {