From 79b7146d0bbb3c80cb3a73a6fa2d86894af97d6a Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 10 Nov 2015 13:30:26 -0800 Subject: [PATCH] Cleanup of types --- src/compiler/checker.ts | 2 +- src/compiler/parser.ts | 56 +++---- src/compiler/types.ts | 337 +++++++++++++++++++++++++++++++++----- src/compiler/utilities.ts | 4 +- src/services/services.ts | 96 +++++------ 5 files changed, 371 insertions(+), 124 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f1593abb17763..bfd2eb8d7b878 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9766,7 +9766,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/parser.ts b/src/compiler/parser.ts index 18e9cdea4062f..39b5a5d322eaf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1082,7 +1082,7 @@ namespace ts { token === SyntaxKind.NumericLiteral; } - function parsePropertyNameWorker(allowComputedPropertyNames: boolean): DeclarationName { + function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { return parseLiteralNode(/*internName*/ true); } @@ -1092,7 +1092,7 @@ namespace ts { return parseIdentifierName(); } - function parsePropertyName(): DeclarationName { + function parsePropertyName(): PropertyName { return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true); } @@ -1152,7 +1152,7 @@ namespace ts { } function parseAnyContextualModifier(): boolean { - return isModifier(token) && tryParse(nextTokenCanFollowModifier); + return isModifierKind(token) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier(): boolean { @@ -1999,7 +1999,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) { @@ -2020,7 +2020,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) @@ -2127,8 +2127,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); } @@ -2167,7 +2167,7 @@ namespace ts { return true; } - if (isModifier(token)) { + if (isModifierKind(token)) { nextToken(); if (isIdentifier()) { return true; @@ -2210,13 +2210,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; @@ -2227,7 +2227,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(); @@ -2243,7 +2243,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; @@ -2255,7 +2255,7 @@ namespace ts { } function isStartOfIndexSignatureDeclaration() { - while (isModifier(token)) { + while (isModifierKind(token)) { nextToken(); } @@ -2271,7 +2271,7 @@ namespace ts { canParseSemicolon(); } - function parseTypeMember(): Declaration { + function parseTypeMember(): TypeElement { switch (token) { case SyntaxKind.OpenParenToken: case SyntaxKind.LessThanToken: @@ -2296,7 +2296,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; @@ -2329,14 +2329,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; @@ -2478,11 +2478,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 ? @@ -2889,7 +2889,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 { @@ -2988,7 +2988,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 @@ -3215,7 +3215,7 @@ namespace ts { /** * Parse ES7 unary expression and await expression - * + * * ES7 UnaryExpression: * 1) SimpleUnaryExpression[?yield] * 2) IncrementExpression[?yield] ** UnaryExpression[?yield] @@ -4716,7 +4716,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); @@ -4730,7 +4730,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); @@ -4804,7 +4804,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 @@ -5014,8 +5014,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/types.ts b/src/compiler/types.ts index 08313f832a2ad..2489c049b6885 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; @@ -491,6 +505,8 @@ 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 { @@ -498,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; @@ -515,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 @@ -528,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 @@ -541,7 +572,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - // SyntaxKind.BindingElement + // @kind(SyntaxKind.BindingElement) export interface BindingElement extends Declaration { propertyName?: Identifier; // Binding property name (in object binding pattern) dotDotDotToken?: Node; // Present on rest binding element @@ -549,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; @@ -595,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. @@ -615,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. @@ -629,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; } @@ -646,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; } @@ -661,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; } @@ -692,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; } @@ -718,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; } @@ -726,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; @@ -748,37 +842,49 @@ 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) export interface BinaryExpression extends Expression { left: Expression; operatorToken: Node; right: Expression; } + // @kind(SyntaxKind.ConditionalExpression) export interface ConditionalExpression extends Expression { condition: Expression; questionToken: Node; @@ -787,24 +893,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; @@ -812,52 +931,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 { 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; @@ -865,11 +995,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; @@ -878,6 +1010,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; @@ -885,6 +1018,7 @@ namespace ts { } /// The opening element of a ... JsxElement + // @kind(SyntaxKind.JsxOpeningElement) export interface JsxOpeningElement extends Expression { _openingElementBrand?: any; tagName: EntityName; @@ -892,6 +1026,7 @@ namespace ts { } /// A JSX expression of the form + // @kind(SyntaxKind.JsxSelfClosingElement) export interface JsxSelfClosingElement extends PrimaryExpression, JsxOpeningElement { _selfClosingElementBrand?: any; } @@ -899,24 +1034,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; } @@ -927,18 +1067,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; @@ -949,78 +1107,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; @@ -1033,34 +1214,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 @@ -1068,21 +1264,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 @@ -1090,6 +1292,7 @@ namespace ts { moduleReference: EntityName | ExternalModuleReference; } + // @kind(SyntaxKind.ExternalModuleReference) export interface ExternalModuleReference extends Node { expression?: Expression; } @@ -1098,6 +1301,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; @@ -1109,36 +1313,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 type NamedImportsOrExports = NamedImports | NamedExports; - export interface ImportOrExportSpecifier extends Declaration { + // @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 type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - export interface ExportAssignment extends Declaration, Statement { + // @kind(SyntaxKind.ExportAssignment) + export interface ExportAssignment extends DeclarationStatement { isExportEquals?: boolean; expression: Expression; } @@ -1153,6 +1372,7 @@ namespace ts { } // represents a top level: { type } expression in a JSDoc comment. + // @kind(SyntaxKind.JSDocTypeExpression) export interface JSDocTypeExpression extends Node { type: JSDocType; } @@ -1161,90 +1381,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; @@ -1252,7 +1493,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; @@ -1261,7 +1508,7 @@ namespace ts { /* internal */ path: Path; text: string; - amdDependencies: {path: string; name: string}[]; + amdDependencies: AmdDependency[]; moduleName: string; referencedFiles: FileReference[]; languageVariant: LanguageVariant; @@ -2336,7 +2583,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; } @@ -2344,7 +2591,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 */ @@ -2367,11 +2614,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 17d780df57458..199ca4e636f41 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1273,7 +1273,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; } @@ -1483,7 +1483,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/services/services.ts b/src/services/services.ts index 113a52459e9cb..529a70b14536b 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[]; @@ -816,7 +816,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); } @@ -1030,7 +1030,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[]; @@ -1854,7 +1854,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(); @@ -2574,7 +2574,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); @@ -2662,10 +2662,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 @@ -3068,7 +3068,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; @@ -3101,7 +3101,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; @@ -3622,8 +3622,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; } @@ -3672,7 +3672,7 @@ namespace ts { containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A