From 0123bd0e208c1cd5353b82adc3b9b22a6f1618b7 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sat, 17 Jun 2017 09:20:55 -0700 Subject: [PATCH 01/22] Add missing newline in --pretty diagnostics formatter It was compensated in tsc.ts, but then other compilers are missing a newline. --- src/compiler/program.ts | 1 + src/compiler/tsc.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bbc0fa09780..efe0c31ef1f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -332,6 +332,7 @@ namespace ts { const categoryColor = getCategoryFormat(diagnostic.category); const category = DiagnosticCategory[diagnostic.category].toLowerCase(); output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; + output += sys.newLine; } return output; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 3b2422bfe08..c502bb916d2 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -61,7 +61,7 @@ namespace ts { } function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: FormatDiagnosticsHost): void { - sys.write(ts.formatDiagnosticsWithColorAndContext([diagnostic], host) + sys.newLine + sys.newLine); + sys.write(ts.formatDiagnosticsWithColorAndContext([diagnostic], host) + sys.newLine); } function reportWatchDiagnostic(diagnostic: Diagnostic) { From bc69c7e6d15caec28483018c2d6bfb669b572487 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 13 Jul 2017 11:27:50 -0700 Subject: [PATCH 02/22] Parse JSDoc types using the normal TS parser This means that JSDoc types can include the full range of Typescript types now. It also means that Typescript annotations can include JSDoc types. This is disallowed with a new error, however. But Typescript can still give the correct types to JSDoc that shows up in .ts files by mistake. This can easily happen, for example with types like ```ts var x: number? = null; var y: ?string = null; var z: function(string,string): string = (s,t) => s + t; // less likely to show up, but still understood. var ka: ? = 1; ``` In the future, I will add a quick fix to convert these into the correct types. Fixes #16550 --- src/compiler/binder.ts | 25 +- src/compiler/checker.ts | 99 +++-- src/compiler/diagnosticMessages.json | 29 +- src/compiler/parser.ts | 510 +++++++------------------- src/compiler/types.ts | 81 +--- src/compiler/utilities.ts | 37 +- src/harness/unittests/jsDocParsing.ts | 14 +- src/services/utilities.ts | 1 - 8 files changed, 254 insertions(+), 542 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e7b759ff64f..0c3f1a2444d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -280,7 +280,14 @@ namespace ts { Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); const functionType = node.parent; const index = indexOf(functionType.parameters, node); - return "arg" + index as __String; + switch ((node as ParameterDeclaration).type.kind) { + case SyntaxKind.JSDocThisType: + return "this" as __String; + case SyntaxKind.JSDocConstructorType: + return "new" as __String; + default: + return "arg" + index as __String; + } case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; let nameFromParentNode: __String; @@ -1395,14 +1402,12 @@ namespace ts { case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.TypeLiteral: case SyntaxKind.JSDocTypeLiteral: - case SyntaxKind.JSDocRecordType: case SyntaxKind.JsxAttributes: return ContainerFlags.IsContainer; case SyntaxKind.InterfaceDeclaration: return ContainerFlags.IsContainer | ContainerFlags.IsInterface; - case SyntaxKind.JSDocFunctionType: case SyntaxKind.ModuleDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.MappedType: @@ -1422,9 +1427,10 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.CallSignature: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.FunctionType: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike; @@ -1502,7 +1508,6 @@ namespace ts { case SyntaxKind.TypeLiteral: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.JSDocRecordType: case SyntaxKind.JSDocTypeLiteral: case SyntaxKind.JsxAttributes: // Interface/Object-types always have their children added to the 'members' of @@ -2095,6 +2100,7 @@ namespace ts { case SyntaxKind.SetAccessor: return bindPropertyOrMethodOrAccessor(node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); case SyntaxKind.FunctionType: + case SyntaxKind.JSDocFunctionType: case SyntaxKind.ConstructorType: return bindFunctionOrConstructorType(node); case SyntaxKind.TypeLiteral: @@ -2157,18 +2163,13 @@ namespace ts { case SyntaxKind.ModuleBlock: return updateStrictModeStatementList((node).statements); - case SyntaxKind.JSDocRecordMember: - return bindPropertyWorker(node as JSDocRecordMember); case SyntaxKind.JSDocPropertyTag: return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, (node as JSDocPropertyTag).isBracketed || ((node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) ? SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property, SymbolFlags.PropertyExcludes); - case SyntaxKind.JSDocFunctionType: - return bindFunctionOrConstructorType(node); case SyntaxKind.JSDocTypeLiteral: - case SyntaxKind.JSDocRecordType: - return bindAnonymousTypeWorker(node as JSDocTypeLiteral | JSDocRecordType); + return bindAnonymousTypeWorker(node as JSDocTypeLiteral); case SyntaxKind.JSDocTypedefTag: { const { fullName } = node as JSDocTypedefTag; if (!fullName || fullName.kind === SyntaxKind.Identifier) { @@ -2183,7 +2184,7 @@ namespace ts { return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); } - function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) { + function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral) { return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, InternalSymbolName.Type); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c5fcc36e4d..cd1fbcc379b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6339,7 +6339,7 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - if (i === 0 && paramSymbol.name === "this") { + if (i === 0 && paramSymbol.name === "this" || (param.type && param.type.kind === SyntaxKind.JSDocThisType)) { hasThisParameter = true; thisParameter = param.symbol; } @@ -6798,8 +6798,6 @@ namespace ts { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; - case SyntaxKind.JSDocTypeReference: - return (node).name; case SyntaxKind.ExpressionWithTypeArguments: // We only support expressions that are simple qualified names. For other // expressions this produces undefined. @@ -6807,7 +6805,6 @@ namespace ts { if (isEntityNameExpression(expr)) { return expr; } - // fall through; } @@ -6833,8 +6830,8 @@ namespace ts { return type; } - if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) { - // A JSDocTypeReference may have resolved to a value (as opposed to a type). If + if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) { + // A jsdoc TypeReference may have resolved to a value (as opposed to a type). If // the symbol is a constructor function, return the inferred class type; otherwise, // the type of this reference is just the type of the value we resolved to. const valueType = getTypeOfSymbol(symbol); @@ -6862,14 +6859,16 @@ namespace ts { return getTypeFromTypeAliasReference(node, symbol, typeArguments); } - if (symbol.flags & SymbolFlags.Function && node.kind === SyntaxKind.JSDocTypeReference && (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) { + if (symbol.flags & SymbolFlags.Function && + isJSDocTypeReference(node) && + (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) { return getInferredClassType(symbol); } } - function getPrimitiveTypeFromJSDocTypeReference(node: JSDocTypeReference): Type { - if (isIdentifier(node.name)) { - switch (node.name.text) { + function getPrimitiveTypeFromJSDocTypeReference(node: TypeReferenceNode): Type { + if (isIdentifier(node.typeName)) { + switch (node.typeName.text) { case "String": return stringType; case "Number": @@ -6909,7 +6908,7 @@ namespace ts { let symbol: Symbol; let type: Type; let meaning = SymbolFlags.Type; - if (node.kind === SyntaxKind.JSDocTypeReference) { + if (isJSDocTypeReference(node)) { type = getPrimitiveTypeFromJSDocTypeReference(node); meaning |= SymbolFlags.Value; } @@ -7799,15 +7798,6 @@ namespace ts { return links.resolvedType; } - function getTypeFromJSDocTupleType(node: JSDocTupleType): Type { - const links = getNodeLinks(node); - if (!links.resolvedType) { - const types = map(node.types, getTypeFromTypeNode); - links.resolvedType = createTupleType(types); - } - return links.resolvedType; - } - function getThisType(node: Node): Type { const container = getThisContainer(node, /*includeArrowFunctions*/ false); const parent = container && container.parent; @@ -7852,16 +7842,18 @@ namespace ts { case SyntaxKind.NeverKeyword: return neverType; case SyntaxKind.ObjectKeyword: - return nonPrimitiveType; + if (node.flags & NodeFlags.JavaScriptFile) { + return anyType; + } + else { + return nonPrimitiveType; + } case SyntaxKind.ThisType: case SyntaxKind.ThisKeyword: return getTypeFromThisTypeNode(node); case SyntaxKind.LiteralType: return getTypeFromLiteralTypeNode(node); - case SyntaxKind.JSDocLiteralType: - return getTypeFromLiteralTypeNode((node).literal); case SyntaxKind.TypeReference: - case SyntaxKind.JSDocTypeReference: return getTypeFromTypeReference(node); case SyntaxKind.TypePredicate: return booleanType; @@ -7870,12 +7862,10 @@ namespace ts { case SyntaxKind.TypeQuery: return getTypeFromTypeQueryNode(node); case SyntaxKind.ArrayType: - case SyntaxKind.JSDocArrayType: return getTypeFromArrayTypeNode(node); case SyntaxKind.TupleType: return getTypeFromTupleTypeNode(node); case SyntaxKind.UnionType: - case SyntaxKind.JSDocUnionType: return getTypeFromUnionTypeNode(node); case SyntaxKind.IntersectionType: return getTypeFromIntersectionTypeNode(node); @@ -7887,8 +7877,6 @@ namespace ts { case SyntaxKind.JSDocThisType: case SyntaxKind.JSDocOptionalType: return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocRecordType: - return getTypeFromTypeNode((node as JSDocRecordType).literal); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: case SyntaxKind.TypeLiteral: @@ -7907,8 +7895,6 @@ namespace ts { case SyntaxKind.QualifiedName: const symbol = getSymbolAtLocation(node); return symbol && getDeclaredTypeOfSymbol(symbol); - case SyntaxKind.JSDocTupleType: - return getTypeFromJSDocTupleType(node); case SyntaxKind.JSDocVariadicType: return getTypeFromJSDocVariadicType(node); default: @@ -18474,6 +18460,9 @@ namespace ts { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); + if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDot && !isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { + grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_used_inside_documentation_comments); + } const type = getTypeFromTypeReference(node); if (type !== unknownType) { if (node.typeArguments) { @@ -19372,7 +19361,17 @@ namespace ts { } } + function checkJsDoc(node: FunctionDeclaration | MethodDeclaration) { + if (!node.jsDoc) { + return; + } + for (const doc of node.jsDoc) { + checkSourceElement(doc); + } + } + function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void { + checkJsDoc(node); checkDecorators(node); checkSignatureDeclaration(node); const functionFlags = getFunctionFlags(node); @@ -21971,6 +21970,22 @@ namespace ts { } } + function checkJSDocComment(node: JSDoc) { + if (isInJavaScriptFile(node) && (node as JSDoc).tags) { + for (const tag of (node as JSDoc).tags) { + checkSourceElement(tag); + } + } + } + + function checkJSDocFunctionType(node: JSDocFunctionType) { + for (const p of node.parameters) { + // don't bother with normal parameter checking since jsdoc function parameters only consist of a type + checkSourceElement(p.type); + } + checkSourceElement(node.type); + } + function checkSourceElement(node: Node): void { if (!node) { return; @@ -22030,6 +22045,26 @@ namespace ts { case SyntaxKind.ParenthesizedType: case SyntaxKind.TypeOperator: return checkSourceElement((node).type); + case SyntaxKind.JSDocComment: + return checkJSDocComment(node as JSDoc); + case SyntaxKind.JSDocParameterTag: + return checkSourceElement((node as JSDocParameterTag).typeExpression); + case SyntaxKind.JSDocFunctionType: + checkJSDocFunctionType(node as JSDocFunctionType); + // falls through + case SyntaxKind.JSDocConstructorType: + case SyntaxKind.JSDocThisType: + case SyntaxKind.JSDocVariadicType: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + if (!isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { + grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_used_inside_documentation_comments); + } + return; + case SyntaxKind.JSDocTypeExpression: + return checkSourceElement((node as JSDocTypeExpression).type); case SyntaxKind.IndexedAccessType: return checkIndexedAccessType(node); case SyntaxKind.MappedType: @@ -22386,7 +22421,7 @@ namespace ts { node = node.parent; } - return node.parent && (node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.JSDocTypeReference) ; + return node.parent && node.parent.kind === SyntaxKind.TypeReference ; } function isHeritageClauseElementIdentifier(entityName: Node): boolean { @@ -22540,7 +22575,7 @@ namespace ts { } } else if (isTypeReferenceIdentifier(entityName)) { - const meaning = (entityName.parent.kind === SyntaxKind.TypeReference || entityName.parent.kind === SyntaxKind.JSDocTypeReference) ? SymbolFlags.Type : SymbolFlags.Namespace; + const meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace; return resolveEntityName(entityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } else if (entityName.parent.kind === SyntaxKind.JsxAttribute) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cf198ec06ec..cee632634a9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3463,6 +3463,22 @@ "category": "Error", "code": 8016 }, + "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { + "category": "Error", + "code": 8017 + }, + "Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": { + "category": "Error", + "code": 8018 + }, + "Report errors in .js files.": { + "category": "Message", + "code": 8019 + }, + "JSDoc types can only used inside documentation comments.": { + "category": "Error", + "code": 8020 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 @@ -3645,18 +3661,5 @@ "Convert function '{0}' to class": { "category": "Message", "code": 95002 - }, - - "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { - "category": "Error", - "code": 8017 - }, - "Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": { - "category": "Error", - "code": 8018 - }, - "Report errors in .js files.": { - "category": "Message", - "code": 8019 } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 089bff53a05..41abbf59305 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -9,6 +9,7 @@ namespace ts { Type = 1 << 2, RequireCompleteParameterList = 1 << 3, IgnoreMissingOpenBrace = 1 << 4, + JSDoc = 1 << 5, } let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; @@ -392,21 +393,10 @@ namespace ts { case SyntaxKind.JSDocTypeExpression: return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocUnionType: - return visitNodes(cbNode, cbNodes, (node).types); - case SyntaxKind.JSDocTupleType: - return visitNodes(cbNode, cbNodes, (node).types); - case SyntaxKind.JSDocArrayType: - return visitNode(cbNode, (node).elementType); case SyntaxKind.JSDocNonNullableType: return visitNode(cbNode, (node).type); case SyntaxKind.JSDocNullableType: return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocRecordType: - return visitNode(cbNode, (node).literal); - case SyntaxKind.JSDocTypeReference: - return visitNode(cbNode, (node).name) || - visitNodes(cbNode, cbNodes, (node).typeArguments); case SyntaxKind.JSDocOptionalType: return visitNode(cbNode, (node).type); case SyntaxKind.JSDocFunctionType: @@ -418,9 +408,6 @@ namespace ts { return visitNode(cbNode, (node).type); case SyntaxKind.JSDocThisType: return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocRecordMember: - return visitNode(cbNode, (node).name) || - visitNode(cbNode, (node).type); case SyntaxKind.JSDocComment: return visitNodes(cbNode, cbNodes, (node).tags); case SyntaxKind.JSDocParameterTag: @@ -447,8 +434,6 @@ namespace ts { visitNode(cbNode, (node).name); case SyntaxKind.PartiallyEmittedExpression: return visitNode(cbNode, (node).expression); - case SyntaxKind.JSDocLiteralType: - return visitNode(cbNode, (node).literal); } } @@ -1239,14 +1224,6 @@ namespace ts { return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } - function parseSimplePropertyName(): Identifier | LiteralExpression { - return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); - } - - function isSimplePropertyName() { - return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral || tokenIsIdentifierOrKeyword(token()); - } - function parseComputedPropertyName(): ComputedPropertyName { // PropertyName [Yield]: // LiteralPropertyName @@ -1394,12 +1371,6 @@ namespace ts { return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken; case ParsingContext.JsxChildren: return true; - case ParsingContext.JSDocFunctionParameters: - case ParsingContext.JSDocTypeArguments: - case ParsingContext.JSDocTupleTypes: - return JSDocParser.isJSDocType(); - case ParsingContext.JSDocRecordMembers: - return isSimplePropertyName(); } Debug.fail("Non-exhaustive case in 'isListElement'."); @@ -1494,14 +1465,6 @@ namespace ts { return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken; case ParsingContext.JsxChildren: return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash); - case ParsingContext.JSDocFunctionParameters: - return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.ColonToken || token() === SyntaxKind.CloseBraceToken; - case ParsingContext.JSDocTypeArguments: - return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.CloseBraceToken; - case ParsingContext.JSDocTupleTypes: - return token() === SyntaxKind.CloseBracketToken || token() === SyntaxKind.CloseBraceToken; - case ParsingContext.JSDocRecordMembers: - return token() === SyntaxKind.CloseBraceToken; } } @@ -1887,10 +1850,6 @@ namespace ts { case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected; case ParsingContext.JsxAttributes: return Diagnostics.Identifier_expected; case ParsingContext.JsxChildren: return Diagnostics.Identifier_expected; - case ParsingContext.JSDocFunctionParameters: return Diagnostics.Parameter_declaration_expected; - case ParsingContext.JSDocTypeArguments: return Diagnostics.Type_argument_expected; - case ParsingContext.JSDocTupleTypes: return Diagnostics.Type_expected; - case ParsingContext.JSDocRecordMembers: return Diagnostics.Property_assignment_expected; } } @@ -1969,9 +1928,14 @@ namespace ts { // The allowReservedWords parameter controls whether reserved words are permitted after the first dot function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { - let entity: EntityName = parseIdentifier(diagnosticMessage); + let entity: EntityName = allowReservedWords ? parseIdentifierName() : parseIdentifier(diagnosticMessage); while (parseOptional(SyntaxKind.DotToken)) { - const node: QualifiedName = createNode(SyntaxKind.QualifiedName, entity.pos); // !!! + if (token() === SyntaxKind.LessThanToken) { + // the entity is part of a JSDoc-style generic, so record this for later in case it's an error + entity.jsdocDot = true; + break; + } + const node: QualifiedName = createNode(SyntaxKind.QualifiedName, entity.pos); node.left = entity; node.right = parseRightSideOfDot(allowReservedWords); entity = finishNode(node); @@ -2098,7 +2062,7 @@ namespace ts { function parseTypeReference(): TypeReferenceNode { const node = createNode(SyntaxKind.TypeReference); - node.typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected); + node.typeName = parseEntityName(/*allowReservedWords*/ !!(contextFlags & NodeFlags.JSDoc), Diagnostics.Type_expected); if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.LessThanToken) { node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); } @@ -2119,6 +2083,69 @@ namespace ts { return finishNode(node); } + function parseJSDocAllType(): JSDocAllType { + const result = createNode(SyntaxKind.JSDocAllType); + nextToken(); + return finishNode(result); + } + + function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { + const pos = scanner.getStartPos(); + // skip the ? + nextToken(); + + // Need to lookahead to decide if this is a nullable or unknown type. + + // Here are cases where we'll pick the unknown type: + // + // Foo(?, + // { a: ? } + // Foo(?) + // Foo + // Foo(?= + // (?| + if (token() === SyntaxKind.CommaToken || + token() === SyntaxKind.CloseBraceToken || + token() === SyntaxKind.CloseParenToken || + token() === SyntaxKind.GreaterThanToken || + token() === SyntaxKind.EqualsToken || + token() === SyntaxKind.BarToken) { + + const result = createNode(SyntaxKind.JSDocUnknownType, pos); + return finishNode(result); + } + else { + const result = createNode(SyntaxKind.JSDocNullableType, pos); + result.type = parseType(); + return finishNode(result); + } + } + + function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode { + if (lookAhead(nextTokenIsOpenParen)) { + const result = createNode(SyntaxKind.JSDocFunctionType); + nextToken(); + fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type | SignatureFlags.JSDoc, result); + return finishNode(result); + } + const node = createNode(SyntaxKind.TypeReference); + node.typeName = parseIdentifierName(); + return finishNode(node); + } + + function parseJSDocParameter(): ParameterDeclaration { + const parameter = createNode(SyntaxKind.Parameter); + parameter.type = parseType(); + return finishNode(parameter); + } + + function parseJSDocNodeWithType(kind: SyntaxKind): TypeNode { + const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType | JSDocThisType | JSDocConstructorType; + nextToken(); + result.type = parseType(); + return finishNode(result); + } + function parseTypeQuery(): TypeQueryNode { const node = createNode(SyntaxKind.TypeQuery); parseExpected(SyntaxKind.TypeOfKeyword); @@ -2171,7 +2198,7 @@ namespace ts { } function isStartOfParameter(): boolean { - return token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token()) || token() === SyntaxKind.AtToken || token() === SyntaxKind.ThisKeyword; + return token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token()) || token() === SyntaxKind.AtToken || token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword; } function parseParameter(): ParameterDeclaration { @@ -2229,7 +2256,9 @@ namespace ts { returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, flags: SignatureFlags, signature: SignatureDeclaration): void { - signature.typeParameters = parseTypeParameters(); + if (!(flags & SignatureFlags.JSDoc)) { + signature.typeParameters = parseTypeParameters(); + } signature.parameters = parseParameterList(flags); const returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken; @@ -2273,7 +2302,7 @@ namespace ts { setYieldContext(!!(flags & SignatureFlags.Yield)); setAwaitContext(!!(flags & SignatureFlags.Await)); - const result = parseDelimitedList(ParsingContext.Parameters, parseParameter); + const result = parseDelimitedList(ParsingContext.Parameters, flags & SignatureFlags.JSDoc ? parseJSDocParameter : parseParameter); setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); @@ -2538,10 +2567,14 @@ namespace ts { return finishNode(node); } - function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode | JSDocConstructorType { const node = createNode(kind); if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); + if (token() === SyntaxKind.ColonToken) { + // JSDoc -- `new:T` as in `function(new:T, string, string)`; an infix constructor-return-type + return parseJSDocNodeWithType(SyntaxKind.JSDocConstructorType) as JSDocConstructorType; + } } fillSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type, node); return finishNode(node); @@ -2574,8 +2607,17 @@ namespace ts { case SyntaxKind.NeverKeyword: case SyntaxKind.ObjectKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. - const node = tryParse(parseKeywordAndNoDot); - return node || parseTypeReference(); + return tryParse(parseKeywordAndNoDot) || parseTypeReference(); + case SyntaxKind.AsteriskToken: + return parseJSDocAllType(); + case SyntaxKind.QuestionToken: + return parseJSDocUnknownOrNullableType(); + case SyntaxKind.FunctionKeyword: + return parseJSDocFunctionType(); + case SyntaxKind.DotDotDotToken: + return parseJSDocNodeWithType(SyntaxKind.JSDocVariadicType); + case SyntaxKind.ExclamationToken: + return parseJSDocNodeWithType(SyntaxKind.JSDocNonNullableType); case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: case SyntaxKind.TrueKeyword: @@ -2591,6 +2633,9 @@ namespace ts { if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { return parseThisTypePredicate(thisKeyword); } + else if (token() === SyntaxKind.ColonToken) { + return parseJSDocNodeWithType(SyntaxKind.JSDocThisType); + } else { return thisKeyword; } @@ -2649,6 +2694,26 @@ namespace ts { return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); } + function parseJSDocPostfixTypeOrHigher(): TypeNode { + let type = parseArrayTypeOrHigher(); + let postfix: JSDocOptionalType | JSDocNonNullableType | JSDocNullableType; + // only parse postfix = inside jsdoc, because it's ambiguous elsewhere + if (contextFlags & NodeFlags.JSDoc && parseOptional(SyntaxKind.EqualsToken)) { + postfix = createNode(SyntaxKind.JSDocOptionalType, type.pos) as JSDocOptionalType; + } + else if (parseOptional(SyntaxKind.ExclamationToken)) { + postfix = createNode(SyntaxKind.JSDocNonNullableType, type.pos) as JSDocNonNullableType; + } + else if (parseOptional(SyntaxKind.QuestionToken)) { + postfix = createNode(SyntaxKind.JSDocNullableType, type.pos) as JSDocNullableType; + } + if (postfix) { + postfix.type = type; + type = finishNode(postfix); + } + return type; + } + function parseArrayTypeOrHigher(): TypeNode { let type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { @@ -2682,7 +2747,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseArrayTypeOrHigher(); + return parseJSDocPostfixTypeOrHigher(); } function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { @@ -6015,10 +6080,6 @@ namespace ts { TupleElementTypes, // Element types in tuple element type list HeritageClauses, // Heritage clauses for a class or interface declaration. ImportOrExportSpecifiers, // Named import clause's import specifier list - JSDocFunctionParameters, - JSDocTypeArguments, - JSDocRecordMembers, - JSDocTupleTypes, Count // Number of parsing contexts } @@ -6029,24 +6090,6 @@ namespace ts { } export namespace JSDocParser { - export function isJSDocType() { - switch (token()) { - case SyntaxKind.AsteriskToken: - case SyntaxKind.QuestionToken: - case SyntaxKind.OpenParenToken: - case SyntaxKind.OpenBracketToken: - case SyntaxKind.ExclamationToken: - case SyntaxKind.OpenBraceToken: - case SyntaxKind.FunctionKeyword: - case SyntaxKind.DotDotDotToken: - case SyntaxKind.NewKeyword: - case SyntaxKind.ThisKeyword: - return true; - } - - return tokenIsIdentifierOrKeyword(token()); - } - export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS); @@ -6065,308 +6108,13 @@ namespace ts { const result = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); parseExpected(SyntaxKind.OpenBraceToken); - result.type = parseJSDocTopLevelType(); + result.type = doInsideOfContext(NodeFlags.JSDoc, parseType); parseExpected(SyntaxKind.CloseBraceToken); fixupParentReferences(result); return finishNode(result); } - function parseJSDocTopLevelType(): JSDocType { - let type = parseJSDocType(); - if (token() === SyntaxKind.BarToken) { - const unionType = createNode(SyntaxKind.JSDocUnionType, type.pos); - unionType.types = parseJSDocTypeList(type); - type = finishNode(unionType); - } - - if (token() === SyntaxKind.EqualsToken) { - const optionalType = createNode(SyntaxKind.JSDocOptionalType, type.pos); - nextToken(); - optionalType.type = type; - type = finishNode(optionalType); - } - - return type; - } - - function parseJSDocType(): JSDocType { - let type = parseBasicTypeExpression(); - - while (true) { - if (token() === SyntaxKind.OpenBracketToken) { - const arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); - arrayType.elementType = type; - - nextToken(); - parseExpected(SyntaxKind.CloseBracketToken); - - type = finishNode(arrayType); - } - else if (token() === SyntaxKind.QuestionToken) { - const nullableType = createNode(SyntaxKind.JSDocNullableType, type.pos); - nullableType.type = type; - - nextToken(); - type = finishNode(nullableType); - } - else if (token() === SyntaxKind.ExclamationToken) { - const nonNullableType = createNode(SyntaxKind.JSDocNonNullableType, type.pos); - nonNullableType.type = type; - - nextToken(); - type = finishNode(nonNullableType); - } - else { - break; - } - } - - return type; - } - - function parseBasicTypeExpression(): JSDocType { - switch (token()) { - case SyntaxKind.AsteriskToken: - return parseJSDocAllType(); - case SyntaxKind.QuestionToken: - return parseJSDocUnknownOrNullableType(); - case SyntaxKind.OpenParenToken: - return parseJSDocUnionType(); - case SyntaxKind.OpenBracketToken: - return parseJSDocTupleType(); - case SyntaxKind.ExclamationToken: - return parseJSDocNonNullableType(); - case SyntaxKind.OpenBraceToken: - return parseJSDocRecordType(); - case SyntaxKind.FunctionKeyword: - if (lookAhead(nextTokenIsOpenParen)) { - return parseJSDocFunctionType(); - } - break; - case SyntaxKind.DotDotDotToken: - return parseJSDocVariadicType(); - case SyntaxKind.NewKeyword: - return parseJSDocConstructorType(); - case SyntaxKind.ThisKeyword: - return parseJSDocThisType(); - case SyntaxKind.AnyKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.VoidKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.UndefinedKeyword: - case SyntaxKind.NeverKeyword: - return parseTokenNode(); - case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.TrueKeyword: - case SyntaxKind.FalseKeyword: - return parseJSDocLiteralType(); - } - - return parseJSDocTypeReference(); - } - - function parseJSDocThisType(): JSDocThisType { - const result = createNode(SyntaxKind.JSDocThisType); - nextToken(); - parseExpected(SyntaxKind.ColonToken); - result.type = parseJSDocType(); - return finishNode(result); - } - - function parseJSDocConstructorType(): JSDocConstructorType { - const result = createNode(SyntaxKind.JSDocConstructorType); - nextToken(); - parseExpected(SyntaxKind.ColonToken); - result.type = parseJSDocType(); - return finishNode(result); - } - - function parseJSDocVariadicType(): JSDocVariadicType { - const result = createNode(SyntaxKind.JSDocVariadicType); - nextToken(); - result.type = parseJSDocType(); - return finishNode(result); - } - - function parseJSDocFunctionType(): JSDocFunctionType { - const result = createNode(SyntaxKind.JSDocFunctionType); - nextToken(); - - parseExpected(SyntaxKind.OpenParenToken); - result.parameters = parseDelimitedList(ParsingContext.JSDocFunctionParameters, parseJSDocParameter); - checkForTrailingComma(result.parameters); - parseExpected(SyntaxKind.CloseParenToken); - - if (token() === SyntaxKind.ColonToken) { - nextToken(); - result.type = parseJSDocType(); - } - - return finishNode(result); - } - - function parseJSDocParameter(): ParameterDeclaration { - const parameter = createNode(SyntaxKind.Parameter); - parameter.type = parseJSDocType(); - if (parseOptional(SyntaxKind.EqualsToken)) { - // TODO(rbuckton): Can this be changed to SyntaxKind.QuestionToken? - parameter.questionToken = createNode(SyntaxKind.EqualsToken); - } - return finishNode(parameter); - } - - function parseJSDocTypeReference(): JSDocTypeReference { - const result = createNode(SyntaxKind.JSDocTypeReference); - result.name = parseSimplePropertyName(); - - if (token() === SyntaxKind.LessThanToken) { - result.typeArguments = parseTypeArguments(); - } - else { - while (parseOptional(SyntaxKind.DotToken)) { - if (token() === SyntaxKind.LessThanToken) { - result.typeArguments = parseTypeArguments(); - break; - } - else { - result.name = parseQualifiedName(result.name); - } - } - } - - - return finishNode(result); - } - - function parseTypeArguments() { - // Move past the < - nextToken(); - const typeArguments = parseDelimitedList(ParsingContext.JSDocTypeArguments, parseJSDocType); - checkForTrailingComma(typeArguments); - checkForEmptyTypeArgumentList(typeArguments); - parseExpected(SyntaxKind.GreaterThanToken); - - return typeArguments; - } - - function checkForEmptyTypeArgumentList(typeArguments: NodeArray) { - if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) { - const start = typeArguments.pos - "<".length; - const end = skipTrivia(sourceText, typeArguments.end) + ">".length; - return parseErrorAtPosition(start, end - start, Diagnostics.Type_argument_list_cannot_be_empty); - } - } - - function parseQualifiedName(left: EntityName): QualifiedName { - const result = createNode(SyntaxKind.QualifiedName, left.pos); - result.left = left; - result.right = parseIdentifierName(); - - return finishNode(result); - } - - function parseJSDocRecordType(): JSDocRecordType { - const result = createNode(SyntaxKind.JSDocRecordType); - result.literal = parseTypeLiteral(); - return finishNode(result); - } - - function parseJSDocNonNullableType(): JSDocNonNullableType { - const result = createNode(SyntaxKind.JSDocNonNullableType); - nextToken(); - result.type = parseJSDocType(); - return finishNode(result); - } - - function parseJSDocTupleType(): JSDocTupleType { - const result = createNode(SyntaxKind.JSDocTupleType); - nextToken(); - result.types = parseDelimitedList(ParsingContext.JSDocTupleTypes, parseJSDocType); - checkForTrailingComma(result.types); - parseExpected(SyntaxKind.CloseBracketToken); - - return finishNode(result); - } - - function checkForTrailingComma(list: NodeArray) { - if (parseDiagnostics.length === 0 && list.hasTrailingComma) { - const start = list.end - ",".length; - parseErrorAtPosition(start, ",".length, Diagnostics.Trailing_comma_not_allowed); - } - } - - function parseJSDocUnionType(): JSDocUnionType { - const result = createNode(SyntaxKind.JSDocUnionType); - nextToken(); - result.types = parseJSDocTypeList(parseJSDocType()); - - parseExpected(SyntaxKind.CloseParenToken); - - return finishNode(result); - } - - function parseJSDocTypeList(firstType: JSDocType) { - Debug.assert(!!firstType); - - const types = createNodeArray([firstType], firstType.pos); - - while (parseOptional(SyntaxKind.BarToken)) { - types.push(parseJSDocType()); - } - - types.end = scanner.getStartPos(); - return types; - } - - function parseJSDocAllType(): JSDocAllType { - const result = createNode(SyntaxKind.JSDocAllType); - nextToken(); - return finishNode(result); - } - - function parseJSDocLiteralType(): JSDocLiteralType { - const result = createNode(SyntaxKind.JSDocLiteralType); - result.literal = parseLiteralTypeNode(); - return finishNode(result); - } - - function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { - const pos = scanner.getStartPos(); - // skip the ? - nextToken(); - - // Need to lookahead to decide if this is a nullable or unknown type. - - // Here are cases where we'll pick the unknown type: - // - // Foo(?, - // { a: ? } - // Foo(?) - // Foo - // Foo(?= - // (?| - if (token() === SyntaxKind.CommaToken || - token() === SyntaxKind.CloseBraceToken || - token() === SyntaxKind.CloseParenToken || - token() === SyntaxKind.GreaterThanToken || - token() === SyntaxKind.EqualsToken || - token() === SyntaxKind.BarToken) { - - const result = createNode(SyntaxKind.JSDocUnknownType, pos); - return finishNode(result); - } - else { - const result = createNode(SyntaxKind.JSDocNullableType, pos); - result.type = parseJSDocType(); - return finishNode(result); - } - } - export function parseIsolatedJSDocComment(content: string, start: number, length: number) { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; @@ -6820,14 +6568,8 @@ namespace ts { skipWhitespace(); if (typeExpression) { - if (typeExpression.type.kind === SyntaxKind.JSDocTypeReference) { - const jsDocTypeReference = typeExpression.type; - if (jsDocTypeReference.name.kind === SyntaxKind.Identifier) { - const name = jsDocTypeReference.name; - if (name.text === "Object" || name.text === "object") { - typedefTag.jsDocTypeLiteral = scanChildTags(); - } - } + if (isObjectTypeReference(typeExpression.type)) { + typedefTag.jsDocTypeLiteral = scanChildTags(); } if (!typedefTag.jsDocTypeLiteral) { typedefTag.jsDocTypeLiteral = typeExpression.type; @@ -6839,6 +6581,18 @@ namespace ts { return finishNode(typedefTag); + function isObjectTypeReference(node: TypeNode) { + if (node.kind === SyntaxKind.ObjectKeyword) { + return true; + } + if (node.kind === SyntaxKind.TypeReference) { + const jsDocTypeReference = node; + if (jsDocTypeReference.typeName.kind === SyntaxKind.Identifier) { + return (jsDocTypeReference.typeName as Identifier).text === "Object"; + } + } + } + function scanChildTags(): JSDocTypeLiteral { const jsDocTypeLiteral = createNode(SyntaxKind.JSDocTypeLiteral, scanner.getStartPos()); let resumePos = scanner.getStartPos(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c9309a7d844..b2fb24fa0e4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -347,14 +347,8 @@ namespace ts { JSDocAllType, // The ? type JSDocUnknownType, - JSDocArrayType, - JSDocUnionType, - JSDocTupleType, JSDocNullableType, JSDocNonNullableType, - JSDocRecordType, - JSDocRecordMember, - JSDocTypeReference, JSDocOptionalType, JSDocFunctionType, JSDocVariadicType, @@ -371,7 +365,6 @@ namespace ts { JSDocTypedefTag, JSDocPropertyTag, JSDocTypeLiteral, - JSDocLiteralType, // Synthesized list SyntaxList, @@ -413,9 +406,9 @@ namespace ts { LastBinaryOperator = CaretEqualsToken, FirstNode = QualifiedName, FirstJSDocNode = JSDocTypeExpression, - LastJSDocNode = JSDocLiteralType, + LastJSDocNode = JSDocTypeLiteral, FirstJSDocTagNode = JSDocTag, - LastJSDocTagNode = JSDocLiteralType + LastJSDocTagNode = JSDocTypeLiteral } export const enum NodeFlags { @@ -450,6 +443,7 @@ namespace ts { // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. /* @internal */ PossiblyContainsDynamicImport = 1 << 19, + JSDoc = 1 << 20, // If node was parsed inside jsdoc BlockScoped = Let | Const, @@ -584,6 +578,7 @@ namespace ts { /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics. + /*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id. } // Transient identifier node (marked by id === -1) @@ -603,6 +598,7 @@ namespace ts { kind: SyntaxKind.QualifiedName; left: EntityName; right: Identifier; + /*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id1.Id2. } export type EntityName = Identifier | QualifiedName; @@ -694,7 +690,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface TSPropertySignature extends TypeElement { + export interface PropertySignature extends TypeElement { kind: SyntaxKind.PropertySignature; name: PropertyName; // Declared property name questionToken?: QuestionToken; // Present on optional property @@ -702,16 +698,6 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface JSDocPropertySignature extends TypeElement { - kind: SyntaxKind.JSDocRecordMember; - name: PropertyName; // Declared property name - questionToken?: QuestionToken; // Present on optional property - type?: TypeNode; // Optional type annotation - initializer?: Expression; // Optional initializer - } - - export type PropertySignature = TSPropertySignature | JSDocPropertySignature; - export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error @@ -921,7 +907,7 @@ namespace ts { kind: SyntaxKind.ConstructorType; } - export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference; + export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments; export interface TypeReferenceNode extends TypeNode { kind: SyntaxKind.TypeReference; @@ -2042,7 +2028,7 @@ namespace ts { // represents a top level: { type } expression in a JSDoc comment. export interface JSDocTypeExpression extends Node { kind: SyntaxKind.JSDocTypeExpression; - type: JSDocType; + type: TypeNode; } export interface JSDocType extends TypeNode { @@ -2057,81 +2043,42 @@ namespace ts { kind: SyntaxKind.JSDocUnknownType; } - export interface JSDocArrayType extends JSDocType { - kind: SyntaxKind.JSDocArrayType; - elementType: JSDocType; - } - - export interface JSDocUnionType extends JSDocType { - kind: SyntaxKind.JSDocUnionType; - types: NodeArray; - } - - export interface JSDocTupleType extends JSDocType { - kind: SyntaxKind.JSDocTupleType; - types: NodeArray; - } - export interface JSDocNonNullableType extends JSDocType { kind: SyntaxKind.JSDocNonNullableType; - type: JSDocType; + type: TypeNode; } export interface JSDocNullableType extends JSDocType { kind: SyntaxKind.JSDocNullableType; - type: JSDocType; - } - - export interface JSDocRecordType extends JSDocType { - kind: SyntaxKind.JSDocRecordType; - literal: TypeLiteralNode; - } - - export interface JSDocTypeReference extends JSDocType { - kind: SyntaxKind.JSDocTypeReference; - name: EntityName; - typeArguments: NodeArray; + type: TypeNode; } export interface JSDocOptionalType extends JSDocType { kind: SyntaxKind.JSDocOptionalType; - type: JSDocType; + type: TypeNode; } export interface JSDocFunctionType extends JSDocType, SignatureDeclaration { kind: SyntaxKind.JSDocFunctionType; - parameters: NodeArray; - type: JSDocType; } export interface JSDocVariadicType extends JSDocType { kind: SyntaxKind.JSDocVariadicType; - type: JSDocType; + type: TypeNode; } export interface JSDocConstructorType extends JSDocType { kind: SyntaxKind.JSDocConstructorType; - type: JSDocType; + type: TypeNode; } export interface JSDocThisType extends JSDocType { kind: SyntaxKind.JSDocThisType; - type: JSDocType; - } - - export interface JSDocLiteralType extends JSDocType { - kind: SyntaxKind.JSDocLiteralType; - literal: LiteralTypeNode; + type: TypeNode; } export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; - export interface JSDocRecordMember extends JSDocPropertySignature { - kind: SyntaxKind.JSDocRecordMember; - name: Identifier | StringLiteral | NumericLiteral; - type?: JSDocType; - } - export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; tags: NodeArray | undefined; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c8751f497a6..f7356f425fe 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1082,7 +1082,6 @@ namespace ts { export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { switch (node.kind) { case SyntaxKind.TypeReference: - case SyntaxKind.JSDocTypeReference: return (node).typeName; case SyntaxKind.ExpressionWithTypeArguments: @@ -1582,7 +1581,7 @@ namespace ts { return find(typeParameters, p => p.name.text === name); } - export function getJSDocType(node: Node): JSDocType { + export function getJSDocType(node: Node): TypeNode { let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag; if (!tag && node.kind === SyntaxKind.Parameter) { const paramTags = getJSDocParameterTags(node as ParameterDeclaration); @@ -1606,7 +1605,7 @@ namespace ts { return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag; } - export function getJSDocReturnType(node: Node): JSDocType { + export function getJSDocReturnType(node: Node): TypeNode { const returnTag = getJSDocReturnTag(node); return returnTag && returnTag.typeExpression && returnTag.typeExpression.type; } @@ -3298,6 +3297,10 @@ namespace ts { return false; } + export function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode { + return node.kind === SyntaxKind.TypeReference && !!findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression); + } + /** * Formats an enum value as a string for debugging and debug assertions. */ @@ -4664,18 +4667,6 @@ namespace ts { return node.kind === SyntaxKind.JSDocUnknownType; } - export function isJSDocArrayType(node: Node): node is JSDocArrayType { - return node.kind === SyntaxKind.JSDocArrayType; - } - - export function isJSDocUnionType(node: Node): node is JSDocUnionType { - return node.kind === SyntaxKind.JSDocUnionType; - } - - export function isJSDocTupleType(node: Node): node is JSDocTupleType { - return node.kind === SyntaxKind.JSDocTupleType; - } - export function isJSDocNullableType(node: Node): node is JSDocNullableType { return node.kind === SyntaxKind.JSDocNullableType; } @@ -4684,18 +4675,6 @@ namespace ts { return node.kind === SyntaxKind.JSDocNonNullableType; } - export function isJSDocRecordType(node: Node): node is JSDocRecordType { - return node.kind === SyntaxKind.JSDocRecordType; - } - - export function isJSDocRecordMember(node: Node): node is JSDocRecordMember { - return node.kind === SyntaxKind.JSDocRecordMember; - } - - export function isJSDocTypeReference(node: Node): node is JSDocTypeReference { - return node.kind === SyntaxKind.JSDocTypeReference; - } - export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { return node.kind === SyntaxKind.JSDocOptionalType; } @@ -4751,10 +4730,6 @@ namespace ts { export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { return node.kind === SyntaxKind.JSDocTypeLiteral; } - - export function isJSDocLiteralType(node: Node): node is JSDocLiteralType { - return node.kind === SyntaxKind.JSDocLiteralType; - } } // Node tests diff --git a/src/harness/unittests/jsDocParsing.ts b/src/harness/unittests/jsDocParsing.ts index 309e49bd6b8..032c4e848b5 100644 --- a/src/harness/unittests/jsDocParsing.ts +++ b/src/harness/unittests/jsDocParsing.ts @@ -62,6 +62,12 @@ namespace ts { parsesCorrectly("tupleType1", "{[number]}"); parsesCorrectly("tupleType2", "{[number,string]}"); parsesCorrectly("tupleType3", "{[number,string,boolean]}"); + parsesCorrectly("tupleTypeWithTrailingComma", "{[number,]}"); + parsesCorrectly("typeOfType", "{typeof M}"); + parsesCorrectly("tsConstructoType", "{new () => string}"); + parsesCorrectly("tsFunctionType", "{() => string}"); + parsesCorrectly("typeArgumentsNotFollowingDot", "{a<>}"); + parsesCorrectly("functionTypeWithTrailingComma", "{function(a,)}"); }); describe("parsesIncorrectly", () => { @@ -69,21 +75,13 @@ namespace ts { parsesIncorrectly("unionTypeWithTrailingBar", "{(a|)}"); parsesIncorrectly("unionTypeWithoutTypes", "{()}"); parsesIncorrectly("nullableTypeWithoutType", "{!}"); - parsesIncorrectly("functionTypeWithTrailingComma", "{function(a,)}"); parsesIncorrectly("thisWithoutType", "{this:}"); parsesIncorrectly("newWithoutType", "{new:}"); parsesIncorrectly("variadicWithoutType", "{...}"); parsesIncorrectly("optionalWithoutType", "{=}"); parsesIncorrectly("allWithType", "{*foo}"); - parsesIncorrectly("typeArgumentsNotFollowingDot", "{a<>}"); - parsesIncorrectly("emptyTypeArguments", "{a.<>}"); - parsesIncorrectly("typeArgumentsWithTrailingComma", "{a.}"); - parsesIncorrectly("tsFunctionType", "{() => string}"); - parsesIncorrectly("tsConstructoType", "{new () => string}"); - parsesIncorrectly("typeOfType", "{typeof M}"); parsesIncorrectly("namedParameter", "{function(a: number)}"); parsesIncorrectly("tupleTypeWithComma", "{[,]}"); - parsesIncorrectly("tupleTypeWithTrailingComma", "{[number,]}"); parsesIncorrectly("tupleTypeWithLeadingComma", "{[,number]}"); }); }); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 7fcfffc3ee2..0e92884d502 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -176,7 +176,6 @@ namespace ts { switch (node.parent.kind) { case SyntaxKind.TypeReference: - case SyntaxKind.JSDocTypeReference: return true; case SyntaxKind.ExpressionWithTypeArguments: return !isExpressionWithTypeArgumentsInClassExtendsClause(node.parent); From 91633cde5f6b06d7e55a3d7d428efac4f2aa48a7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 13 Jul 2017 11:33:12 -0700 Subject: [PATCH 03/22] Test JSDoc parsing using TS parser --- .../conformance/jsdoc/checkJsdocTypeTag1.ts | 4 +-- .../conformance/jsdoc/jsdocFunctionType.ts | 35 +++++++++++++++++++ .../conformance/jsdoc/jsdocInTypescript.ts | 23 ++++++++++++ .../conformance/jsdoc/jsdocInTypescript2.ts | 2 ++ .../conformance/jsdoc/jsdocTemplateTag.ts | 5 +-- .../jsdoc/jsdocTypesInTypeAnnotations.ts | 22 ++++++++++++ tests/cases/conformance/jsdoc/syntaxErrors.ts | 24 +++++-------- tests/cases/fourslash/formatEmptyParamList.ts | 2 +- 8 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 tests/cases/conformance/jsdoc/jsdocFunctionType.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocInTypescript.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocInTypescript2.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypeTag1.ts b/tests/cases/conformance/jsdoc/checkJsdocTypeTag1.ts index 4dc7b934571..87e799e793c 100644 --- a/tests/cases/conformance/jsdoc/checkJsdocTypeTag1.ts +++ b/tests/cases/conformance/jsdoc/checkJsdocTypeTag1.ts @@ -23,7 +23,7 @@ x(1); /** @type {function} */ const y = (a) => a + 1; -x(1); +y(1); /** @type {function (number)} */ const x1 = (a) => a + 1; @@ -41,4 +41,4 @@ var props = {}; /** * @type {Object} */ -var props = {}; \ No newline at end of file +var props = {}; diff --git a/tests/cases/conformance/jsdoc/jsdocFunctionType.ts b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts new file mode 100644 index 00000000000..0be247a9494 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts @@ -0,0 +1,35 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @noImplicitAny: true + +// @Filename: functions.js + +/** + * @param {function(this: string, number): number} c is just passing on through + * @return {function(this: string, number): number} + */ +function id1(c) { + return c +} + +var x = id1(function (n) { return this.length + n }); + +/** + * @param {function(new: { length: number }, number): number} c is just passing on through + * @return {function(new: { length: number }, number): number} + */ +function id2(c) { + return c +} + +class C { + /** @param {number} n */ + constructor(n) { + this.length = n; + } +} + +var y = id2(C); +var z = new y(12); +z.length; diff --git a/tests/cases/conformance/jsdoc/jsdocInTypescript.ts b/tests/cases/conformance/jsdoc/jsdocInTypescript.ts new file mode 100644 index 00000000000..fbe8982f891 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocInTypescript.ts @@ -0,0 +1,23 @@ +// @strict: true + +// grammar error from checker +var ara: Array. = [1,2,3]; + +function f(x: ?number, y: Array.) { + return x ? x + y[1] : y[0]; +} +function hof(ctor: function(new: number, string)) { + return new ctor('hi'); +} +function hof2(f: function(this: number, string): string) { + return f(12, 'hullo'); +} +var whatevs: * = 1001; +var ques: ? = 'what'; +var g: function(number, number): number = (n,m) => n + m; +var variadic: ...boolean = [true, false, true]; +var most: !string = 'definite'; +var weird1: new:string = {}; +var weird2: this:string = {}; +var postfixdef: number! = 101; +var postfixopt: number? = undefined; diff --git a/tests/cases/conformance/jsdoc/jsdocInTypescript2.ts b/tests/cases/conformance/jsdoc/jsdocInTypescript2.ts new file mode 100644 index 00000000000..2df22f3e4ab --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocInTypescript2.ts @@ -0,0 +1,2 @@ +// parse error (blocks grammar errors from checker) +function parse1(n: number=) { } diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts b/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts index 42b21cf935b..79dc083a952 100644 --- a/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts +++ b/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts @@ -1,11 +1,12 @@ // @allowJs: true // @checkJs: true // @noEmit: true +// @Filename: forgot.js /** * @param {T} a * @template T */ -function f(a: T) { +function f(a) { return () => a } let n = f(1)() @@ -15,7 +16,7 @@ let n = f(1)() * @template T * @returns {function(): T} */ -function g(a: T) { +function g(a) { return () => a } let s = g('hi')() diff --git a/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts b/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts new file mode 100644 index 00000000000..b2e7d122199 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts @@ -0,0 +1,22 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @module: commonjs +// @filename: node.d.ts +// @noImplicitAny: true +declare function require(id: string): any; +declare var module: any, exports: any; + +// @filename: f.js +var F = function () { + this.x = 1; +}; + +function f(p: F) { p.x; } + +// @filename: normal.ts +class C { p: number } + +/** @param {C} p */ +function g(c) { return c.p } + diff --git a/tests/cases/conformance/jsdoc/syntaxErrors.ts b/tests/cases/conformance/jsdoc/syntaxErrors.ts index 4f9024810dd..847a99a5a12 100644 --- a/tests/cases/conformance/jsdoc/syntaxErrors.ts +++ b/tests/cases/conformance/jsdoc/syntaxErrors.ts @@ -2,19 +2,13 @@ // @allowJs: true // @noEmit: true -// @Filename: foo.js -/** - * @param {(x)=>void} x - * @param {typeof String} y - * @param {string & number} z - **/ -function foo(x, y, z) { } +// @Filename: dummyType.d.ts +declare class C { t: T } -// @Filename: skipped.js -// @ts-nocheck -/** - * @param {(x)=>void} x - * @param {typeof String} y - * @param {string & number} z - **/ -function bar(x, y, z) { } +// @Filename: badTypeArguments.js +/** @param {C.<>} x */ +/** @param {C.} y */ +function f(x, y) { + return x.t + y.t; +} +var x = f({ t: 1000 }, { t: 3000 }); diff --git a/tests/cases/fourslash/formatEmptyParamList.ts b/tests/cases/fourslash/formatEmptyParamList.ts index a5372010baa..1822506d486 100644 --- a/tests/cases/fourslash/formatEmptyParamList.ts +++ b/tests/cases/fourslash/formatEmptyParamList.ts @@ -2,4 +2,4 @@ ////function f( f: function){/*1*/ goTo.marker("1"); edit.insert("}"); -verify.currentLineContentIs("function f(f: function){ }") \ No newline at end of file +verify.currentLineContentIs("function f(f: function) { }") From 48d9012989b2bd4c9b8a73037d7058cdcb538bfc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 13 Jul 2017 11:34:56 -0700 Subject: [PATCH 04/22] Update baselines --- ...sCorrectly.typedefTagWithChildrenTags.json | 4 +- ...peExpressions.parsesCorrectly.allType.json | 3 +- ...xpressions.parsesCorrectly.arrayType1.json | 9 +- ...xpressions.parsesCorrectly.arrayType2.json | 12 ++- ...xpressions.parsesCorrectly.arrayType3.json | 13 ++- ...esCorrectly.callSignatureInRecordType.json | 46 +++++----- ...s.parsesCorrectly.functionReturnType1.json | 9 +- ...essions.parsesCorrectly.functionType1.json | 1 + ...essions.parsesCorrectly.functionType2.json | 9 +- ...rrectly.functionTypeWithTrailingComma.json | 31 +++++++ ...eExpressions.parsesCorrectly.keyword1.json | 6 +- ...eExpressions.parsesCorrectly.keyword2.json | 3 +- ...eExpressions.parsesCorrectly.keyword3.json | 3 +- ...ns.parsesCorrectly.methodInRecordType.json | 59 +++++++------ ...eExpressions.parsesCorrectly.newType1.json | 11 ++- ...sions.parsesCorrectly.nonNullableType.json | 4 +- ...ions.parsesCorrectly.nonNullableType2.json | 4 +- ...ressions.parsesCorrectly.nullableType.json | 4 +- ...essions.parsesCorrectly.nullableType2.json | 4 +- ...ions.parsesCorrectly.optionalNullable.json | 4 +- ...ressions.parsesCorrectly.optionalType.json | 4 +- ...pressions.parsesCorrectly.recordType1.json | 16 ++-- ...pressions.parsesCorrectly.recordType2.json | 36 ++++---- ...pressions.parsesCorrectly.recordType3.json | 49 ++++++----- ...pressions.parsesCorrectly.recordType4.json | 58 ++++++------- ...pressions.parsesCorrectly.recordType5.json | 67 ++++++++------- ...pressions.parsesCorrectly.recordType6.json | 73 ++++++++-------- ...pressions.parsesCorrectly.recordType7.json | 84 +++++++++--------- ...pressions.parsesCorrectly.recordType8.json | 38 ++++----- ...Expressions.parsesCorrectly.thisType1.json | 11 ++- ...sesCorrectly.topLevelNoParenUnionType.json | 9 +- ...esCorrectly.trailingCommaInRecordType.json | 38 ++++----- ...ions.parsesCorrectly.tsConstructoType.json | 17 ++++ ...ssions.parsesCorrectly.tsFunctionType.json | 17 ++++ ...xpressions.parsesCorrectly.tupleType0.json | 5 +- ...xpressions.parsesCorrectly.tupleType1.json | 8 +- ...xpressions.parsesCorrectly.tupleType2.json | 11 ++- ...xpressions.parsesCorrectly.tupleType3.json | 14 +-- ...sCorrectly.tupleTypeWithTrailingComma.json | 18 ++++ ...orrectly.typeArgumentsNotFollowingDot.json | 18 ++++ ...xpressions.parsesCorrectly.typeOfType.json | 13 +++ ...ssions.parsesCorrectly.typeReference1.json | 12 ++- ...ssions.parsesCorrectly.typeReference2.json | 15 ++-- ...ssions.parsesCorrectly.typeReference3.json | 8 +- ...Expressions.parsesCorrectly.unionType.json | 37 +++++--- ...pressions.parsesCorrectly.unknownType.json | 3 +- ...ressions.parsesCorrectly.variadicType.json | 4 +- .../baselines/reference/checkJsdocTypeTag1.js | 7 +- .../reference/checkJsdocTypeTag1.symbols | 4 +- .../reference/checkJsdocTypeTag1.types | 6 +- ...zerReferencingConstructorLocals.errors.txt | 16 ++-- ...initializerReferencingConstructorLocals.js | 2 - ...eferencingConstructorParameters.errors.txt | 4 +- ...ializerReferencingConstructorParameters.js | 1 - .../reference/invalidTypeOfTarget.errors.txt | 19 +++-- .../reference/invalidTypeOfTarget.js | 4 +- .../reference/jsdocFunctionType.symbols | 63 ++++++++++++++ .../reference/jsdocFunctionType.types | 70 +++++++++++++++ .../reference/jsdocInTypescript.errors.txt | 85 +++++++++++++++++++ .../baselines/reference/jsdocInTypescript.js | 46 ++++++++++ .../reference/jsdocInTypescript2.errors.txt | 9 ++ .../baselines/reference/jsdocInTypescript2.js | 10 +++ .../reference/jsdocTemplateTag.symbols | 30 +++---- .../reference/jsdocTemplateTag.types | 10 +-- .../jsdocTypesInTypeAnnotations.errors.txt | 29 +++++++ tests/baselines/reference/jsweird.symbols | 14 +++ tests/baselines/reference/jsweird.types | 16 ++++ ...vateInstanceMemberAccessibility.errors.txt | 9 +- .../privateInstanceMemberAccessibility.js | 1 - .../reference/syntaxErrors.errors.txt | 42 ++++----- .../thisTypeInFunctionsNegative.errors.txt | 21 +---- .../reference/thisTypeInFunctionsNegative.js | 6 +- 72 files changed, 970 insertions(+), 476 deletions(-) create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionTypeWithTrailingComma.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsFunctionType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleTypeWithTrailingComma.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeArgumentsNotFollowingDot.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeOfType.json create mode 100644 tests/baselines/reference/jsdocFunctionType.symbols create mode 100644 tests/baselines/reference/jsdocFunctionType.types create mode 100644 tests/baselines/reference/jsdocInTypescript.errors.txt create mode 100644 tests/baselines/reference/jsdocInTypescript.js create mode 100644 tests/baselines/reference/jsdocInTypescript2.errors.txt create mode 100644 tests/baselines/reference/jsdocInTypescript2.js create mode 100644 tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt create mode 100644 tests/baselines/reference/jsweird.symbols create mode 100644 tests/baselines/reference/jsweird.types diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json index 13826b63d9c..370e139b512 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -54,10 +54,10 @@ "pos": 34, "end": 42, "type": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 35, "end": 41, - "name": { + "typeName": { "kind": "Identifier", "pos": 35, "end": 41, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json index 68081a1b9e4..7fb632c7a35 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json @@ -1,5 +1,6 @@ { "kind": "JSDocAllType", "pos": 1, - "end": 2 + "end": 2, + "flags": "JSDoc" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json index cd9255d392c..b1e7fa13dc9 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json @@ -1,15 +1,18 @@ { - "kind": "JSDocArrayType", + "kind": "ArrayType", "pos": 1, "end": 4, + "flags": "JSDoc", "elementType": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 2, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 2, + "flags": "JSDoc", "text": "a" } } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json index 1fe6d184599..125c706510d 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json @@ -1,19 +1,23 @@ { - "kind": "JSDocArrayType", + "kind": "ArrayType", "pos": 1, "end": 6, + "flags": "JSDoc", "elementType": { - "kind": "JSDocArrayType", + "kind": "ArrayType", "pos": 1, "end": 4, + "flags": "JSDoc", "elementType": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 2, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 2, + "flags": "JSDoc", "text": "a" } } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json index 2fe27c67a1b..ca2b2e175cd 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json @@ -2,22 +2,27 @@ "kind": "JSDocOptionalType", "pos": 1, "end": 7, + "flags": "JSDoc", "type": { - "kind": "JSDocArrayType", + "kind": "ArrayType", "pos": 1, "end": 6, + "flags": "JSDoc", "elementType": { - "kind": "JSDocArrayType", + "kind": "ArrayType", "pos": 1, "end": 4, + "flags": "JSDoc", "elementType": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 2, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 2, + "flags": "JSDoc", "text": "a" } } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.callSignatureInRecordType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.callSignatureInRecordType.json index 244c568ae05..6c00c3a8912 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.callSignatureInRecordType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.callSignatureInRecordType.json @@ -1,30 +1,28 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 13, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 13, - "members": { - "0": { - "kind": "CallSignature", - "pos": 2, - "end": 12, - "parameters": { - "length": 0, - "pos": 3, - "end": 3 - }, - "type": { - "kind": "NumberKeyword", - "pos": 5, - "end": 12 - } - }, - "length": 1, + "flags": "JSDoc", + "members": { + "0": { + "kind": "CallSignature", "pos": 2, - "end": 12 - } + "end": 12, + "flags": "JSDoc", + "parameters": { + "length": 0, + "pos": 3, + "end": 3 + }, + "type": { + "kind": "NumberKeyword", + "pos": 5, + "end": 12, + "flags": "JSDoc" + } + }, + "length": 1, + "pos": 2, + "end": 12 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json index 209b9440a87..d33287fb251 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json @@ -2,25 +2,30 @@ "kind": "JSDocFunctionType", "pos": 1, "end": 26, + "flags": "JSDoc", "parameters": { "0": { "kind": "Parameter", "pos": 10, "end": 16, + "flags": "JSDoc", "type": { "kind": "StringKeyword", "pos": 10, - "end": 16 + "end": 16, + "flags": "JSDoc" } }, "1": { "kind": "Parameter", "pos": 17, "end": 25, + "flags": "JSDoc", "type": { "kind": "BooleanKeyword", "pos": 17, - "end": 25 + "end": 25, + "flags": "JSDoc" } }, "length": 2, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json index d3be94a76ff..c589fd75317 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json @@ -2,6 +2,7 @@ "kind": "JSDocFunctionType", "pos": 1, "end": 11, + "flags": "JSDoc", "parameters": { "length": 0, "pos": 10, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json index 209b9440a87..d33287fb251 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json @@ -2,25 +2,30 @@ "kind": "JSDocFunctionType", "pos": 1, "end": 26, + "flags": "JSDoc", "parameters": { "0": { "kind": "Parameter", "pos": 10, "end": 16, + "flags": "JSDoc", "type": { "kind": "StringKeyword", "pos": 10, - "end": 16 + "end": 16, + "flags": "JSDoc" } }, "1": { "kind": "Parameter", "pos": 17, "end": 25, + "flags": "JSDoc", "type": { "kind": "BooleanKeyword", "pos": 17, - "end": 25 + "end": 25, + "flags": "JSDoc" } }, "length": 2, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionTypeWithTrailingComma.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionTypeWithTrailingComma.json new file mode 100644 index 00000000000..a3d7fd40267 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionTypeWithTrailingComma.json @@ -0,0 +1,31 @@ +{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 13, + "flags": "JSDoc", + "parameters": { + "0": { + "kind": "Parameter", + "pos": 10, + "end": 11, + "flags": "JSDoc", + "type": { + "kind": "TypeReference", + "pos": 10, + "end": 11, + "flags": "JSDoc", + "typeName": { + "kind": "Identifier", + "pos": 10, + "end": 11, + "flags": "JSDoc", + "text": "a" + } + } + }, + "length": 1, + "pos": 10, + "end": 12, + "hasTrailingComma": true + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json index 80b1378b291..b37c372a30c 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json @@ -1,11 +1,13 @@ { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 4, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 4, + "flags": "JSDoc", "originalKeywordKind": "VarKeyword", "text": "var" } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json index 4148937b278..a733da557af 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json @@ -1,5 +1,6 @@ { "kind": "NullKeyword", "pos": 1, - "end": 5 + "end": 5, + "flags": "JSDoc" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json index c61912f9eb8..c991d6cecc4 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json @@ -1,5 +1,6 @@ { "kind": "UndefinedKeyword", "pos": 1, - "end": 10 + "end": 10, + "flags": "JSDoc" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.methodInRecordType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.methodInRecordType.json index fab9a581bd9..296a5b0cc31 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.methodInRecordType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.methodInRecordType.json @@ -1,36 +1,35 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 16, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 16, - "members": { - "0": { - "kind": "MethodSignature", - "pos": 2, - "end": 15, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "parameters": { - "length": 0, - "pos": 6, - "end": 6 - }, - "type": { - "kind": "NumberKeyword", - "pos": 8, - "end": 15 - } - }, - "length": 1, + "flags": "JSDoc", + "members": { + "0": { + "kind": "MethodSignature", "pos": 2, - "end": 15 - } + "end": 15, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "flags": "JSDoc", + "text": "foo" + }, + "parameters": { + "length": 0, + "pos": 6, + "end": 6 + }, + "type": { + "kind": "NumberKeyword", + "pos": 8, + "end": 15, + "flags": "JSDoc" + } + }, + "length": 1, + "pos": 2, + "end": 15 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json index 194037970c5..f5956cd2ddb 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json @@ -1,25 +1,30 @@ { "kind": "JSDocConstructorType", - "pos": 1, + "pos": 4, "end": 8, + "flags": "JSDoc", "type": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 5, "end": 8, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "FirstNode", "pos": 5, "end": 8, + "flags": "JSDoc", "left": { "kind": "Identifier", "pos": 5, "end": 6, + "flags": "JSDoc", "text": "a" }, "right": { "kind": "Identifier", "pos": 7, "end": 8, + "flags": "JSDoc", "text": "b" } } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json index e089754a0de..5096e2c5ae1 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json @@ -2,9 +2,11 @@ "kind": "JSDocNonNullableType", "pos": 1, "end": 8, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json index 377b19d0f70..75bed7d45b6 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json @@ -2,9 +2,11 @@ "kind": "JSDocNonNullableType", "pos": 1, "end": 8, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json index 9c4457fba12..3b57e9c760a 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json @@ -2,9 +2,11 @@ "kind": "JSDocNullableType", "pos": 1, "end": 8, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json index 03aea7be8c5..1f0adde5ee1 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json @@ -2,9 +2,11 @@ "kind": "JSDocNullableType", "pos": 1, "end": 8, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json index f4940c28475..069de4aa09d 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json @@ -2,9 +2,11 @@ "kind": "JSDocOptionalType", "pos": 1, "end": 3, + "flags": "JSDoc", "type": { "kind": "JSDocUnknownType", "pos": 1, - "end": 2 + "end": 2, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json index 6069107cc6e..9faa4db0744 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json @@ -2,9 +2,11 @@ "kind": "JSDocOptionalType", "pos": 1, "end": 8, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json index 12be4806629..eb669992ca2 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json @@ -1,15 +1,11 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 3, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 3, - "members": { - "length": 0, - "pos": 2, - "end": 2 - } + "flags": "JSDoc", + "members": { + "length": 0, + "pos": 2, + "end": 2 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json index 4bed6d0b918..274a1abd531 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json @@ -1,26 +1,24 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 6, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 6, - "members": { - "0": { - "kind": "PropertySignature", + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", + "pos": 2, + "end": 5, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 2, "end": 5, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "length": 1, - "pos": 2, - "end": 5 - } + "flags": "JSDoc", + "text": "foo" + } + }, + "length": 1, + "pos": 2, + "end": 5 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json index 565738a6ba9..6451edee68b 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json @@ -1,31 +1,30 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 14, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 14, - "members": { - "0": { - "kind": "PropertySignature", - "pos": 2, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } - }, - "length": 1, + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", "pos": 2, - "end": 13 - } + "end": 13, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "flags": "JSDoc", + "text": "foo" + }, + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13, + "flags": "JSDoc" + } + }, + "length": 1, + "pos": 2, + "end": 13 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json index 74bb20ab30b..2fb902cc7d3 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json @@ -1,37 +1,37 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 11, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 11, - "members": { - "0": { - "kind": "PropertySignature", + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", + "pos": 2, + "end": 6, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 2, - "end": 6, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "1": { - "kind": "PropertySignature", + "end": 5, + "flags": "JSDoc", + "text": "foo" + } + }, + "1": { + "kind": "PropertySignature", + "pos": 6, + "end": 10, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 6, "end": 10, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 10, - "text": "bar" - } - }, - "length": 2, - "pos": 2, - "end": 10 - } + "flags": "JSDoc", + "text": "bar" + } + }, + "length": 2, + "pos": 2, + "end": 10 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json index b57de3aea3c..083d498df5f 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json @@ -1,42 +1,43 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 19, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 19, - "members": { - "0": { - "kind": "PropertySignature", + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", + "pos": 2, + "end": 14, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 2, - "end": 14, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } + "end": 5, + "flags": "JSDoc", + "text": "foo" }, - "1": { - "kind": "PropertySignature", + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13, + "flags": "JSDoc" + } + }, + "1": { + "kind": "PropertySignature", + "pos": 14, + "end": 18, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 14, "end": 18, - "name": { - "kind": "Identifier", - "pos": 14, - "end": 18, - "text": "bar" - } - }, - "length": 2, - "pos": 2, - "end": 18 - } + "flags": "JSDoc", + "text": "bar" + } + }, + "length": 2, + "pos": 2, + "end": 18 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json index 6c980da4085..7c3e7898528 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json @@ -1,42 +1,43 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 19, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 19, - "members": { - "0": { - "kind": "PropertySignature", - "pos": 2, - "end": 6, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "1": { - "kind": "PropertySignature", - "pos": 6, - "end": 18, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 10, - "text": "bar" - }, - "type": { - "kind": "NumberKeyword", - "pos": 11, - "end": 18 - } - }, - "length": 2, + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", "pos": 2, - "end": 18 - } + "end": 6, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "flags": "JSDoc", + "text": "foo" + } + }, + "1": { + "kind": "PropertySignature", + "pos": 6, + "end": 18, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 6, + "end": 10, + "flags": "JSDoc", + "text": "bar" + }, + "type": { + "kind": "NumberKeyword", + "pos": 11, + "end": 18, + "flags": "JSDoc" + } + }, + "length": 2, + "pos": 2, + "end": 18 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json index fb9f8c055cb..484c8eab770 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json @@ -1,47 +1,49 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 27, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 27, - "members": { - "0": { - "kind": "PropertySignature", - "pos": 2, - "end": 14, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } - }, - "1": { - "kind": "PropertySignature", - "pos": 14, - "end": 26, - "name": { - "kind": "Identifier", - "pos": 14, - "end": 18, - "text": "bar" - }, - "type": { - "kind": "NumberKeyword", - "pos": 19, - "end": 26 - } - }, - "length": 2, + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", "pos": 2, - "end": 26 - } + "end": 14, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "flags": "JSDoc", + "text": "foo" + }, + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13, + "flags": "JSDoc" + } + }, + "1": { + "kind": "PropertySignature", + "pos": 14, + "end": 26, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 14, + "end": 18, + "flags": "JSDoc", + "text": "bar" + }, + "type": { + "kind": "NumberKeyword", + "pos": 19, + "end": 26, + "flags": "JSDoc" + } + }, + "length": 2, + "pos": 2, + "end": 26 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json index 748b593d235..661a02217aa 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json @@ -1,27 +1,25 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 11, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 11, - "members": { - "0": { - "kind": "PropertySignature", + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", + "pos": 2, + "end": 10, + "flags": "JSDoc", + "name": { + "kind": "Identifier", "pos": 2, "end": 10, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 10, - "originalKeywordKind": "FunctionKeyword", - "text": "function" - } - }, - "length": 1, - "pos": 2, - "end": 10 - } + "flags": "JSDoc", + "originalKeywordKind": "FunctionKeyword", + "text": "function" + } + }, + "length": 1, + "pos": 2, + "end": 10 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json index f0b8038b586..cb6cfba99fe 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json @@ -1,25 +1,30 @@ { "kind": "JSDocThisType", - "pos": 1, + "pos": 5, "end": 9, + "flags": "JSDoc", "type": { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 6, "end": 9, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "FirstNode", "pos": 6, "end": 9, + "flags": "JSDoc", "left": { "kind": "Identifier", "pos": 6, "end": 7, + "flags": "JSDoc", "text": "a" }, "right": { "kind": "Identifier", "pos": 8, "end": 9, + "flags": "JSDoc", "text": "b" } } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json index dd9ef74f8c6..3ca80d437b5 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json @@ -1,17 +1,20 @@ { - "kind": "JSDocUnionType", + "kind": "UnionType", "pos": 1, "end": 14, + "flags": "JSDoc", "types": { "0": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "flags": "JSDoc" }, "1": { "kind": "StringKeyword", "pos": 8, - "end": 14 + "end": 14, + "flags": "JSDoc" }, "length": 2, "pos": 1, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.trailingCommaInRecordType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.trailingCommaInRecordType.json index 1694cf9aa73..899fcc6a649 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.trailingCommaInRecordType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.trailingCommaInRecordType.json @@ -1,26 +1,24 @@ { - "kind": "JSDocRecordType", + "kind": "TypeLiteral", "pos": 1, "end": 5, - "literal": { - "kind": "TypeLiteral", - "pos": 1, - "end": 5, - "members": { - "0": { - "kind": "PropertySignature", - "pos": 2, - "end": 4, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 3, - "text": "a" - } - }, - "length": 1, + "flags": "JSDoc", + "members": { + "0": { + "kind": "PropertySignature", "pos": 2, - "end": 4 - } + "end": 4, + "flags": "JSDoc", + "name": { + "kind": "Identifier", + "pos": 2, + "end": 3, + "flags": "JSDoc", + "text": "a" + } + }, + "length": 1, + "pos": 2, + "end": 4 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json new file mode 100644 index 00000000000..1b124c78dac --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json @@ -0,0 +1,17 @@ +{ + "kind": "ConstructorType", + "pos": 1, + "end": 17, + "flags": "JSDoc", + "parameters": { + "length": 0, + "pos": 6, + "end": 6 + }, + "type": { + "kind": "StringKeyword", + "pos": 10, + "end": 17, + "flags": "JSDoc" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsFunctionType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsFunctionType.json new file mode 100644 index 00000000000..32dd097a8f9 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsFunctionType.json @@ -0,0 +1,17 @@ +{ + "kind": "FunctionType", + "pos": 1, + "end": 13, + "flags": "JSDoc", + "parameters": { + "length": 0, + "pos": 2, + "end": 2 + }, + "type": { + "kind": "StringKeyword", + "pos": 6, + "end": 13, + "flags": "JSDoc" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json index 2b5580f7622..979f7e1d783 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json @@ -1,8 +1,9 @@ { - "kind": "JSDocTupleType", + "kind": "TupleType", "pos": 1, "end": 3, - "types": { + "flags": "JSDoc", + "elementTypes": { "length": 0, "pos": 2, "end": 2 diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json index f741169be4b..9f913923b68 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json @@ -1,12 +1,14 @@ { - "kind": "JSDocTupleType", + "kind": "TupleType", "pos": 1, "end": 9, - "types": { + "flags": "JSDoc", + "elementTypes": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "flags": "JSDoc" }, "length": 1, "pos": 2, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json index 939eec1cb0c..9b87dc74995 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json @@ -1,17 +1,20 @@ { - "kind": "JSDocTupleType", + "kind": "TupleType", "pos": 1, "end": 16, - "types": { + "flags": "JSDoc", + "elementTypes": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "flags": "JSDoc" }, "1": { "kind": "StringKeyword", "pos": 9, - "end": 15 + "end": 15, + "flags": "JSDoc" }, "length": 2, "pos": 2, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json index 50b0a702a84..5877b92ae64 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json @@ -1,22 +1,26 @@ { - "kind": "JSDocTupleType", + "kind": "TupleType", "pos": 1, "end": 24, - "types": { + "flags": "JSDoc", + "elementTypes": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "flags": "JSDoc" }, "1": { "kind": "StringKeyword", "pos": 9, - "end": 15 + "end": 15, + "flags": "JSDoc" }, "2": { "kind": "BooleanKeyword", "pos": 16, - "end": 23 + "end": 23, + "flags": "JSDoc" }, "length": 3, "pos": 2, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleTypeWithTrailingComma.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleTypeWithTrailingComma.json new file mode 100644 index 00000000000..48438f90c68 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleTypeWithTrailingComma.json @@ -0,0 +1,18 @@ +{ + "kind": "TupleType", + "pos": 1, + "end": 10, + "flags": "JSDoc", + "elementTypes": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8, + "flags": "JSDoc" + }, + "length": 1, + "pos": 2, + "end": 9, + "hasTrailingComma": true + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeArgumentsNotFollowingDot.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeArgumentsNotFollowingDot.json new file mode 100644 index 00000000000..a7a7ffbdf50 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeArgumentsNotFollowingDot.json @@ -0,0 +1,18 @@ +{ + "kind": "TypeReference", + "pos": 1, + "end": 4, + "flags": "JSDoc", + "typeName": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "flags": "JSDoc", + "text": "a" + }, + "typeArguments": { + "length": 0, + "pos": 3, + "end": 3 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeOfType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeOfType.json new file mode 100644 index 00000000000..a889c3ef3a1 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeOfType.json @@ -0,0 +1,13 @@ +{ + "kind": "TypeQuery", + "pos": 1, + "end": 9, + "flags": "JSDoc", + "exprName": { + "kind": "Identifier", + "pos": 7, + "end": 9, + "flags": "JSDoc", + "text": "M" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json index 282bc8c8e64..62d6b12c8e5 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json @@ -1,18 +1,22 @@ { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 11, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 2, - "text": "a" + "flags": "JSDoc", + "text": "a", + "jsdocDot": true }, "typeArguments": { "0": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "flags": "JSDoc" }, "length": 1, "pos": 4, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json index 570db907956..4ea0a37ee41 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json @@ -1,23 +1,28 @@ { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 18, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "Identifier", "pos": 1, "end": 2, - "text": "a" + "flags": "JSDoc", + "text": "a", + "jsdocDot": true }, "typeArguments": { "0": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "flags": "JSDoc" }, "1": { "kind": "StringKeyword", "pos": 11, - "end": 17 + "end": 17, + "flags": "JSDoc" }, "length": 2, "pos": 4, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json index 683c17e582e..632c7ba87e9 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json @@ -1,21 +1,25 @@ { - "kind": "JSDocTypeReference", + "kind": "TypeReference", "pos": 1, "end": 11, - "name": { + "flags": "JSDoc", + "typeName": { "kind": "FirstNode", "pos": 1, "end": 11, + "flags": "JSDoc", "left": { "kind": "Identifier", "pos": 1, "end": 2, + "flags": "JSDoc", "text": "a" }, "right": { "kind": "Identifier", "pos": 3, "end": 11, + "flags": "JSDoc", "originalKeywordKind": "FunctionKeyword", "text": "function" } diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json index f9301d05cc5..a6e8ab18df2 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json @@ -1,20 +1,29 @@ { - "kind": "JSDocUnionType", + "kind": "ParenthesizedType", "pos": 1, "end": 16, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - }, - "1": { - "kind": "StringKeyword", - "pos": 9, - "end": 15 - }, - "length": 2, + "flags": "JSDoc", + "type": { + "kind": "UnionType", "pos": 2, - "end": 15 + "end": 15, + "flags": "JSDoc", + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8, + "flags": "JSDoc" + }, + "1": { + "kind": "StringKeyword", + "pos": 9, + "end": 15, + "flags": "JSDoc" + }, + "length": 2, + "pos": 2, + "end": 15 + } } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json index 0fb7af7ef23..3dff66b0347 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json @@ -1,5 +1,6 @@ { "kind": "JSDocUnknownType", "pos": 1, - "end": 2 + "end": 2, + "flags": "JSDoc" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json index 2cf6079533c..00b950750e9 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json @@ -2,9 +2,11 @@ "kind": "JSDocVariadicType", "pos": 1, "end": 10, + "flags": "JSDoc", "type": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "flags": "JSDoc" } } \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag1.js b/tests/baselines/reference/checkJsdocTypeTag1.js index 664a02c6047..0613a237d7b 100644 --- a/tests/baselines/reference/checkJsdocTypeTag1.js +++ b/tests/baselines/reference/checkJsdocTypeTag1.js @@ -20,7 +20,7 @@ x(1); /** @type {function} */ const y = (a) => a + 1; -x(1); +y(1); /** @type {function (number)} */ const x1 = (a) => a + 1; @@ -38,7 +38,8 @@ var props = {}; /** * @type {Object} */ -var props = {}; +var props = {}; + //// [0.js] // @ts-check @@ -57,7 +58,7 @@ var x = function (a) { return a + 1; }; x(1); /** @type {function} */ var y = function (a) { return a + 1; }; -x(1); +y(1); /** @type {function (number)} */ var x1 = function (a) { return a + 1; }; x1(0); diff --git a/tests/baselines/reference/checkJsdocTypeTag1.symbols b/tests/baselines/reference/checkJsdocTypeTag1.symbols index cd337f8b556..281b59d37a0 100644 --- a/tests/baselines/reference/checkJsdocTypeTag1.symbols +++ b/tests/baselines/reference/checkJsdocTypeTag1.symbols @@ -37,8 +37,8 @@ const y = (a) => a + 1; >a : Symbol(a, Decl(0.js, 20, 11)) >a : Symbol(a, Decl(0.js, 20, 11)) -x(1); ->x : Symbol(x, Decl(0.js, 16, 5)) +y(1); +>y : Symbol(y, Decl(0.js, 20, 5)) /** @type {function (number)} */ const x1 = (a) => a + 1; diff --git a/tests/baselines/reference/checkJsdocTypeTag1.types b/tests/baselines/reference/checkJsdocTypeTag1.types index 8e59a2cdb7c..a0c0c53cfeb 100644 --- a/tests/baselines/reference/checkJsdocTypeTag1.types +++ b/tests/baselines/reference/checkJsdocTypeTag1.types @@ -53,9 +53,9 @@ const y = (a) => a + 1; >a : any >1 : 1 -x(1); ->x(1) : any ->x : Function +y(1); +>y(1) : any +>y : Function >1 : 1 /** @type {function (number)} */ diff --git a/tests/baselines/reference/initializerReferencingConstructorLocals.errors.txt b/tests/baselines/reference/initializerReferencingConstructorLocals.errors.txt index a3909e481f6..146048ceb93 100644 --- a/tests/baselines/reference/initializerReferencingConstructorLocals.errors.txt +++ b/tests/baselines/reference/initializerReferencingConstructorLocals.errors.txt @@ -1,18 +1,16 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(4,9): error TS2304: Cannot find name 'z'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(5,15): error TS2304: Cannot find name 'z'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(6,14): error TS2339: Property 'z' does not exist on type 'C'. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(7,15): error TS1003: Identifier expected. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(7,20): error TS2339: Property 'z' does not exist on type 'C'. +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(7,15): error TS2304: Cannot find name 'this'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(9,9): error TS2304: Cannot find name 'z'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(14,9): error TS2304: Cannot find name 'z'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(15,15): error TS2304: Cannot find name 'z'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(16,14): error TS2339: Property 'z' does not exist on type 'D'. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(17,15): error TS1003: Identifier expected. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(17,20): error TS2339: Property 'z' does not exist on type 'D'. +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(17,15): error TS2304: Cannot find name 'this'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts(19,9): error TS2304: Cannot find name 'z'. -==== tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts (12 errors) ==== +==== tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorLocals.ts (10 errors) ==== // Initializer expressions for instance member variables are evaluated in the scope of the class constructor body but are not permitted to reference parameters or local variables of the constructor. class C { @@ -27,9 +25,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin !!! error TS2339: Property 'z' does not exist on type 'C'. d: typeof this.z; // error ~~~~ -!!! error TS1003: Identifier expected. - ~ -!!! error TS2339: Property 'z' does not exist on type 'C'. +!!! error TS2304: Cannot find name 'this'. constructor(x) { z = 1; ~ @@ -49,9 +45,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin !!! error TS2339: Property 'z' does not exist on type 'D'. d: typeof this.z; // error ~~~~ -!!! error TS1003: Identifier expected. - ~ -!!! error TS2339: Property 'z' does not exist on type 'D'. +!!! error TS2304: Cannot find name 'this'. constructor(x: T) { z = 1; ~ diff --git a/tests/baselines/reference/initializerReferencingConstructorLocals.js b/tests/baselines/reference/initializerReferencingConstructorLocals.js index a4922e954d7..2dd3fdd0745 100644 --- a/tests/baselines/reference/initializerReferencingConstructorLocals.js +++ b/tests/baselines/reference/initializerReferencingConstructorLocals.js @@ -27,7 +27,6 @@ var C = (function () { function C(x) { this.a = z; // error this.c = this.z; // error - this.d = this.z; // error z = 1; } return C; @@ -36,7 +35,6 @@ var D = (function () { function D(x) { this.a = z; // error this.c = this.z; // error - this.d = this.z; // error z = 1; } return D; diff --git a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt index eb6744d656b..0c92d8c52a6 100644 --- a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt +++ b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(5,15): error TS2304: Cannot find name 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(10,9): error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(11,15): error TS2304: Cannot find name 'x'. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(17,15): error TS1003: Identifier expected. +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(17,15): error TS2304: Cannot find name 'this'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(23,9): error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? @@ -33,7 +33,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin a = this.x; // ok b: typeof this.x; // error ~~~~ -!!! error TS1003: Identifier expected. +!!! error TS2304: Cannot find name 'this'. constructor(public x) { } } diff --git a/tests/baselines/reference/initializerReferencingConstructorParameters.js b/tests/baselines/reference/initializerReferencingConstructorParameters.js index 881913d5b5f..9326636fbd6 100644 --- a/tests/baselines/reference/initializerReferencingConstructorParameters.js +++ b/tests/baselines/reference/initializerReferencingConstructorParameters.js @@ -44,7 +44,6 @@ var E = (function () { function E(x) { this.x = x; this.a = this.x; // ok - this.b = this.x; // error } return E; }()); diff --git a/tests/baselines/reference/invalidTypeOfTarget.errors.txt b/tests/baselines/reference/invalidTypeOfTarget.errors.txt index 3c5f43c85d4..e658ab68c81 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.errors.txt +++ b/tests/baselines/reference/invalidTypeOfTarget.errors.txt @@ -4,12 +4,15 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(3,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(4,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(5,16): error TS1003: Identifier expected. -tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(6,16): error TS1003: Identifier expected. -tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(7,16): error TS1003: Identifier expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(6,16): error TS2304: Cannot find name 'null'. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(7,16): error TS2552: Cannot find name 'function'. Did you mean 'Function'? +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(7,25): error TS1005: '=' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(7,25): error TS2304: Cannot find name 'f'. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(7,29): error TS1005: ',' expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(8,16): error TS1003: Identifier expected. -==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (9 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (12 errors) ==== var x1: typeof {}; ~ !!! error TS1003: Identifier expected. @@ -29,10 +32,16 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts !!! error TS1003: Identifier expected. var x6: typeof null; ~~~~ -!!! error TS1003: Identifier expected. +!!! error TS2304: Cannot find name 'null'. var x7: typeof function f() { }; ~~~~~~~~ -!!! error TS1003: Identifier expected. +!!! error TS2552: Cannot find name 'function'. Did you mean 'Function'? + ~ +!!! error TS1005: '=' expected. + ~ +!!! error TS2304: Cannot find name 'f'. + ~ +!!! error TS1005: ',' expected. var x8: typeof /123/; ~ !!! error TS1003: Identifier expected. \ No newline at end of file diff --git a/tests/baselines/reference/invalidTypeOfTarget.js b/tests/baselines/reference/invalidTypeOfTarget.js index 9945af643e6..ebc5bb70875 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.js +++ b/tests/baselines/reference/invalidTypeOfTarget.js @@ -14,6 +14,6 @@ var x2 = function () { return ; }; var x3 = 1; var x4 = ''; var x5; -var x6 = null; -var x7 = function f() { }; +var x6; +var x7 = f(), _a = void 0; var x8 = /123/; diff --git a/tests/baselines/reference/jsdocFunctionType.symbols b/tests/baselines/reference/jsdocFunctionType.symbols new file mode 100644 index 00000000000..18592bf2cdc --- /dev/null +++ b/tests/baselines/reference/jsdocFunctionType.symbols @@ -0,0 +1,63 @@ +=== tests/cases/conformance/jsdoc/functions.js === +/** + * @param {function(this: string, number): number} c is just passing on through + * @return {function(this: string, number): number} + */ +function id1(c) { +>id1 : Symbol(id1, Decl(functions.js, 0, 0)) +>c : Symbol(c, Decl(functions.js, 4, 13)) + + return c +>c : Symbol(c, Decl(functions.js, 4, 13)) +} + +var x = id1(function (n) { return this.length + n }); +>x : Symbol(x, Decl(functions.js, 8, 3)) +>id1 : Symbol(id1, Decl(functions.js, 0, 0)) +>n : Symbol(n, Decl(functions.js, 8, 22)) +>this.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>this : Symbol(this, Decl(functions.js, 1, 20)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>n : Symbol(n, Decl(functions.js, 8, 22)) + +/** + * @param {function(new: { length: number }, number): number} c is just passing on through + * @return {function(new: { length: number }, number): number} + */ +function id2(c) { +>id2 : Symbol(id2, Decl(functions.js, 8, 53)) +>c : Symbol(c, Decl(functions.js, 14, 13)) + + return c +>c : Symbol(c, Decl(functions.js, 14, 13)) +} + +class C { +>C : Symbol(C, Decl(functions.js, 16, 1)) + + /** @param {number} n */ + constructor(n) { +>n : Symbol(n, Decl(functions.js, 20, 16)) + + this.length = n; +>this.length : Symbol(C.length, Decl(functions.js, 20, 20)) +>this : Symbol(C, Decl(functions.js, 16, 1)) +>length : Symbol(C.length, Decl(functions.js, 20, 20)) +>n : Symbol(n, Decl(functions.js, 20, 16)) + } +} + +var y = id2(C); +>y : Symbol(y, Decl(functions.js, 25, 3)) +>id2 : Symbol(id2, Decl(functions.js, 8, 53)) +>C : Symbol(C, Decl(functions.js, 16, 1)) + +var z = new y(12); +>z : Symbol(z, Decl(functions.js, 26, 3)) +>y : Symbol(y, Decl(functions.js, 25, 3)) + +z.length; +>z.length : Symbol(length, Decl(functions.js, 12, 27)) +>z : Symbol(z, Decl(functions.js, 26, 3)) +>length : Symbol(length, Decl(functions.js, 12, 27)) + diff --git a/tests/baselines/reference/jsdocFunctionType.types b/tests/baselines/reference/jsdocFunctionType.types new file mode 100644 index 00000000000..65f3f929a5c --- /dev/null +++ b/tests/baselines/reference/jsdocFunctionType.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/jsdoc/functions.js === +/** + * @param {function(this: string, number): number} c is just passing on through + * @return {function(this: string, number): number} + */ +function id1(c) { +>id1 : (c: (this: string, arg1: number) => number) => (this: string, arg1: number) => number +>c : (this: string, arg1: number) => number + + return c +>c : (this: string, arg1: number) => number +} + +var x = id1(function (n) { return this.length + n }); +>x : (this: string, arg1: number) => number +>id1(function (n) { return this.length + n }) : (this: string, arg1: number) => number +>id1 : (c: (this: string, arg1: number) => number) => (this: string, arg1: number) => number +>function (n) { return this.length + n } : (this: string, n: number) => number +>n : number +>this.length + n : number +>this.length : number +>this : string +>length : number +>n : number + +/** + * @param {function(new: { length: number }, number): number} c is just passing on through + * @return {function(new: { length: number }, number): number} + */ +function id2(c) { +>id2 : (c: new (arg1: number) => { length: number; }) => new (arg1: number) => { length: number; } +>c : new (arg1: number) => { length: number; } + + return c +>c : new (arg1: number) => { length: number; } +} + +class C { +>C : C + + /** @param {number} n */ + constructor(n) { +>n : number + + this.length = n; +>this.length = n : number +>this.length : number +>this : this +>length : number +>n : number + } +} + +var y = id2(C); +>y : new (arg1: number) => { length: number; } +>id2(C) : new (arg1: number) => { length: number; } +>id2 : (c: new (arg1: number) => { length: number; }) => new (arg1: number) => { length: number; } +>C : typeof C + +var z = new y(12); +>z : { length: number; } +>new y(12) : { length: number; } +>y : new (arg1: number) => { length: number; } +>12 : 12 + +z.length; +>z.length : number +>z : { length: number; } +>length : number + diff --git a/tests/baselines/reference/jsdocInTypescript.errors.txt b/tests/baselines/reference/jsdocInTypescript.errors.txt new file mode 100644 index 00000000000..3e5e0ca027f --- /dev/null +++ b/tests/baselines/reference/jsdocInTypescript.errors.txt @@ -0,0 +1,85 @@ +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(2,10): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,15): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,27): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,20): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,32): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,18): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,31): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(11,12): error TS2554: Expected 1 arguments, but got 2. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(13,14): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(14,11): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(15,8): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(16,15): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(17,11): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,5): error TS2322: Type '{}' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,16): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,5): error TS2322: Type '{}' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,17): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(20,17): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,5): error TS2322: Type 'undefined' is not assignable to type 'number | null'. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,17): error TS8020: JSDoc types can only used inside documentation comments. + + +==== tests/cases/conformance/jsdoc/jsdocInTypescript.ts (20 errors) ==== + // grammar error from checker + var ara: Array. = [1,2,3]; + ~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + + function f(x: ?number, y: Array.) { + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + ~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + return x ? x + y[1] : y[0]; + } + function hof(ctor: function(new: number, string)) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + ~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + return new ctor('hi'); + } + function hof2(f: function(this: number, string): string) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + ~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + return f(12, 'hullo'); + ~~~~~~~~~~~~~~ +!!! error TS2554: Expected 1 arguments, but got 2. + } + var whatevs: * = 1001; + ~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var ques: ? = 'what'; + ~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var g: function(number, number): number = (n,m) => n + m; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var variadic: ...boolean = [true, false, true]; + ~~~~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var most: !string = 'definite'; + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var weird1: new:string = {}; + ~~~~~~ +!!! error TS2322: Type '{}' is not assignable to type 'string'. + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var weird2: this:string = {}; + ~~~~~~ +!!! error TS2322: Type '{}' is not assignable to type 'string'. + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var postfixdef: number! = 101; + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + var postfixopt: number? = undefined; + ~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'number | null'. + ~~~~~~~ +!!! error TS8020: JSDoc types can only used inside documentation comments. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypescript.js b/tests/baselines/reference/jsdocInTypescript.js new file mode 100644 index 00000000000..665707e15d1 --- /dev/null +++ b/tests/baselines/reference/jsdocInTypescript.js @@ -0,0 +1,46 @@ +//// [jsdocInTypescript.ts] +// grammar error from checker +var ara: Array. = [1,2,3]; + +function f(x: ?number, y: Array.) { + return x ? x + y[1] : y[0]; +} +function hof(ctor: function(new: number, string)) { + return new ctor('hi'); +} +function hof2(f: function(this: number, string): string) { + return f(12, 'hullo'); +} +var whatevs: * = 1001; +var ques: ? = 'what'; +var g: function(number, number): number = (n,m) => n + m; +var variadic: ...boolean = [true, false, true]; +var most: !string = 'definite'; +var weird1: new:string = {}; +var weird2: this:string = {}; +var postfixdef: number! = 101; +var postfixopt: number? = undefined; + + +//// [jsdocInTypescript.js] +"use strict"; +// grammar error from checker +var ara = [1, 2, 3]; +function f(x, y) { + return x ? x + y[1] : y[0]; +} +function hof(ctor) { + return new ctor('hi'); +} +function hof2(f) { + return f(12, 'hullo'); +} +var whatevs = 1001; +var ques = 'what'; +var g = function (n, m) { return n + m; }; +var variadic = [true, false, true]; +var most = 'definite'; +var weird1 = {}; +var weird2 = {}; +var postfixdef = 101; +var postfixopt = undefined; diff --git a/tests/baselines/reference/jsdocInTypescript2.errors.txt b/tests/baselines/reference/jsdocInTypescript2.errors.txt new file mode 100644 index 00000000000..4616212c211 --- /dev/null +++ b/tests/baselines/reference/jsdocInTypescript2.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/jsdoc/jsdocInTypescript2.ts(2,27): error TS1109: Expression expected. + + +==== tests/cases/conformance/jsdoc/jsdocInTypescript2.ts (1 errors) ==== + // parse error (blocks grammar errors from checker) + function parse1(n: number=) { } + ~ +!!! error TS1109: Expression expected. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypescript2.js b/tests/baselines/reference/jsdocInTypescript2.js new file mode 100644 index 00000000000..0624d5af1d8 --- /dev/null +++ b/tests/baselines/reference/jsdocInTypescript2.js @@ -0,0 +1,10 @@ +//// [jsdocInTypescript2.ts] +// parse error (blocks grammar errors from checker) +function parse1(n: number=) { } + + +//// [jsdocInTypescript2.js] +// parse error (blocks grammar errors from checker) +function parse1(n) { + if (n === void 0) { n = ; } +} diff --git a/tests/baselines/reference/jsdocTemplateTag.symbols b/tests/baselines/reference/jsdocTemplateTag.symbols index 699e93339ed..98eee628178 100644 --- a/tests/baselines/reference/jsdocTemplateTag.symbols +++ b/tests/baselines/reference/jsdocTemplateTag.symbols @@ -1,36 +1,32 @@ -=== tests/cases/conformance/jsdoc/jsdocTemplateTag.ts === +=== tests/cases/conformance/jsdoc/forgot.js === /** * @param {T} a * @template T */ -function f(a: T) { ->f : Symbol(f, Decl(jsdocTemplateTag.ts, 0, 0)) ->T : Symbol(T, Decl(jsdocTemplateTag.ts, 4, 11)) ->a : Symbol(a, Decl(jsdocTemplateTag.ts, 4, 14)) ->T : Symbol(T, Decl(jsdocTemplateTag.ts, 4, 11)) +function f(a) { +>f : Symbol(f, Decl(forgot.js, 0, 0)) +>a : Symbol(a, Decl(forgot.js, 4, 11)) return () => a ->a : Symbol(a, Decl(jsdocTemplateTag.ts, 4, 14)) +>a : Symbol(a, Decl(forgot.js, 4, 11)) } let n = f(1)() ->n : Symbol(n, Decl(jsdocTemplateTag.ts, 7, 3)) ->f : Symbol(f, Decl(jsdocTemplateTag.ts, 0, 0)) +>n : Symbol(n, Decl(forgot.js, 7, 3)) +>f : Symbol(f, Decl(forgot.js, 0, 0)) /** * @param {T} a * @template T * @returns {function(): T} */ -function g(a: T) { ->g : Symbol(g, Decl(jsdocTemplateTag.ts, 7, 14)) ->T : Symbol(T, Decl(jsdocTemplateTag.ts, 14, 11)) ->a : Symbol(a, Decl(jsdocTemplateTag.ts, 14, 14)) ->T : Symbol(T, Decl(jsdocTemplateTag.ts, 14, 11)) +function g(a) { +>g : Symbol(g, Decl(forgot.js, 7, 14)) +>a : Symbol(a, Decl(forgot.js, 14, 11)) return () => a ->a : Symbol(a, Decl(jsdocTemplateTag.ts, 14, 14)) +>a : Symbol(a, Decl(forgot.js, 14, 11)) } let s = g('hi')() ->s : Symbol(s, Decl(jsdocTemplateTag.ts, 17, 3)) ->g : Symbol(g, Decl(jsdocTemplateTag.ts, 7, 14)) +>s : Symbol(s, Decl(forgot.js, 17, 3)) +>g : Symbol(g, Decl(forgot.js, 7, 14)) diff --git a/tests/baselines/reference/jsdocTemplateTag.types b/tests/baselines/reference/jsdocTemplateTag.types index 72b0529d97e..b1d8c46720d 100644 --- a/tests/baselines/reference/jsdocTemplateTag.types +++ b/tests/baselines/reference/jsdocTemplateTag.types @@ -1,13 +1,11 @@ -=== tests/cases/conformance/jsdoc/jsdocTemplateTag.ts === +=== tests/cases/conformance/jsdoc/forgot.js === /** * @param {T} a * @template T */ -function f(a: T) { +function f(a) { >f : (a: T) => () => T ->T : T >a : T ->T : T return () => a >() => a : () => T @@ -25,11 +23,9 @@ let n = f(1)() * @template T * @returns {function(): T} */ -function g(a: T) { +function g(a) { >g : (a: T) => () => T ->T : T >a : T ->T : T return () => a >() => a : () => T diff --git a/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt b/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt new file mode 100644 index 00000000000..72f74609078 --- /dev/null +++ b/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt @@ -0,0 +1,29 @@ +tests/cases/conformance/jsdoc/f.js(5,15): error TS2304: Cannot find name 'F'. +tests/cases/conformance/jsdoc/f.js(5,15): error TS8010: 'types' can only be used in a .ts file. +tests/cases/conformance/jsdoc/normal.ts(4,12): error TS7006: Parameter 'c' implicitly has an 'any' type. + + +==== tests/cases/conformance/jsdoc/node.d.ts (0 errors) ==== + declare function require(id: string): any; + declare var module: any, exports: any; + +==== tests/cases/conformance/jsdoc/f.js (2 errors) ==== + var F = function () { + this.x = 1; + }; + + function f(p: F) { p.x; } + ~ +!!! error TS2304: Cannot find name 'F'. + ~ +!!! error TS8010: 'types' can only be used in a .ts file. + +==== tests/cases/conformance/jsdoc/normal.ts (1 errors) ==== + class C { p: number } + + /** @param {C} p */ + function g(c) { return c.p } + ~ +!!! error TS7006: Parameter 'c' implicitly has an 'any' type. + + \ No newline at end of file diff --git a/tests/baselines/reference/jsweird.symbols b/tests/baselines/reference/jsweird.symbols new file mode 100644 index 00000000000..8bed15c4468 --- /dev/null +++ b/tests/baselines/reference/jsweird.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/jsdoc/crash.js === +/** + * @param {function(new:number, string)} c crashes with correct syntax too + * @return {number} + */ +function sub4(c) { +>sub4 : Symbol(sub4, Decl(crash.js, 0, 0)) +>c : Symbol(c, Decl(crash.js, 4, 14)) + + return new c('hi') +>c : Symbol(c, Decl(crash.js, 4, 14)) +} + + diff --git a/tests/baselines/reference/jsweird.types b/tests/baselines/reference/jsweird.types new file mode 100644 index 00000000000..f77bb369570 --- /dev/null +++ b/tests/baselines/reference/jsweird.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/jsdoc/crash.js === +/** + * @param {function(new:number, string)} c crashes with correct syntax too + * @return {number} + */ +function sub4(c) { +>sub4 : (c: new (arg1: string) => number) => number +>c : new (arg1: string) => number + + return new c('hi') +>new c('hi') : number +>c : new (arg1: string) => number +>'hi' : "hi" +} + + diff --git a/tests/baselines/reference/privateInstanceMemberAccessibility.errors.txt b/tests/baselines/reference/privateInstanceMemberAccessibility.errors.txt index adca4e30e10..ae7dac2f18c 100644 --- a/tests/baselines/reference/privateInstanceMemberAccessibility.errors.txt +++ b/tests/baselines/reference/privateInstanceMemberAccessibility.errors.txt @@ -2,12 +2,11 @@ tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAcces Property 'foo' is private in type 'Base' but not in type 'Derived'. tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(6,15): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(8,22): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. -tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(10,15): error TS1003: Identifier expected. -tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(10,21): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. +tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(10,15): error TS2304: Cannot find name 'super'. tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts(12,12): error TS1005: ';' expected. -==== tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts (6 errors) ==== +==== tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAccessibility.ts (5 errors) ==== class Base { private foo: string; } @@ -26,9 +25,7 @@ tests/cases/conformance/classes/members/accessibility/privateInstanceMemberAcces } z: typeof super.foo; // error ~~~~~ -!!! error TS1003: Identifier expected. - ~~~ -!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. +!!! error TS2304: Cannot find name 'super'. a: this.foo; // error ~ diff --git a/tests/baselines/reference/privateInstanceMemberAccessibility.js b/tests/baselines/reference/privateInstanceMemberAccessibility.js index 8448f142bbb..40b8c886cc0 100644 --- a/tests/baselines/reference/privateInstanceMemberAccessibility.js +++ b/tests/baselines/reference/privateInstanceMemberAccessibility.js @@ -34,7 +34,6 @@ var Derived = (function (_super) { function Derived() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.x = _super.prototype.foo; // error - _this.z = _super.prototype.foo; // error return _this; } Derived.prototype.y = function () { diff --git a/tests/baselines/reference/syntaxErrors.errors.txt b/tests/baselines/reference/syntaxErrors.errors.txt index 8e3005891a5..02ad52a15e5 100644 --- a/tests/baselines/reference/syntaxErrors.errors.txt +++ b/tests/baselines/reference/syntaxErrors.errors.txt @@ -1,31 +1,19 @@ -tests/cases/conformance/jsdoc/foo.js(2,15): error TS1005: '}' expected. -tests/cases/conformance/jsdoc/foo.js(3,19): error TS1005: '}' expected. -tests/cases/conformance/jsdoc/foo.js(4,18): error TS1003: Identifier expected. -tests/cases/conformance/jsdoc/foo.js(4,19): error TS1005: '}' expected. +tests/cases/conformance/jsdoc/badTypeArguments.js(1,15): error TS1099: Type argument list cannot be empty. +tests/cases/conformance/jsdoc/badTypeArguments.js(2,22): error TS1009: Trailing comma not allowed. -==== tests/cases/conformance/jsdoc/foo.js (4 errors) ==== - /** - * @param {(x)=>void} x - ~~ -!!! error TS1005: '}' expected. - * @param {typeof String} y - ~~~~~~ -!!! error TS1005: '}' expected. - * @param {string & number} z - -!!! error TS1003: Identifier expected. - ~ -!!! error TS1005: '}' expected. - **/ - function foo(x, y, z) { } +==== tests/cases/conformance/jsdoc/dummyType.d.ts (0 errors) ==== + declare class C { t: T } -==== tests/cases/conformance/jsdoc/skipped.js (0 errors) ==== - // @ts-nocheck - /** - * @param {(x)=>void} x - * @param {typeof String} y - * @param {string & number} z - **/ - function bar(x, y, z) { } +==== tests/cases/conformance/jsdoc/badTypeArguments.js (2 errors) ==== + /** @param {C.<>} x */ + ~~ +!!! error TS1099: Type argument list cannot be empty. + /** @param {C.} y */ + ~ +!!! error TS1009: Trailing comma not allowed. + function f(x, y) { + return x.t + y.t; + } + var x = f({ t: 1000 }, { t: 3000 }); \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index ad8978847f4..4f566c1a7ae 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -88,18 +88,13 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,24): e tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,28): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,32): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,42): error TS2693: 'number' only refers to a type, but is being used as a value here. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(175,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(175,29): error TS2304: Cannot find name 'm'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(175,32): error TS1005: ';' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(175,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (65 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (60 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -419,20 +414,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(175,35): e ~ !!! error TS1005: ',' expected. ~~~ -!!! error TS1138: Parameter declaration expected. - ~ -!!! error TS1005: ';' expected. - ~ -!!! error TS1128: Declaration or statement expected. - ~~~~~~ -!!! error TS2693: 'number' only refers to a type, but is being used as a value here. - ~ -!!! error TS1005: ';' expected. +!!! error TS1003: Identifier expected. // can't name parameters 'this' in a lambda. c.explicitProperty = (this, m) => m + this.n; - ~ -!!! error TS7027: Unreachable code detected. ~ !!! error TS2304: Cannot find name 'm'. ~~ diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index 6cf6f477827..4b0e18f9b94 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -350,10 +350,8 @@ function decorated(, C) { if ( === void 0) { = this; } return this.n; } -function initializer() { } -new C(); -number; -{ +function initializer() { + if ( === void 0) { = new C(); } return this.n; } // can't name parameters 'this' in a lambda. From ac478a97209c92d9f922dddd5cc605cbd4cfb449 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 13 Jul 2017 13:37:35 -0700 Subject: [PATCH 05/22] Add missing word in error message --- src/compiler/checker.ts | 4 +- src/compiler/diagnosticMessages.json | 2 +- .../reference/jsdocInTypescript.errors.txt | 64 +++++++++---------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd1fbcc379b..b5d1cf5bcc6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18461,7 +18461,7 @@ namespace ts { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDot && !isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { - grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_used_inside_documentation_comments); + grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } const type = getTypeFromTypeReference(node); if (type !== unknownType) { @@ -22060,7 +22060,7 @@ namespace ts { case SyntaxKind.JSDocAllType: case SyntaxKind.JSDocUnknownType: if (!isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { - grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_used_inside_documentation_comments); + grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } return; case SyntaxKind.JSDocTypeExpression: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cee632634a9..9881d32d775 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3475,7 +3475,7 @@ "category": "Message", "code": 8019 }, - "JSDoc types can only used inside documentation comments.": { + "JSDoc types can only be used inside documentation comments.": { "category": "Error", "code": 8020 }, diff --git a/tests/baselines/reference/jsdocInTypescript.errors.txt b/tests/baselines/reference/jsdocInTypescript.errors.txt index 3e5e0ca027f..d1d6f404e15 100644 --- a/tests/baselines/reference/jsdocInTypescript.errors.txt +++ b/tests/baselines/reference/jsdocInTypescript.errors.txt @@ -1,85 +1,85 @@ -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(2,10): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,15): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,27): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,20): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,32): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,18): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,31): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(2,10): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,15): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,27): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,20): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,32): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,18): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,31): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocInTypescript.ts(11,12): error TS2554: Expected 1 arguments, but got 2. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(13,14): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(14,11): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(15,8): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(16,15): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(17,11): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(13,14): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(14,11): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(15,8): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(16,15): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(17,11): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,5): error TS2322: Type '{}' is not assignable to type 'string'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,16): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,16): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,5): error TS2322: Type '{}' is not assignable to type 'string'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,17): error TS8020: JSDoc types can only used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(20,17): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,17): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(20,17): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,5): error TS2322: Type 'undefined' is not assignable to type 'number | null'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,17): error TS8020: JSDoc types can only used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,17): error TS8020: JSDoc types can only be used inside documentation comments. ==== tests/cases/conformance/jsdoc/jsdocInTypescript.ts (20 errors) ==== // grammar error from checker var ara: Array. = [1,2,3]; ~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. function f(x: ?number, y: Array.) { ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. ~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. return x ? x + y[1] : y[0]; } function hof(ctor: function(new: number, string)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. ~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. return new ctor('hi'); } function hof2(f: function(this: number, string): string) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. ~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. return f(12, 'hullo'); ~~~~~~~~~~~~~~ !!! error TS2554: Expected 1 arguments, but got 2. } var whatevs: * = 1001; ~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var ques: ? = 'what'; ~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var g: function(number, number): number = (n,m) => n + m; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var variadic: ...boolean = [true, false, true]; ~~~~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var most: !string = 'definite'; ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var weird1: new:string = {}; ~~~~~~ !!! error TS2322: Type '{}' is not assignable to type 'string'. ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var weird2: this:string = {}; ~~~~~~ !!! error TS2322: Type '{}' is not assignable to type 'string'. ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var postfixdef: number! = 101; ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. var postfixopt: number? = undefined; ~~~~~~~~~~ !!! error TS2322: Type 'undefined' is not assignable to type 'number | null'. ~~~~~~~ -!!! error TS8020: JSDoc types can only used inside documentation comments. +!!! error TS8020: JSDoc types can only be used inside documentation comments. \ No newline at end of file From 680bfbb70511932a29115855549bb9c801651fd6 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Jul 2017 13:46:04 -0700 Subject: [PATCH 06/22] Combine moduleHasNonRelativeName with isExternalModuleNameRelative (#16564) --- src/compiler/core.ts | 13 ++++++++++++- src/compiler/moduleNameResolver.ts | 12 ++++-------- src/server/lsHost.ts | 2 +- src/services/codefixes/importFixes.ts | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index a1880b46471..9f5872540f4 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1580,10 +1580,21 @@ namespace ts { return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1; } + /* @internal */ + export function pathIsRelative(path: string): boolean { + return /^\.\.?($|[\\/])/.test(path); + } + export function isExternalModuleNameRelative(moduleName: string): boolean { // TypeScript 1.0 spec (April 2014): 11.2.1 // An external module name is "relative" if the first term is "." or "..". - return /^\.\.?($|[\\/])/.test(moduleName); + // Update: We also consider a path like `C:\foo.ts` "relative" because we do not search for it in `node_modules` or treat it as an ambient module. + return pathIsRelative(moduleName) || isRootedDiskPath(moduleName); + } + + /** @deprecated Use `!isExternalModuleNameRelative(moduleName)` instead. */ + export function moduleHasNonRelativeName(moduleName: string): boolean { + return !isExternalModuleNameRelative(moduleName); } export function getEmitScriptTarget(compilerOptions: CompilerOptions) { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 2a32dc11f7b..59afd8daff0 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -54,10 +54,6 @@ namespace ts { }; } - export function moduleHasNonRelativeName(moduleName: string): boolean { - return !(isRootedDiskPath(moduleName) || isExternalModuleNameRelative(moduleName)); - } - interface ModuleResolutionState { host: ModuleResolutionHost; compilerOptions: CompilerOptions; @@ -318,7 +314,7 @@ namespace ts { } function getOrCreateCacheForModuleName(nonRelativeModuleName: string) { - if (!moduleHasNonRelativeName(nonRelativeModuleName)) { + if (isExternalModuleNameRelative(nonRelativeModuleName)) { return undefined; } let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName); @@ -535,7 +531,7 @@ namespace ts { function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - if (moduleHasNonRelativeName(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state); } else { @@ -711,7 +707,7 @@ namespace ts { return toSearchResult({ resolved, isExternalLibraryImport: false }); } - if (moduleHasNonRelativeName(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { if (traceEnabled) { trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); } @@ -1024,7 +1020,7 @@ namespace ts { } const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); - if (moduleHasNonRelativeName(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { // Climb up parent directories looking for a module. const resolved = forEachAncestorDirectory(containingDirectory, directory => { const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, traceEnabled, host); diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index af4c39e4f8d..3f1a4e054a8 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -29,7 +29,7 @@ namespace ts.server { : undefined; const primaryResult = resolveModuleName(moduleName, containingFile, compilerOptions, host); // return result immediately only if it is .ts, .tsx or .d.ts - if (moduleHasNonRelativeName(moduleName) && !(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension)) && globalCache !== undefined) { + if (!isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension)) && globalCache !== undefined) { // otherwise try to load typings from @types // create different collection of failed lookup locations for second pass diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index d30997aa076..2be20f35c16 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -565,7 +565,7 @@ namespace ts.codefix { function getRelativePath(path: string, directoryPath: string) { const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); - return moduleHasNonRelativeName(relativePath) ? "./" + relativePath : relativePath; + return !pathIsRelative(relativePath) ? "./" + relativePath : relativePath; } } From d24b3a3cbad7f00d35faeb4137f604f73277b468 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 13 Jul 2017 14:49:50 -0700 Subject: [PATCH 07/22] Add fourslash tests for function(new/this:T) syntax --- tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts | 4 ++++ tests/cases/fourslash/completionInJSDocFunctionNew.ts | 10 ++++++++++ .../cases/fourslash/completionInJSDocFunctionThis.ts | 9 +++++++++ .../fourslash/findAllReferencesJSDocFunctionNew.ts | 9 +++++++++ .../fourslash/findAllReferencesJSDocFunctionThis.ts | 11 +++++++++++ tests/cases/fourslash/quickInfoJSDocFunctionNew.ts | 8 ++++++++ tests/cases/fourslash/quickInfoJSDocFunctionThis.ts | 9 +++++++++ 7 files changed, 60 insertions(+) create mode 100644 tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts create mode 100644 tests/cases/fourslash/completionInJSDocFunctionNew.ts create mode 100644 tests/cases/fourslash/completionInJSDocFunctionThis.ts create mode 100644 tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts create mode 100644 tests/cases/fourslash/findAllReferencesJSDocFunctionThis.ts create mode 100644 tests/cases/fourslash/quickInfoJSDocFunctionNew.ts create mode 100644 tests/cases/fourslash/quickInfoJSDocFunctionThis.ts diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts new file mode 100644 index 00000000000..93107ef669b --- /dev/null +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts @@ -0,0 +1,4 @@ +/// +//// var x: [|?|] = 12; + +verify.rangeAfterCodeFix("any"); diff --git a/tests/cases/fourslash/completionInJSDocFunctionNew.ts b/tests/cases/fourslash/completionInJSDocFunctionNew.ts new file mode 100644 index 00000000000..9e19964cd25 --- /dev/null +++ b/tests/cases/fourslash/completionInJSDocFunctionNew.ts @@ -0,0 +1,10 @@ + +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function (new: string, string): string} */ +////var f = function (s) { return /**/; } + +goTo.marker(); +verify.completionListCount(115); +verify.completionListContains('new', 'new', '', 'keyword'); diff --git a/tests/cases/fourslash/completionInJSDocFunctionThis.ts b/tests/cases/fourslash/completionInJSDocFunctionThis.ts new file mode 100644 index 00000000000..3fe02825d4c --- /dev/null +++ b/tests/cases/fourslash/completionInJSDocFunctionThis.ts @@ -0,0 +1,9 @@ +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function (this: string, string): string} */ +////var f = function (s) { return /**/; } + +goTo.marker(); +verify.completionListCount(115); +verify.completionListContains('this'); diff --git a/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts b/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts new file mode 100644 index 00000000000..e75040d1f77 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts @@ -0,0 +1,9 @@ +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function ([|new|]: string, string): string} */ +////var f; + +const [a0] = test.ranges(); +// should be: verify.referenceGroups([a0], [{ definition: "new", ranges: [a0] }]); +verify.referenceGroups([a0], undefined); diff --git a/tests/cases/fourslash/findAllReferencesJSDocFunctionThis.ts b/tests/cases/fourslash/findAllReferencesJSDocFunctionThis.ts new file mode 100644 index 00000000000..1f00e9f5647 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesJSDocFunctionThis.ts @@ -0,0 +1,11 @@ +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function (this: string, string): string} */ +////var f = function (s) { return [|this|] + s; } + +const [a0] = test.ranges(); +// should be: verify.referenceGroups([a0, a1], [{ definition: "this", ranges: [a0] }]); + +// but is currently +verify.referenceGroups([], undefined); diff --git a/tests/cases/fourslash/quickInfoJSDocFunctionNew.ts b/tests/cases/fourslash/quickInfoJSDocFunctionNew.ts new file mode 100644 index 00000000000..5fed7d9a39a --- /dev/null +++ b/tests/cases/fourslash/quickInfoJSDocFunctionNew.ts @@ -0,0 +1,8 @@ +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function (new: string, string): string} */ +////var f/**/; + +goTo.marker(); +verify.quickInfoIs('var f: new (arg1: string) => string'); diff --git a/tests/cases/fourslash/quickInfoJSDocFunctionThis.ts b/tests/cases/fourslash/quickInfoJSDocFunctionThis.ts new file mode 100644 index 00000000000..5568ff829f1 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJSDocFunctionThis.ts @@ -0,0 +1,9 @@ + +/// +// @allowJs: true +// @Filename: Foo.js +/////** @type {function (this: string, string): string} */ +////var f/**/ = function (s) { return s; } + +goTo.marker(); +verify.quickInfoIs('var f: (this: string, arg1: string) => string'); From da5285e979e1b3492a4ebfa97265f47d95a7d470 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 09:34:35 -0700 Subject: [PATCH 08/22] Update baselines --- src/harness/unittests/jsDocParsing.ts | 6 +- ...eExpressions.parsesCorrectly.newType1.json | 63 +++++++++----- ...Expressions.parsesCorrectly.thisType1.json | 63 +++++++++----- ...ns.parsesCorrectly.tsConstructorType.json} | 0 .../jsdocDisallowedInTypescript.errors.txt | 65 ++++++++++++++ ...ript.js => jsdocDisallowedInTypescript.js} | 8 +- .../reference/jsdocInTypescript.errors.txt | 85 ------------------- .../reference/jsdocInTypescript2.errors.txt | 9 -- .../jsdocParseErrorsInTypescript.errors.txt | 9 ++ ...pt2.js => jsdocParseErrorsInTypescript.js} | 4 +- ...ript.ts => jsdocDisallowedInTypescript.ts} | 2 - ...pt2.ts => jsdocParseErrorsInTypescript.ts} | 0 .../fourslash/completionInJSDocFunctionNew.ts | 4 +- .../completionInJSDocFunctionThis.ts | 5 +- .../findAllReferencesJSDocFunctionNew.ts | 5 +- 15 files changed, 170 insertions(+), 158 deletions(-) rename tests/baselines/reference/JSDocParsing/{TypeExpressions.parsesCorrectly.tsConstructoType.json => TypeExpressions.parsesCorrectly.tsConstructorType.json} (100%) create mode 100644 tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt rename tests/baselines/reference/{jsdocInTypescript.js => jsdocDisallowedInTypescript.js} (84%) delete mode 100644 tests/baselines/reference/jsdocInTypescript.errors.txt delete mode 100644 tests/baselines/reference/jsdocInTypescript2.errors.txt create mode 100644 tests/baselines/reference/jsdocParseErrorsInTypescript.errors.txt rename tests/baselines/reference/{jsdocInTypescript2.js => jsdocParseErrorsInTypescript.js} (69%) rename tests/cases/conformance/jsdoc/{jsdocInTypescript.ts => jsdocDisallowedInTypescript.ts} (90%) rename tests/cases/conformance/jsdoc/{jsdocInTypescript2.ts => jsdocParseErrorsInTypescript.ts} (100%) diff --git a/src/harness/unittests/jsDocParsing.ts b/src/harness/unittests/jsDocParsing.ts index 032c4e848b5..48d280c78dc 100644 --- a/src/harness/unittests/jsDocParsing.ts +++ b/src/harness/unittests/jsDocParsing.ts @@ -44,8 +44,8 @@ namespace ts { parsesCorrectly("functionType1", "{function()}"); parsesCorrectly("functionType2", "{function(string, boolean)}"); parsesCorrectly("functionReturnType1", "{function(string, boolean)}"); - parsesCorrectly("thisType1", "{this:a.b}"); - parsesCorrectly("newType1", "{new:a.b}"); + parsesCorrectly("thisType1", "{function(this:a.b)}"); + parsesCorrectly("newType1", "{function(new:a.b)}"); parsesCorrectly("variadicType", "{...number}"); parsesCorrectly("optionalType", "{number=}"); parsesCorrectly("optionalNullable", "{?=}"); @@ -64,7 +64,7 @@ namespace ts { parsesCorrectly("tupleType3", "{[number,string,boolean]}"); parsesCorrectly("tupleTypeWithTrailingComma", "{[number,]}"); parsesCorrectly("typeOfType", "{typeof M}"); - parsesCorrectly("tsConstructoType", "{new () => string}"); + parsesCorrectly("tsConstructorType", "{new () => string}"); parsesCorrectly("tsFunctionType", "{() => string}"); parsesCorrectly("typeArgumentsNotFollowingDot", "{a<>}"); parsesCorrectly("functionTypeWithTrailingComma", "{function(a,)}"); diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json index f5956cd2ddb..4458100a3c1 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json @@ -1,32 +1,51 @@ { - "kind": "JSDocConstructorType", - "pos": 4, - "end": 8, + "kind": "JSDocFunctionType", + "pos": 1, + "end": 18, "flags": "JSDoc", - "type": { - "kind": "TypeReference", - "pos": 5, - "end": 8, - "flags": "JSDoc", - "typeName": { - "kind": "FirstNode", - "pos": 5, - "end": 8, + "parameters": { + "0": { + "kind": "Parameter", + "pos": 10, + "end": 17, "flags": "JSDoc", - "left": { + "name": { "kind": "Identifier", - "pos": 5, - "end": 6, + "pos": 10, + "end": 13, "flags": "JSDoc", - "text": "a" + "originalKeywordKind": "NewKeyword", + "text": "new" }, - "right": { - "kind": "Identifier", - "pos": 7, - "end": 8, + "type": { + "kind": "TypeReference", + "pos": 14, + "end": 17, "flags": "JSDoc", - "text": "b" + "typeName": { + "kind": "FirstNode", + "pos": 14, + "end": 17, + "flags": "JSDoc", + "left": { + "kind": "Identifier", + "pos": 14, + "end": 15, + "flags": "JSDoc", + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 16, + "end": 17, + "flags": "JSDoc", + "text": "b" + } + } } - } + }, + "length": 1, + "pos": 10, + "end": 17 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json index cb6cfba99fe..276a3bc4ee9 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json @@ -1,32 +1,51 @@ { - "kind": "JSDocThisType", - "pos": 5, - "end": 9, + "kind": "JSDocFunctionType", + "pos": 1, + "end": 19, "flags": "JSDoc", - "type": { - "kind": "TypeReference", - "pos": 6, - "end": 9, - "flags": "JSDoc", - "typeName": { - "kind": "FirstNode", - "pos": 6, - "end": 9, + "parameters": { + "0": { + "kind": "Parameter", + "pos": 10, + "end": 18, "flags": "JSDoc", - "left": { + "name": { "kind": "Identifier", - "pos": 6, - "end": 7, + "pos": 10, + "end": 14, "flags": "JSDoc", - "text": "a" + "originalKeywordKind": "ThisKeyword", + "text": "this" }, - "right": { - "kind": "Identifier", - "pos": 8, - "end": 9, + "type": { + "kind": "TypeReference", + "pos": 15, + "end": 18, "flags": "JSDoc", - "text": "b" + "typeName": { + "kind": "FirstNode", + "pos": 15, + "end": 18, + "flags": "JSDoc", + "left": { + "kind": "Identifier", + "pos": 15, + "end": 16, + "flags": "JSDoc", + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 17, + "end": 18, + "flags": "JSDoc", + "text": "b" + } + } } - } + }, + "length": 1, + "pos": 10, + "end": 18 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructorType.json similarity index 100% rename from tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructoType.json rename to tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tsConstructorType.json diff --git a/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt b/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt new file mode 100644 index 00000000000..18a5c99dfd0 --- /dev/null +++ b/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt @@ -0,0 +1,65 @@ +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(2,10): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(4,15): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(4,27): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(7,20): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(10,18): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(11,12): error TS2554: Expected 1 arguments, but got 2. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(13,14): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(14,11): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(15,8): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(16,15): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(17,11): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(18,17): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(19,5): error TS2322: Type 'undefined' is not assignable to type 'number | null'. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(19,17): error TS8020: JSDoc types can only be used inside documentation comments. + + +==== tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts (14 errors) ==== + // grammar error from checker + var ara: Array. = [1,2,3]; + ~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + + function f(x: ?number, y: Array.) { + ~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + ~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + return x ? x + y[1] : y[0]; + } + function hof(ctor: function(new: number, string)) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + return new ctor('hi'); + } + function hof2(f: function(this: number, string): string) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + return f(12, 'hullo'); + ~~~~~~~~~~~~~~ +!!! error TS2554: Expected 1 arguments, but got 2. + } + var whatevs: * = 1001; + ~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var ques: ? = 'what'; + ~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var g: function(number, number): number = (n,m) => n + m; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var variadic: ...boolean = [true, false, true]; + ~~~~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var most: !string = 'definite'; + ~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var postfixdef: number! = 101; + ~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + var postfixopt: number? = undefined; + ~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'number | null'. + ~~~~~~~ +!!! error TS8020: JSDoc types can only be used inside documentation comments. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypescript.js b/tests/baselines/reference/jsdocDisallowedInTypescript.js similarity index 84% rename from tests/baselines/reference/jsdocInTypescript.js rename to tests/baselines/reference/jsdocDisallowedInTypescript.js index 665707e15d1..2785eca2073 100644 --- a/tests/baselines/reference/jsdocInTypescript.js +++ b/tests/baselines/reference/jsdocDisallowedInTypescript.js @@ -1,4 +1,4 @@ -//// [jsdocInTypescript.ts] +//// [jsdocDisallowedInTypescript.ts] // grammar error from checker var ara: Array. = [1,2,3]; @@ -16,13 +16,11 @@ var ques: ? = 'what'; var g: function(number, number): number = (n,m) => n + m; var variadic: ...boolean = [true, false, true]; var most: !string = 'definite'; -var weird1: new:string = {}; -var weird2: this:string = {}; var postfixdef: number! = 101; var postfixopt: number? = undefined; -//// [jsdocInTypescript.js] +//// [jsdocDisallowedInTypescript.js] "use strict"; // grammar error from checker var ara = [1, 2, 3]; @@ -40,7 +38,5 @@ var ques = 'what'; var g = function (n, m) { return n + m; }; var variadic = [true, false, true]; var most = 'definite'; -var weird1 = {}; -var weird2 = {}; var postfixdef = 101; var postfixopt = undefined; diff --git a/tests/baselines/reference/jsdocInTypescript.errors.txt b/tests/baselines/reference/jsdocInTypescript.errors.txt deleted file mode 100644 index d1d6f404e15..00000000000 --- a/tests/baselines/reference/jsdocInTypescript.errors.txt +++ /dev/null @@ -1,85 +0,0 @@ -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(2,10): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,15): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(4,27): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,20): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(7,32): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,18): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(10,31): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(11,12): error TS2554: Expected 1 arguments, but got 2. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(13,14): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(14,11): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(15,8): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(16,15): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(17,11): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,5): error TS2322: Type '{}' is not assignable to type 'string'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(18,16): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,5): error TS2322: Type '{}' is not assignable to type 'string'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(19,17): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(20,17): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,5): error TS2322: Type 'undefined' is not assignable to type 'number | null'. -tests/cases/conformance/jsdoc/jsdocInTypescript.ts(21,17): error TS8020: JSDoc types can only be used inside documentation comments. - - -==== tests/cases/conformance/jsdoc/jsdocInTypescript.ts (20 errors) ==== - // grammar error from checker - var ara: Array. = [1,2,3]; - ~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - - function f(x: ?number, y: Array.) { - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - ~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - return x ? x + y[1] : y[0]; - } - function hof(ctor: function(new: number, string)) { - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - ~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - return new ctor('hi'); - } - function hof2(f: function(this: number, string): string) { - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - ~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - return f(12, 'hullo'); - ~~~~~~~~~~~~~~ -!!! error TS2554: Expected 1 arguments, but got 2. - } - var whatevs: * = 1001; - ~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var ques: ? = 'what'; - ~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var g: function(number, number): number = (n,m) => n + m; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var variadic: ...boolean = [true, false, true]; - ~~~~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var most: !string = 'definite'; - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var weird1: new:string = {}; - ~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type 'string'. - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var weird2: this:string = {}; - ~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type 'string'. - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var postfixdef: number! = 101; - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - var postfixopt: number? = undefined; - ~~~~~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'number | null'. - ~~~~~~~ -!!! error TS8020: JSDoc types can only be used inside documentation comments. - \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypescript2.errors.txt b/tests/baselines/reference/jsdocInTypescript2.errors.txt deleted file mode 100644 index 4616212c211..00000000000 --- a/tests/baselines/reference/jsdocInTypescript2.errors.txt +++ /dev/null @@ -1,9 +0,0 @@ -tests/cases/conformance/jsdoc/jsdocInTypescript2.ts(2,27): error TS1109: Expression expected. - - -==== tests/cases/conformance/jsdoc/jsdocInTypescript2.ts (1 errors) ==== - // parse error (blocks grammar errors from checker) - function parse1(n: number=) { } - ~ -!!! error TS1109: Expression expected. - \ No newline at end of file diff --git a/tests/baselines/reference/jsdocParseErrorsInTypescript.errors.txt b/tests/baselines/reference/jsdocParseErrorsInTypescript.errors.txt new file mode 100644 index 00000000000..655c27fb89c --- /dev/null +++ b/tests/baselines/reference/jsdocParseErrorsInTypescript.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/jsdoc/jsdocParseErrorsInTypescript.ts(2,27): error TS1109: Expression expected. + + +==== tests/cases/conformance/jsdoc/jsdocParseErrorsInTypescript.ts (1 errors) ==== + // parse error (blocks grammar errors from checker) + function parse1(n: number=) { } + ~ +!!! error TS1109: Expression expected. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypescript2.js b/tests/baselines/reference/jsdocParseErrorsInTypescript.js similarity index 69% rename from tests/baselines/reference/jsdocInTypescript2.js rename to tests/baselines/reference/jsdocParseErrorsInTypescript.js index 0624d5af1d8..09fcae6e1b6 100644 --- a/tests/baselines/reference/jsdocInTypescript2.js +++ b/tests/baselines/reference/jsdocParseErrorsInTypescript.js @@ -1,9 +1,9 @@ -//// [jsdocInTypescript2.ts] +//// [jsdocParseErrorsInTypescript.ts] // parse error (blocks grammar errors from checker) function parse1(n: number=) { } -//// [jsdocInTypescript2.js] +//// [jsdocParseErrorsInTypescript.js] // parse error (blocks grammar errors from checker) function parse1(n) { if (n === void 0) { n = ; } diff --git a/tests/cases/conformance/jsdoc/jsdocInTypescript.ts b/tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts similarity index 90% rename from tests/cases/conformance/jsdoc/jsdocInTypescript.ts rename to tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts index fbe8982f891..62ad39491d1 100644 --- a/tests/cases/conformance/jsdoc/jsdocInTypescript.ts +++ b/tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts @@ -17,7 +17,5 @@ var ques: ? = 'what'; var g: function(number, number): number = (n,m) => n + m; var variadic: ...boolean = [true, false, true]; var most: !string = 'definite'; -var weird1: new:string = {}; -var weird2: this:string = {}; var postfixdef: number! = 101; var postfixopt: number? = undefined; diff --git a/tests/cases/conformance/jsdoc/jsdocInTypescript2.ts b/tests/cases/conformance/jsdoc/jsdocParseErrorsInTypescript.ts similarity index 100% rename from tests/cases/conformance/jsdoc/jsdocInTypescript2.ts rename to tests/cases/conformance/jsdoc/jsdocParseErrorsInTypescript.ts diff --git a/tests/cases/fourslash/completionInJSDocFunctionNew.ts b/tests/cases/fourslash/completionInJSDocFunctionNew.ts index 9e19964cd25..0d3391cf774 100644 --- a/tests/cases/fourslash/completionInJSDocFunctionNew.ts +++ b/tests/cases/fourslash/completionInJSDocFunctionNew.ts @@ -3,8 +3,8 @@ // @allowJs: true // @Filename: Foo.js /////** @type {function (new: string, string): string} */ -////var f = function (s) { return /**/; } +////var f = function () { return new/**/; } goTo.marker(); verify.completionListCount(115); -verify.completionListContains('new', 'new', '', 'keyword'); +verify.completionListContains('new'); diff --git a/tests/cases/fourslash/completionInJSDocFunctionThis.ts b/tests/cases/fourslash/completionInJSDocFunctionThis.ts index 3fe02825d4c..c28eeeb397f 100644 --- a/tests/cases/fourslash/completionInJSDocFunctionThis.ts +++ b/tests/cases/fourslash/completionInJSDocFunctionThis.ts @@ -2,8 +2,9 @@ // @allowJs: true // @Filename: Foo.js /////** @type {function (this: string, string): string} */ -////var f = function (s) { return /**/; } +////var f = function (s) { return this/**/; } goTo.marker(); -verify.completionListCount(115); +verify.completionListCount(116); verify.completionListContains('this'); + diff --git a/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts b/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts index e75040d1f77..b094714cefb 100644 --- a/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts +++ b/tests/cases/fourslash/findAllReferencesJSDocFunctionNew.ts @@ -1,9 +1,8 @@ /// // @allowJs: true // @Filename: Foo.js -/////** @type {function ([|new|]: string, string): string} */ +/////** @type {function ([|{|"isWriteAccess": true, "isDefinition": true|}new|]: string, string): string} */ ////var f; const [a0] = test.ranges(); -// should be: verify.referenceGroups([a0], [{ definition: "new", ranges: [a0] }]); -verify.referenceGroups([a0], undefined); +verify.singleReferenceGroup("(parameter) new: string", [a0]); From 6e861fd3e609a96792faa33cd9cfe5f9dceaaf68 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 09:36:12 -0700 Subject: [PATCH 09/22] Remove JSDocConstructor/ThisType and just use named parameters --- src/compiler/binder.ts | 9 +----- src/compiler/checker.ts | 58 ++++++++++++++++----------------------- src/compiler/parser.ts | 21 +++++--------- src/compiler/types.ts | 14 +--------- src/compiler/utilities.ts | 13 ++------- 5 files changed, 36 insertions(+), 79 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 0c3f1a2444d..803c9f60709 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -280,14 +280,7 @@ namespace ts { Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); const functionType = node.parent; const index = indexOf(functionType.parameters, node); - switch ((node as ParameterDeclaration).type.kind) { - case SyntaxKind.JSDocThisType: - return "this" as __String; - case SyntaxKind.JSDocConstructorType: - return "new" as __String; - default: - return "arg" + index as __String; - } + return "arg" + index as __String; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; let nameFromParentNode: __String; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5d1cf5bcc6..fa44b6a3f5b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6339,7 +6339,7 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - if (i === 0 && paramSymbol.name === "this" || (param.type && param.type.kind === SyntaxKind.JSDocThisType)) { + if (i === 0 && paramSymbol.name === "this") { hasThisParameter = true; thisParameter = param.symbol; } @@ -6882,7 +6882,6 @@ namespace ts { case "Null": return nullType; case "Object": - case "object": return anyType; case "Function": case "function": @@ -7842,12 +7841,7 @@ namespace ts { case SyntaxKind.NeverKeyword: return neverType; case SyntaxKind.ObjectKeyword: - if (node.flags & NodeFlags.JavaScriptFile) { - return anyType; - } - else { - return nonPrimitiveType; - } + return node.flags & NodeFlags.JavaScriptFile ? anyType : nonPrimitiveType; case SyntaxKind.ThisType: case SyntaxKind.ThisKeyword: return getTypeFromThisTypeNode(node); @@ -7873,8 +7867,6 @@ namespace ts { return getTypeFromJSDocNullableTypeNode(node); case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNonNullableType: - case SyntaxKind.JSDocConstructorType: - case SyntaxKind.JSDocThisType: case SyntaxKind.JSDocOptionalType: return getTypeFromTypeNode((node).type); case SyntaxKind.FunctionType: @@ -12367,7 +12359,9 @@ namespace ts { const jsdocType = getJSDocType(node); if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) { const jsDocFunctionType = jsdocType; - if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) { + if (jsDocFunctionType.parameters.length > 0 && + jsDocFunctionType.parameters[0].name && + (jsDocFunctionType.parameters[0].name as Identifier).text === "this") { return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type); } } @@ -19361,17 +19355,31 @@ namespace ts { } } - function checkJsDoc(node: FunctionDeclaration | MethodDeclaration) { - if (!node.jsDoc) { + function checkJSDoc(node: FunctionDeclaration | MethodDeclaration) { + if (!isInJavaScriptFile(node)) { return; } - for (const doc of node.jsDoc) { - checkSourceElement(doc); + forEach(node.jsDoc, checkSourceElement); + } + + function checkJSDocComment(node: JSDoc) { + if ((node as JSDoc).tags) { + for (const tag of (node as JSDoc).tags) { + checkSourceElement(tag); + } } } + function checkJSDocFunctionType(node: JSDocFunctionType) { + for (const p of node.parameters) { + // don't bother with normal parameter checking since jsdoc function parameters only consist of a type + checkSourceElement(p.type); + } + checkSourceElement(node.type); + } + function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void { - checkJsDoc(node); + checkJSDoc(node); checkDecorators(node); checkSignatureDeclaration(node); const functionFlags = getFunctionFlags(node); @@ -21970,22 +21978,6 @@ namespace ts { } } - function checkJSDocComment(node: JSDoc) { - if (isInJavaScriptFile(node) && (node as JSDoc).tags) { - for (const tag of (node as JSDoc).tags) { - checkSourceElement(tag); - } - } - } - - function checkJSDocFunctionType(node: JSDocFunctionType) { - for (const p of node.parameters) { - // don't bother with normal parameter checking since jsdoc function parameters only consist of a type - checkSourceElement(p.type); - } - checkSourceElement(node.type); - } - function checkSourceElement(node: Node): void { if (!node) { return; @@ -22052,8 +22044,6 @@ namespace ts { case SyntaxKind.JSDocFunctionType: checkJSDocFunctionType(node as JSDocFunctionType); // falls through - case SyntaxKind.JSDocConstructorType: - case SyntaxKind.JSDocThisType: case SyntaxKind.JSDocVariadicType: case SyntaxKind.JSDocNonNullableType: case SyntaxKind.JSDocNullableType: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 41abbf59305..1ecd654d86a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -404,10 +404,6 @@ namespace ts { visitNode(cbNode, (node).type); case SyntaxKind.JSDocVariadicType: return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocConstructorType: - return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocThisType: - return visitNode(cbNode, (node).type); case SyntaxKind.JSDocComment: return visitNodes(cbNode, cbNodes, (node).tags); case SyntaxKind.JSDocParameterTag: @@ -2134,13 +2130,17 @@ namespace ts { } function parseJSDocParameter(): ParameterDeclaration { - const parameter = createNode(SyntaxKind.Parameter); + const parameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration; + if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) { + parameter.name = parseIdentifierName(); + parseExpected(SyntaxKind.ColonToken); + } parameter.type = parseType(); return finishNode(parameter); } function parseJSDocNodeWithType(kind: SyntaxKind): TypeNode { - const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType | JSDocThisType | JSDocConstructorType; + const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType; nextToken(); result.type = parseType(); return finishNode(result); @@ -2567,14 +2567,10 @@ namespace ts { return finishNode(node); } - function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode | JSDocConstructorType { + function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode { const node = createNode(kind); if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); - if (token() === SyntaxKind.ColonToken) { - // JSDoc -- `new:T` as in `function(new:T, string, string)`; an infix constructor-return-type - return parseJSDocNodeWithType(SyntaxKind.JSDocConstructorType) as JSDocConstructorType; - } } fillSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type, node); return finishNode(node); @@ -2633,9 +2629,6 @@ namespace ts { if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { return parseThisTypePredicate(thisKeyword); } - else if (token() === SyntaxKind.ColonToken) { - return parseJSDocNodeWithType(SyntaxKind.JSDocThisType); - } else { return thisKeyword; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b2fb24fa0e4..85e859603d7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -352,8 +352,6 @@ namespace ts { JSDocOptionalType, JSDocFunctionType, JSDocVariadicType, - JSDocConstructorType, - JSDocThisType, JSDocComment, JSDocTag, JSDocAugmentsTag, @@ -2067,17 +2065,7 @@ namespace ts { type: TypeNode; } - export interface JSDocConstructorType extends JSDocType { - kind: SyntaxKind.JSDocConstructorType; - type: TypeNode; - } - - export interface JSDocThisType extends JSDocType { - kind: SyntaxKind.JSDocThisType; - type: TypeNode; - } - - export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; + export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f7356f425fe..dcfad8e776e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1447,8 +1447,9 @@ namespace ts { export function isJSDocConstructSignature(node: Node) { return node.kind === SyntaxKind.JSDocFunctionType && - (node).parameters.length > 0 && - (node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType; + (node as JSDocFunctionType).parameters.length > 0 && + (node as JSDocFunctionType).parameters[0].name && + ((node as JSDocFunctionType).parameters[0].name as Identifier).text === "new"; } export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean { @@ -4687,14 +4688,6 @@ namespace ts { return node.kind === SyntaxKind.JSDocVariadicType; } - export function isJSDocConstructorType(node: Node): node is JSDocConstructorType { - return node.kind === SyntaxKind.JSDocConstructorType; - } - - export function isJSDocThisType(node: Node): node is JSDocThisType { - return node.kind === SyntaxKind.JSDocThisType; - } - export function isJSDoc(node: Node): node is JSDoc { return node.kind === SyntaxKind.JSDocComment; } From f1145c35ca8d5139bfec0ed496d6b90e29fd14da Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 10:15:30 -0700 Subject: [PATCH 10/22] Improve JSDoc function checking 1. Remove checkJSDocFunctionType in favour of checkSignature. 2. Check that 'new', in addition to 'this', must be the first parameter. 3. Remove prematurely added JSDoc-quickfix test. --- src/compiler/checker.ts | 19 ++++++++----------- src/compiler/diagnosticMessages.json | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 1 + .../fourslash/codeFixChangeJSDocSyntax1.ts | 4 ---- 5 files changed, 11 insertions(+), 17 deletions(-) delete mode 100644 tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fa44b6a3f5b..7d7c9cb89d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17863,9 +17863,9 @@ namespace ts { if (node.questionToken && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } - if ((node.name).text === "this") { + if (node.name && ((node.name as Identifier).text === "this" || (node.name as Identifier).text === "new")) { if (indexOf(func.parameters, node) !== 0) { - error(node, Diagnostics.A_this_parameter_must_be_the_first_parameter); + error(node, Diagnostics.A_0_parameter_must_be_the_first_parameter, (node.name as Identifier).text as string); } if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) { error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); @@ -19370,14 +19370,6 @@ namespace ts { } } - function checkJSDocFunctionType(node: JSDocFunctionType) { - for (const p of node.parameters) { - // don't bother with normal parameter checking since jsdoc function parameters only consist of a type - checkSourceElement(p.type); - } - checkSourceElement(node.type); - } - function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void { checkJSDoc(node); checkDecorators(node); @@ -19923,6 +19915,11 @@ namespace ts { function checkVariableLikeDeclaration(node: VariableLikeDeclaration) { checkDecorators(node); checkSourceElement(node.type); + + // JSDoc `function(string, string): string` syntax results in parameters with no name + if (!node.name) { + return; + } // For a computed property, just check the initializer and exit // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including @@ -22042,7 +22039,7 @@ namespace ts { case SyntaxKind.JSDocParameterTag: return checkSourceElement((node as JSDocParameterTag).typeExpression); case SyntaxKind.JSDocFunctionType: - checkJSDocFunctionType(node as JSDocFunctionType); + checkSignatureDeclaration(node as JSDocFunctionType); // falls through case SyntaxKind.JSDocVariadicType: case SyntaxKind.JSDocNonNullableType: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9881d32d775..7cd6108576c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2064,7 +2064,7 @@ "category": "Error", "code": 2679 }, - "A 'this' parameter must be the first parameter.": { + "A '{0}' parameter must be the first parameter.": { "category": "Error", "code": 2680 }, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 85e859603d7..c10cc299728 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -441,7 +441,7 @@ namespace ts { // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. /* @internal */ PossiblyContainsDynamicImport = 1 << 19, - JSDoc = 1 << 20, // If node was parsed inside jsdoc + JSDoc = 1 << 20, // If node was parsed inside jsdoc BlockScoped = Let | Const, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index dcfad8e776e..3a4ece29f75 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4873,6 +4873,7 @@ namespace ts { case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: case SyntaxKind.FunctionType: + case SyntaxKind.JSDocFunctionType: case SyntaxKind.ConstructorType: return true; } diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts deleted file mode 100644 index 93107ef669b..00000000000 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts +++ /dev/null @@ -1,4 +0,0 @@ -/// -//// var x: [|?|] = 12; - -verify.rangeAfterCodeFix("any"); From 40ae42221ecb038e792fd5d5b8a84ca3f6fc5e9c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 11:07:20 -0700 Subject: [PATCH 11/22] Better JSDoc generic errors and faster isInJSDoc --- src/compiler/checker.ts | 7 ++++--- src/compiler/parser.ts | 5 +++-- src/compiler/types.ts | 4 ++-- src/compiler/utilities.ts | 6 +++++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d7c9cb89d6..7b1fa6203a6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18454,8 +18454,9 @@ namespace ts { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDot && !isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { - grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJavaScriptFile(node) && !isInJSDoc(node)) { + grammarErrorAtPos(getSourceFileOfNode(node), node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + } const type = getTypeFromTypeReference(node); if (type !== unknownType) { @@ -22046,7 +22047,7 @@ namespace ts { case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocAllType: case SyntaxKind.JSDocUnknownType: - if (!isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) { + if (!isInJavaScriptFile(node) && !isInJSDoc(node)) { grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } return; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1ecd654d86a..3e850245e7f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1925,10 +1925,11 @@ namespace ts { // The allowReservedWords parameter controls whether reserved words are permitted after the first dot function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { let entity: EntityName = allowReservedWords ? parseIdentifierName() : parseIdentifier(diagnosticMessage); + let dotPos = scanner.getStartPos(); while (parseOptional(SyntaxKind.DotToken)) { if (token() === SyntaxKind.LessThanToken) { - // the entity is part of a JSDoc-style generic, so record this for later in case it's an error - entity.jsdocDot = true; + // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting + entity.jsdocDotPos = dotPos; break; } const node: QualifiedName = createNode(SyntaxKind.QualifiedName, entity.pos); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c10cc299728..6ba1591d54f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -576,7 +576,7 @@ namespace ts { /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics. - /*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id. + /*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id. } // Transient identifier node (marked by id === -1) @@ -596,7 +596,7 @@ namespace ts { kind: SyntaxKind.QualifiedName; left: EntityName; right: Identifier; - /*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id1.Id2. + /*@internal*/ jsdocDotPos?: number; // QualifiedName occurs in JSDoc-style generic: Id1.Id2. } export type EntityName = Identifier | QualifiedName; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3a4ece29f75..5ae1d835e46 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1292,6 +1292,10 @@ namespace ts { return node && !!(node.flags & NodeFlags.JavaScriptFile); } + export function isInJSDoc(node: Node): boolean { + return node && !!(node.flags & NodeFlags.JSDoc); + } + /** * Returns true if the node is a CallExpression to the identifier 'require' with * exactly one argument (of the form 'require("name")'). @@ -3299,7 +3303,7 @@ namespace ts { } export function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode { - return node.kind === SyntaxKind.TypeReference && !!findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression); + return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; } /** From b2e892f0b9e6713f890eba64c9d9307bc46793be Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 11:08:06 -0700 Subject: [PATCH 12/22] Update baselines --- .../TypeExpressions.parsesCorrectly.typeReference1.json | 2 +- .../TypeExpressions.parsesCorrectly.typeReference2.json | 2 +- .../reference/jsdocDisallowedInTypescript.errors.txt | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json index 62d6b12c8e5..9c22db0c64d 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json @@ -9,7 +9,7 @@ "end": 2, "flags": "JSDoc", "text": "a", - "jsdocDot": true + "jsdocDotPos": 2 }, "typeArguments": { "0": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json index 4ea0a37ee41..38e2616fc04 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json @@ -9,7 +9,7 @@ "end": 2, "flags": "JSDoc", "text": "a", - "jsdocDot": true + "jsdocDotPos": 2 }, "typeArguments": { "0": { diff --git a/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt b/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt index 18a5c99dfd0..554b7af5822 100644 --- a/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt +++ b/tests/baselines/reference/jsdocDisallowedInTypescript.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(2,10): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(2,15): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(4,15): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(4,27): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(4,32): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(7,20): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(10,18): error TS8020: JSDoc types can only be used inside documentation comments. tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(11,12): error TS2554: Expected 1 arguments, but got 2. @@ -17,13 +17,13 @@ tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(19,17): error TS802 ==== tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts (14 errors) ==== // grammar error from checker var ara: Array. = [1,2,3]; - ~~~~~~~~~~~~~~ + ~ !!! error TS8020: JSDoc types can only be used inside documentation comments. function f(x: ?number, y: Array.) { ~~~~~~~ !!! error TS8020: JSDoc types can only be used inside documentation comments. - ~~~~~~~~~~~~~~ + ~ !!! error TS8020: JSDoc types can only be used inside documentation comments. return x ? x + y[1] : y[0]; } From bdc3f1f3f7a67665dbd5175595627980508ce421 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 13:29:44 -0700 Subject: [PATCH 13/22] Address more PR comments --- src/compiler/parser.ts | 54 +++++++++---------- src/harness/unittests/jsDocParsing.ts | 2 +- ...xpressions.parsesCorrectly.arrayType3.json | 34 +++++++----- .../jsdocPrefixPostfixParsing.symbols | 25 +++++++++ .../reference/jsdocPrefixPostfixParsing.types | 25 +++++++++ .../jsdoc/jsdocPrefixPostfixParsing.ts | 21 ++++++++ 6 files changed, 117 insertions(+), 44 deletions(-) create mode 100644 tests/baselines/reference/jsdocPrefixPostfixParsing.symbols create mode 100644 tests/baselines/reference/jsdocPrefixPostfixParsing.types create mode 100644 tests/cases/conformance/jsdoc/jsdocPrefixPostfixParsing.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 3e850245e7f..086c121b173 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1922,7 +1922,6 @@ namespace ts { return createMissingList(); } - // The allowReservedWords parameter controls whether reserved words are permitted after the first dot function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { let entity: EntityName = allowReservedWords ? parseIdentifierName() : parseIdentifier(diagnosticMessage); let dotPos = scanner.getStartPos(); @@ -1932,6 +1931,7 @@ namespace ts { entity.jsdocDotPos = dotPos; break; } + dotPos = scanner.getStartPos(); const node: QualifiedName = createNode(SyntaxKind.QualifiedName, entity.pos); node.left = entity; node.right = parseRightSideOfDot(allowReservedWords); @@ -2140,7 +2140,7 @@ namespace ts { return finishNode(parameter); } - function parseJSDocNodeWithType(kind: SyntaxKind): TypeNode { + function parseJSDocNodeWithType(kind: SyntaxKind.JSDocVariadicType | SyntaxKind.JSDocNonNullableType): TypeNode { const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType; nextToken(); result.type = parseType(); @@ -2689,27 +2689,30 @@ namespace ts { } function parseJSDocPostfixTypeOrHigher(): TypeNode { - let type = parseArrayTypeOrHigher(); - let postfix: JSDocOptionalType | JSDocNonNullableType | JSDocNullableType; - // only parse postfix = inside jsdoc, because it's ambiguous elsewhere - if (contextFlags & NodeFlags.JSDoc && parseOptional(SyntaxKind.EqualsToken)) { - postfix = createNode(SyntaxKind.JSDocOptionalType, type.pos) as JSDocOptionalType; + const type = parseNonArrayType(); + const kind = getKind(token()); + if (!kind) return type; + nextToken(); + + const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType; + postfix.type = type; + return finishNode(postfix); + + function getKind(tokenKind: SyntaxKind): SyntaxKind | undefined { + switch (tokenKind) { + case SyntaxKind.EqualsToken: + // only parse postfix = inside jsdoc, because it's ambiguous elsewhere + return contextFlags & NodeFlags.JSDoc ? SyntaxKind.JSDocOptionalType : undefined; + case SyntaxKind.ExclamationToken: + return SyntaxKind.JSDocNonNullableType; + case SyntaxKind.QuestionToken: + return SyntaxKind.JSDocNullableType; + } } - else if (parseOptional(SyntaxKind.ExclamationToken)) { - postfix = createNode(SyntaxKind.JSDocNonNullableType, type.pos) as JSDocNonNullableType; - } - else if (parseOptional(SyntaxKind.QuestionToken)) { - postfix = createNode(SyntaxKind.JSDocNullableType, type.pos) as JSDocNullableType; - } - if (postfix) { - postfix.type = type; - type = finishNode(postfix); - } - return type; } function parseArrayTypeOrHigher(): TypeNode { - let type = parseNonArrayType(); + let type = parseJSDocPostfixTypeOrHigher(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { if (isStartOfType()) { const node = createNode(SyntaxKind.IndexedAccessType, type.pos); @@ -2741,7 +2744,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseJSDocPostfixTypeOrHigher(); + return parseArrayTypeOrHigher(); } function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { @@ -6576,15 +6579,8 @@ namespace ts { return finishNode(typedefTag); function isObjectTypeReference(node: TypeNode) { - if (node.kind === SyntaxKind.ObjectKeyword) { - return true; - } - if (node.kind === SyntaxKind.TypeReference) { - const jsDocTypeReference = node; - if (jsDocTypeReference.typeName.kind === SyntaxKind.Identifier) { - return (jsDocTypeReference.typeName as Identifier).text === "Object"; - } - } + return node.kind === SyntaxKind.ObjectKeyword || + isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.text === "Object"; } function scanChildTags(): JSDocTypeLiteral { diff --git a/src/harness/unittests/jsDocParsing.ts b/src/harness/unittests/jsDocParsing.ts index 48d280c78dc..0e6221567a2 100644 --- a/src/harness/unittests/jsDocParsing.ts +++ b/src/harness/unittests/jsDocParsing.ts @@ -54,7 +54,7 @@ namespace ts { parsesCorrectly("typeReference3", "{a.function}"); parsesCorrectly("arrayType1", "{a[]}"); parsesCorrectly("arrayType2", "{a[][]}"); - parsesCorrectly("arrayType3", "{a[][]=}"); + parsesCorrectly("arrayType3", "{(a[][])=}"); parsesCorrectly("keyword1", "{var}"); parsesCorrectly("keyword2", "{null}"); parsesCorrectly("keyword3", "{undefined}"); diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json index ca2b2e175cd..49ecaf53d4c 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json @@ -1,29 +1,35 @@ { "kind": "JSDocOptionalType", "pos": 1, - "end": 7, + "end": 9, "flags": "JSDoc", "type": { - "kind": "ArrayType", + "kind": "ParenthesizedType", "pos": 1, - "end": 6, + "end": 8, "flags": "JSDoc", - "elementType": { + "type": { "kind": "ArrayType", - "pos": 1, - "end": 4, + "pos": 2, + "end": 7, "flags": "JSDoc", "elementType": { - "kind": "TypeReference", - "pos": 1, - "end": 2, + "kind": "ArrayType", + "pos": 2, + "end": 5, "flags": "JSDoc", - "typeName": { - "kind": "Identifier", - "pos": 1, - "end": 2, + "elementType": { + "kind": "TypeReference", + "pos": 2, + "end": 3, "flags": "JSDoc", - "text": "a" + "typeName": { + "kind": "Identifier", + "pos": 2, + "end": 3, + "flags": "JSDoc", + "text": "a" + } } } } diff --git a/tests/baselines/reference/jsdocPrefixPostfixParsing.symbols b/tests/baselines/reference/jsdocPrefixPostfixParsing.symbols new file mode 100644 index 00000000000..c5363a2ba3f --- /dev/null +++ b/tests/baselines/reference/jsdocPrefixPostfixParsing.symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/jsdoc/prefixPostfix.js === +/** + * @param {number![]} x - number[] + * @param {!number[]} y - number[] + * @param {(number[])!} z - number[] + * @param {number?[]} a - (number | null)[] + * @param {?number[]} b - number[] | null + * @param {(number[])?} c - number[] | null + * @param {?...number} d - number[] | null + * @param {...?number} e - (number | null)[] + * @param {...number?} f - (number | null)[] + */ +function f(x, y, z, a, b, c, d, e, f) { +>f : Symbol(f, Decl(prefixPostfix.js, 0, 0)) +>x : Symbol(x, Decl(prefixPostfix.js, 11, 11)) +>y : Symbol(y, Decl(prefixPostfix.js, 11, 13)) +>z : Symbol(z, Decl(prefixPostfix.js, 11, 16)) +>a : Symbol(a, Decl(prefixPostfix.js, 11, 19)) +>b : Symbol(b, Decl(prefixPostfix.js, 11, 22)) +>c : Symbol(c, Decl(prefixPostfix.js, 11, 25)) +>d : Symbol(d, Decl(prefixPostfix.js, 11, 28)) +>e : Symbol(e, Decl(prefixPostfix.js, 11, 31)) +>f : Symbol(f, Decl(prefixPostfix.js, 11, 34)) +} + diff --git a/tests/baselines/reference/jsdocPrefixPostfixParsing.types b/tests/baselines/reference/jsdocPrefixPostfixParsing.types new file mode 100644 index 00000000000..46b15304bfa --- /dev/null +++ b/tests/baselines/reference/jsdocPrefixPostfixParsing.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/jsdoc/prefixPostfix.js === +/** + * @param {number![]} x - number[] + * @param {!number[]} y - number[] + * @param {(number[])!} z - number[] + * @param {number?[]} a - (number | null)[] + * @param {?number[]} b - number[] | null + * @param {(number[])?} c - number[] | null + * @param {?...number} d - number[] | null + * @param {...?number} e - (number | null)[] + * @param {...number?} f - (number | null)[] + */ +function f(x, y, z, a, b, c, d, e, f) { +>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, ...e: (number | null)[], ...f: (number | null)[]) => void +>x : number[] +>y : number[] +>z : number[] +>a : (number | null)[] +>b : number[] | null +>c : number[] | null +>d : number[] | null +>e : (number | null)[] +>f : (number | null)[] +} + diff --git a/tests/cases/conformance/jsdoc/jsdocPrefixPostfixParsing.ts b/tests/cases/conformance/jsdoc/jsdocPrefixPostfixParsing.ts new file mode 100644 index 00000000000..707ae5a02a2 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocPrefixPostfixParsing.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @strictNullChecks: true +// @noImplicitAny: true + +// @Filename: prefixPostfix.js + +/** + * @param {number![]} x - number[] + * @param {!number[]} y - number[] + * @param {(number[])!} z - number[] + * @param {number?[]} a - (number | null)[] + * @param {?number[]} b - number[] | null + * @param {(number[])?} c - number[] | null + * @param {?...number} d - number[] | null + * @param {...?number} e - (number | null)[] + * @param {...number?} f - (number | null)[] + */ +function f(x, y, z, a, b, c, d, e, f) { +} From 172db13306dec523f63423d4ca2cdd7396b19766 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 14 Jul 2017 14:34:32 -0700 Subject: [PATCH 14/22] Parse more types in JSDoc function() syntax Also some cleanup from PR comments --- src/compiler/checker.ts | 4 +++ src/compiler/parser.ts | 6 +++- src/compiler/utilities.ts | 4 --- .../reference/jsdocFunctionType.symbols | 6 ++++ .../reference/jsdocFunctionType.types | 12 ++++++++ .../jsdocTypesInTypeAnnotations.errors.txt | 29 ------------------- tests/baselines/reference/jsweird.symbols | 14 --------- tests/baselines/reference/jsweird.types | 16 ---------- .../conformance/jsdoc/jsdocFunctionType.ts | 3 ++ .../jsdoc/jsdocTypesInTypeAnnotations.ts | 22 -------------- 10 files changed, 30 insertions(+), 86 deletions(-) delete mode 100644 tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt delete mode 100644 tests/baselines/reference/jsweird.symbols delete mode 100644 tests/baselines/reference/jsweird.types delete mode 100644 tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7b1fa6203a6..5d3300ba19b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6866,6 +6866,10 @@ namespace ts { } } + function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode { + return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; + } + function getPrimitiveTypeFromJSDocTypeReference(node: TypeReferenceNode): Type { if (isIdentifier(node.typeName)) { switch (node.typeName.text) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 086c121b173..20c9559a8f4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2199,7 +2199,11 @@ namespace ts { } function isStartOfParameter(): boolean { - return token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token()) || token() === SyntaxKind.AtToken || token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword; + return token() === SyntaxKind.DotDotDotToken || + isIdentifierOrPattern() || + isModifierKind(token()) || + token() === SyntaxKind.AtToken || token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword || + token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral; } function parseParameter(): ParameterDeclaration { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5ae1d835e46..591baaab706 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3302,10 +3302,6 @@ namespace ts { return false; } - export function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode { - return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; - } - /** * Formats an enum value as a string for debugging and debug assertions. */ diff --git a/tests/baselines/reference/jsdocFunctionType.symbols b/tests/baselines/reference/jsdocFunctionType.symbols index 18592bf2cdc..2c13315feb4 100644 --- a/tests/baselines/reference/jsdocFunctionType.symbols +++ b/tests/baselines/reference/jsdocFunctionType.symbols @@ -61,3 +61,9 @@ z.length; >z : Symbol(z, Decl(functions.js, 26, 3)) >length : Symbol(length, Decl(functions.js, 12, 27)) +/** @type {function ("a" | "b"): 1 | 2} */ +var f = function (s) { return s === "a" ? 1 : 2; } +>f : Symbol(f, Decl(functions.js, 30, 3)) +>s : Symbol(s, Decl(functions.js, 30, 18)) +>s : Symbol(s, Decl(functions.js, 30, 18)) + diff --git a/tests/baselines/reference/jsdocFunctionType.types b/tests/baselines/reference/jsdocFunctionType.types index 65f3f929a5c..c954cbfed7c 100644 --- a/tests/baselines/reference/jsdocFunctionType.types +++ b/tests/baselines/reference/jsdocFunctionType.types @@ -68,3 +68,15 @@ z.length; >z : { length: number; } >length : number +/** @type {function ("a" | "b"): 1 | 2} */ +var f = function (s) { return s === "a" ? 1 : 2; } +>f : (arg0: "a" | "b") => 1 | 2 +>function (s) { return s === "a" ? 1 : 2; } : (s: "a" | "b") => 1 | 2 +>s : "a" | "b" +>s === "a" ? 1 : 2 : 1 | 2 +>s === "a" : boolean +>s : "a" | "b" +>"a" : "a" +>1 : 1 +>2 : 2 + diff --git a/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt b/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt deleted file mode 100644 index 72f74609078..00000000000 --- a/tests/baselines/reference/jsdocTypesInTypeAnnotations.errors.txt +++ /dev/null @@ -1,29 +0,0 @@ -tests/cases/conformance/jsdoc/f.js(5,15): error TS2304: Cannot find name 'F'. -tests/cases/conformance/jsdoc/f.js(5,15): error TS8010: 'types' can only be used in a .ts file. -tests/cases/conformance/jsdoc/normal.ts(4,12): error TS7006: Parameter 'c' implicitly has an 'any' type. - - -==== tests/cases/conformance/jsdoc/node.d.ts (0 errors) ==== - declare function require(id: string): any; - declare var module: any, exports: any; - -==== tests/cases/conformance/jsdoc/f.js (2 errors) ==== - var F = function () { - this.x = 1; - }; - - function f(p: F) { p.x; } - ~ -!!! error TS2304: Cannot find name 'F'. - ~ -!!! error TS8010: 'types' can only be used in a .ts file. - -==== tests/cases/conformance/jsdoc/normal.ts (1 errors) ==== - class C { p: number } - - /** @param {C} p */ - function g(c) { return c.p } - ~ -!!! error TS7006: Parameter 'c' implicitly has an 'any' type. - - \ No newline at end of file diff --git a/tests/baselines/reference/jsweird.symbols b/tests/baselines/reference/jsweird.symbols deleted file mode 100644 index 8bed15c4468..00000000000 --- a/tests/baselines/reference/jsweird.symbols +++ /dev/null @@ -1,14 +0,0 @@ -=== tests/cases/conformance/jsdoc/crash.js === -/** - * @param {function(new:number, string)} c crashes with correct syntax too - * @return {number} - */ -function sub4(c) { ->sub4 : Symbol(sub4, Decl(crash.js, 0, 0)) ->c : Symbol(c, Decl(crash.js, 4, 14)) - - return new c('hi') ->c : Symbol(c, Decl(crash.js, 4, 14)) -} - - diff --git a/tests/baselines/reference/jsweird.types b/tests/baselines/reference/jsweird.types deleted file mode 100644 index f77bb369570..00000000000 --- a/tests/baselines/reference/jsweird.types +++ /dev/null @@ -1,16 +0,0 @@ -=== tests/cases/conformance/jsdoc/crash.js === -/** - * @param {function(new:number, string)} c crashes with correct syntax too - * @return {number} - */ -function sub4(c) { ->sub4 : (c: new (arg1: string) => number) => number ->c : new (arg1: string) => number - - return new c('hi') ->new c('hi') : number ->c : new (arg1: string) => number ->'hi' : "hi" -} - - diff --git a/tests/cases/conformance/jsdoc/jsdocFunctionType.ts b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts index 0be247a9494..69a1ebcff87 100644 --- a/tests/cases/conformance/jsdoc/jsdocFunctionType.ts +++ b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts @@ -33,3 +33,6 @@ class C { var y = id2(C); var z = new y(12); z.length; + +/** @type {function ("a" | "b"): 1 | 2} */ +var f = function (s) { return s === "a" ? 1 : 2; } diff --git a/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts b/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts deleted file mode 100644 index b2e7d122199..00000000000 --- a/tests/cases/conformance/jsdoc/jsdocTypesInTypeAnnotations.ts +++ /dev/null @@ -1,22 +0,0 @@ -// @allowJs: true -// @checkJs: true -// @noEmit: true -// @module: commonjs -// @filename: node.d.ts -// @noImplicitAny: true -declare function require(id: string): any; -declare var module: any, exports: any; - -// @filename: f.js -var F = function () { - this.x = 1; -}; - -function f(p: F) { p.x; } - -// @filename: normal.ts -class C { p: number } - -/** @param {C} p */ -function g(c) { return c.p } - From 96d537bc54844fe77868840966809fac39aa7645 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 14 Jul 2017 14:26:13 -0700 Subject: [PATCH 15/22] `readFile` may return undefined --- src/compiler/commandLineParser.ts | 27 +++++++++---------- src/compiler/sys.ts | 6 ++--- src/compiler/types.ts | 4 +-- src/compiler/utilities.ts | 2 +- src/harness/harness.ts | 6 ++--- src/harness/harnessLanguageService.ts | 4 +-- src/harness/projectsRunner.ts | 2 +- src/harness/unittests/moduleResolution.ts | 2 +- src/harness/unittests/session.ts | 2 +- src/harness/virtualFileSystem.ts | 2 +- src/server/lsHost.ts | 2 +- .../typingsInstaller/typingsInstaller.ts | 8 +++--- src/services/jsTyping.ts | 8 +++--- src/services/services.ts | 2 +- src/services/shims.ts | 10 +++---- src/services/types.ts | 2 +- 16 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 4f1210793bf..7f5f7abc821 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -752,7 +752,7 @@ namespace ts { } } - export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { + export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string | undefined): ParsedCommandLine { const options: CompilerOptions = {}; const fileNames: string[] = []; const errors: Diagnostic[] = []; @@ -878,15 +878,9 @@ namespace ts { * Read tsconfig.json file * @param fileName The path to the config file */ - export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } { - let text = ""; - try { - text = readFile(fileName); - } - catch (e) { - return { config: {}, error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) }; - } - return parseConfigFileTextToJson(fileName, text); + export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic } { + const textOrDiagnostic = tryReadFile(fileName, readFile); + return typeof textOrDiagnostic === "string" ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; } /** @@ -906,15 +900,20 @@ namespace ts { * Read tsconfig.json file * @param fileName The path to the config file */ - export function readJsonConfigFile(fileName: string, readFile: (path: string) => string): JsonSourceFile { - let text = ""; + export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): JsonSourceFile { + const textOrDiagnostic = tryReadFile(fileName, readFile); + return typeof textOrDiagnostic === "string" ? parseJsonText(fileName, textOrDiagnostic) : { parseDiagnostics: [textOrDiagnostic] }; + } + + function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic { + let text: string | undefined; try { text = readFile(fileName); } catch (e) { - return { parseDiagnostics: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] }; + return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message); } - return parseJsonText(fileName, text); + return text === undefined ? createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, "File does not exist.") : text; } function commandLineOptionsToMap(options: CommandLineOption[]) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 3e3ff90c00c..62ce272e96c 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -23,7 +23,7 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - readFile(path: string, encoding?: string): string; + readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; /** @@ -97,7 +97,7 @@ namespace ts { directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; - readFile(path: string): string; + readFile(path: string): string | undefined; writeFile(path: string, contents: string): void; getDirectories(path: string): string[]; readDirectory(path: string, extensions?: ReadonlyArray, basePaths?: ReadonlyArray, excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[]; @@ -204,7 +204,7 @@ namespace ts { const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); - function readFile(fileName: string, _encoding?: string): string { + function readFile(fileName: string, _encoding?: string): string | undefined { if (!fileExists(fileName)) { return undefined; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c9309a7d844..2439a0e16cb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2414,7 +2414,7 @@ namespace ts { */ fileExists(path: string): boolean; - readFile(path: string): string; + readFile(path: string): string | undefined; } export interface WriteFileCallback { @@ -3921,7 +3921,7 @@ namespace ts { 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 - readFile(fileName: string): string; + readFile(fileName: string): string | undefined; trace?(s: string): void; directoryExists?(directoryName: string): boolean; realpath?(path: string): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c8751f497a6..e04727f74f4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3921,7 +3921,7 @@ namespace ts { */ export function validateLocaleAndSetLanguage( locale: string, - sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string }, + sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string | undefined }, errors?: Diagnostic[]) { const matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d5218695f09..55a8f3ebb4d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -479,7 +479,7 @@ namespace Harness { getCurrentDirectory(): string; useCaseSensitiveFileNames(): boolean; resolvePath(path: string): string; - readFile(path: string): string; + readFile(path: string): string | undefined; writeFile(path: string, contents: string): void; directoryName(path: string): string; getDirectories(path: string): string[]; @@ -719,7 +719,7 @@ namespace Harness { } }); - export function readFile(file: string) { + export function readFile(file: string): string | undefined { const response = Http.getFileFromServerSync(serverRoot + file); if (response.status === 200) { return response.responseText; @@ -976,7 +976,7 @@ namespace Harness { useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getNewLine: () => newLine, fileExists: fileName => fileMap.has(toPath(fileName)), - readFile: (fileName: string): string => { + readFile(fileName: string): string | undefined { const file = fileMap.get(toPath(fileName)); if (ts.endsWith(fileName, "json")) { // strip comments diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 339138ba30f..156a9e08dce 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -215,7 +215,7 @@ namespace Harness.LanguageService { depth, (p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p)); } - readFile(path: string): string { + readFile(path: string): string | undefined { const snapshot = this.getScriptSnapshot(path); return snapshot.getText(0, snapshot.getLength()); } @@ -619,7 +619,7 @@ namespace Harness.LanguageService { this.writeMessage(message); } - readFile(fileName: string): string { + readFile(fileName: string): string | undefined { if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) { fileName = Harness.Compiler.defaultLibFileName; } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 46c2b42f6a0..7344c432b97 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -289,7 +289,7 @@ class ProjectRunner extends RunnerBase { return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName)); } - function readFile(fileName: string): string { + function readFile(fileName: string): string | undefined { return Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index 3923e4b2755..ffae1b5f4a9 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -56,7 +56,7 @@ namespace ts { else { return { readFile, fileExists: path => map.has(path) }; } - function readFile(path: string): string { + function readFile(path: string): string | undefined { const file = map.get(path); return file && file.content; } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index c6ec2042fae..862ebee4b03 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -9,7 +9,7 @@ namespace ts.server { newLine: "\n", useCaseSensitiveFileNames: true, write(s): void { lastWrittenToHost = s; }, - readFile(): string { return void 0; }, + readFile: () => undefined, writeFile: noop, resolvePath(): string { return void 0; }, fileExists: () => false, diff --git a/src/harness/virtualFileSystem.ts b/src/harness/virtualFileSystem.ts index da7784770df..8accd6f621e 100644 --- a/src/harness/virtualFileSystem.ts +++ b/src/harness/virtualFileSystem.ts @@ -209,7 +209,7 @@ namespace Utils { } } - readFile(path: string): string { + readFile(path: string): string | undefined { const value = this.traversePath(path); if (value && value.isFile()) { return value.content.content; diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 3f1a4e054a8..13b9505a658 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -217,7 +217,7 @@ namespace ts.server { return !this.project.isWatchedMissingFile(path) && this.host.fileExists(file); } - readFile(fileName: string): string { + readFile(fileName: string): string | undefined { return this.host.readFile(fileName); } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 730257d2ccc..b1fddfb4129 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -93,10 +93,10 @@ namespace ts.server.typingsInstaller { abstract readonly typesRegistry: Map; constructor( - readonly installTypingHost: InstallTypingHost, - readonly globalCachePath: string, - readonly safeListPath: Path, - readonly throttleLimit: number, + protected readonly installTypingHost: InstallTypingHost, + private readonly globalCachePath: string, + private readonly safeListPath: Path, + private readonly throttleLimit: number, protected readonly log = nullLog) { if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}'`); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index f31276b6498..670633eb44b 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -9,10 +9,10 @@ namespace ts.JsTyping { export interface TypingResolutionHost { - directoryExists: (path: string) => boolean; - fileExists: (fileName: string) => boolean; - readFile: (path: string, encoding?: string) => string; - readDirectory: (rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, depth?: number) => string[]; + directoryExists(path: string): boolean; + fileExists(fileName: string): boolean; + readFile(path: string, encoding?: string): string | undefined; + readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, depth?: number): string[]; } interface PackageJson { diff --git a/src/services/services.ts b/src/services/services.ts index 5b2cf949d2a..30c6b88b1e2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1149,7 +1149,7 @@ namespace ts { !!hostCache.getEntryByPath(path) : (host.fileExists && host.fileExists(fileName)); }, - readFile: (fileName): string => { + readFile(fileName) { // stub missing host functionality const path = toPath(fileName, currentDirectory, getCanonicalFileName); if (hostCache.containsEntryByPath(path)) { diff --git a/src/services/shims.ts b/src/services/shims.ts index 2ee1853f18f..03965cb5d48 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -69,7 +69,7 @@ namespace ts { getTypeRootsVersion?(): number; readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; - readFile(path: string, encoding?: string): string; + readFile(path: string, encoding?: string): string | undefined; fileExists(path: string): boolean; getModuleResolutionsForFile?(fileName: string): string; @@ -95,7 +95,7 @@ namespace ts { /** * Read arbitary text files on disk, i.e. when resolution procedure needs the content of 'package.json' to determine location of bundled typings for node modules */ - readFile(fileName: string): string; + readFile(fileName: string): string | undefined; realpath?(path: string): string; trace(s: string): void; useCaseSensitiveFileNames?(): boolean; @@ -458,7 +458,7 @@ namespace ts { )); } - public readFile(path: string, encoding?: string): string { + public readFile(path: string, encoding?: string): string | undefined { return this.shimHost.readFile(path, encoding); } @@ -501,7 +501,7 @@ namespace ts { return this.shimHost.fileExists(fileName); } - public readFile(fileName: string): string { + public readFile(fileName: string): string | undefined { return this.shimHost.readFile(fileName); } @@ -1006,7 +1006,7 @@ namespace ts { class CoreServicesShimObject extends ShimBase implements CoreServicesShim { private logPerformance = false; - constructor(factory: ShimFactory, public logger: Logger, private host: CoreServicesShimHostAdapter) { + constructor(factory: ShimFactory, public readonly logger: Logger, private readonly host: CoreServicesShimHostAdapter) { super(factory); } diff --git a/src/services/types.ts b/src/services/types.ts index bfb8a80b769..19d2345d968 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -165,7 +165,7 @@ namespace ts { * Without these methods, only completions for ambient modules will be provided. */ readDirectory?(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; - readFile?(path: string, encoding?: string): string; + readFile?(path: string, encoding?: string): string | undefined; fileExists?(path: string): boolean; /* From 3f60364a64de19a102b0b84f7dc32a48d7a3aace Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 17 Jul 2017 08:29:40 -0700 Subject: [PATCH 16/22] Improve test of jsdoc literal type parsing --- .../reference/jsdocFunctionType.symbols | 9 ++++---- .../reference/jsdocFunctionType.types | 21 ++++++++++--------- .../conformance/jsdoc/jsdocFunctionType.ts | 4 ++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/baselines/reference/jsdocFunctionType.symbols b/tests/baselines/reference/jsdocFunctionType.symbols index 2c13315feb4..0cac1aa4360 100644 --- a/tests/baselines/reference/jsdocFunctionType.symbols +++ b/tests/baselines/reference/jsdocFunctionType.symbols @@ -61,9 +61,10 @@ z.length; >z : Symbol(z, Decl(functions.js, 26, 3)) >length : Symbol(length, Decl(functions.js, 12, 27)) -/** @type {function ("a" | "b"): 1 | 2} */ -var f = function (s) { return s === "a" ? 1 : 2; } +/** @type {function ("a" | "b", 1 | 2): 3 | 4} */ +var f = function (ab, onetwo) { return ab === "a" ? 3 : 4; } >f : Symbol(f, Decl(functions.js, 30, 3)) ->s : Symbol(s, Decl(functions.js, 30, 18)) ->s : Symbol(s, Decl(functions.js, 30, 18)) +>ab : Symbol(ab, Decl(functions.js, 30, 18)) +>onetwo : Symbol(onetwo, Decl(functions.js, 30, 21)) +>ab : Symbol(ab, Decl(functions.js, 30, 18)) diff --git a/tests/baselines/reference/jsdocFunctionType.types b/tests/baselines/reference/jsdocFunctionType.types index c954cbfed7c..0f4c0c2febe 100644 --- a/tests/baselines/reference/jsdocFunctionType.types +++ b/tests/baselines/reference/jsdocFunctionType.types @@ -68,15 +68,16 @@ z.length; >z : { length: number; } >length : number -/** @type {function ("a" | "b"): 1 | 2} */ -var f = function (s) { return s === "a" ? 1 : 2; } ->f : (arg0: "a" | "b") => 1 | 2 ->function (s) { return s === "a" ? 1 : 2; } : (s: "a" | "b") => 1 | 2 ->s : "a" | "b" ->s === "a" ? 1 : 2 : 1 | 2 ->s === "a" : boolean ->s : "a" | "b" +/** @type {function ("a" | "b", 1 | 2): 3 | 4} */ +var f = function (ab, onetwo) { return ab === "a" ? 3 : 4; } +>f : (arg0: "a" | "b", arg1: 1 | 2) => 3 | 4 +>function (ab, onetwo) { return ab === "a" ? 3 : 4; } : (ab: "a" | "b", onetwo: 1 | 2) => 3 | 4 +>ab : "a" | "b" +>onetwo : 1 | 2 +>ab === "a" ? 3 : 4 : 3 | 4 +>ab === "a" : boolean +>ab : "a" | "b" >"a" : "a" ->1 : 1 ->2 : 2 +>3 : 3 +>4 : 4 diff --git a/tests/cases/conformance/jsdoc/jsdocFunctionType.ts b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts index 69a1ebcff87..b124989f96a 100644 --- a/tests/cases/conformance/jsdoc/jsdocFunctionType.ts +++ b/tests/cases/conformance/jsdoc/jsdocFunctionType.ts @@ -34,5 +34,5 @@ var y = id2(C); var z = new y(12); z.length; -/** @type {function ("a" | "b"): 1 | 2} */ -var f = function (s) { return s === "a" ? 1 : 2; } +/** @type {function ("a" | "b", 1 | 2): 3 | 4} */ +var f = function (ab, onetwo) { return ab === "a" ? 3 : 4; } From 555776eb3cb598ee82aaf903f6d083ebbe82bf33 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Jul 2017 12:24:56 -0700 Subject: [PATCH 17/22] Minor cleanups in builder (#17208) * Minor cleanups in builder * Use enumerateInsertsAndDeletes --- src/compiler/core.ts | 6 ++- src/server/builder.ts | 87 +++++++------------------------------- src/server/project.ts | 6 +-- src/server/types.ts | 6 ++- src/server/typingsCache.ts | 2 +- src/server/utilities.ts | 80 +++++++++++++++++++++++++---------- 6 files changed, 85 insertions(+), 102 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9f5872540f4..6da3a5b77aa 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -780,7 +780,7 @@ namespace ts { /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ - export function stableSort(array: ReadonlyArray, comparer: (x: T, y: T) => Comparison = compareValues) { + export function stableSort(array: ReadonlyArray, comparer: Comparer = compareValues) { return array .map((_, i) => i) // create array of indices .sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)) // sort indices by value then position @@ -852,6 +852,8 @@ namespace ts { return result; } + export type Comparer = (a: T, b: T) => Comparison; + /** * Performs a binary search, finding the index at which 'value' occurs in 'array'. * If no such index is found, returns the 2's-complement of first index at which @@ -859,7 +861,7 @@ namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - export function binarySearch(array: ReadonlyArray, value: T, comparer?: (v1: T, v2: T) => number, offset?: number): number { + export function binarySearch(array: ReadonlyArray, value: T, comparer?: Comparer, offset?: number): number { if (!array || array.length === 0) { return -1; } diff --git a/src/server/builder.ts b/src/server/builder.ts index 8fd8fbf1e65..bc86780fbbe 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -203,57 +203,27 @@ namespace ts.server { } class ModuleBuilderFileInfo extends BuilderFileInfo { - references: ModuleBuilderFileInfo[] = []; - referencedBy: ModuleBuilderFileInfo[] = []; + references = createSortedArray(); + readonly referencedBy = createSortedArray(); scriptVersionForReferences: string; - static compareFileInfos(lf: ModuleBuilderFileInfo, rf: ModuleBuilderFileInfo): number { - const l = lf.scriptInfo.fileName; - const r = rf.scriptInfo.fileName; - return (l < r ? -1 : (l > r ? 1 : 0)); - } - - static addToReferenceList(array: ModuleBuilderFileInfo[], fileInfo: ModuleBuilderFileInfo) { - if (array.length === 0) { - array.push(fileInfo); - return; - } - - const insertIndex = binarySearch(array, fileInfo, ModuleBuilderFileInfo.compareFileInfos); - if (insertIndex < 0) { - array.splice(~insertIndex, 0, fileInfo); - } - } - - static removeFromReferenceList(array: ModuleBuilderFileInfo[], fileInfo: ModuleBuilderFileInfo) { - if (!array || array.length === 0) { - return; - } - - if (array[0] === fileInfo) { - array.splice(0, 1); - return; - } - - const removeIndex = binarySearch(array, fileInfo, ModuleBuilderFileInfo.compareFileInfos); - if (removeIndex >= 0) { - array.splice(removeIndex, 1); - } + static compareFileInfos(lf: ModuleBuilderFileInfo, rf: ModuleBuilderFileInfo): Comparison { + return compareStrings(lf.scriptInfo.fileName, rf.scriptInfo.fileName); } addReferencedBy(fileInfo: ModuleBuilderFileInfo): void { - ModuleBuilderFileInfo.addToReferenceList(this.referencedBy, fileInfo); + insertSorted(this.referencedBy, fileInfo, ModuleBuilderFileInfo.compareFileInfos); } removeReferencedBy(fileInfo: ModuleBuilderFileInfo): void { - ModuleBuilderFileInfo.removeFromReferenceList(this.referencedBy, fileInfo); + removeSorted(this.referencedBy, fileInfo, ModuleBuilderFileInfo.compareFileInfos); } removeFileReferences() { for (const reference of this.references) { reference.removeReferencedBy(this); } - this.references = []; + this.references = createSortedArray(); } } @@ -270,16 +240,13 @@ namespace ts.server { super.clear(); } - private getReferencedFileInfos(fileInfo: ModuleBuilderFileInfo): ModuleBuilderFileInfo[] { + private getReferencedFileInfos(fileInfo: ModuleBuilderFileInfo): SortedArray { if (!fileInfo.isExternalModuleOrHasOnlyAmbientExternalModules()) { - return []; + return createSortedArray(); } const referencedFilePaths = this.project.getReferencedFiles(fileInfo.scriptInfo.path); - if (referencedFilePaths.length > 0) { - return map(referencedFilePaths, f => this.getOrCreateFileInfo(f)).sort(ModuleBuilderFileInfo.compareFileInfos); - } - return []; + return toSortedArray(referencedFilePaths.map(f => this.getOrCreateFileInfo(f)), ModuleBuilderFileInfo.compareFileInfos); } protected ensureFileInfoIfInProject(_scriptInfo: ScriptInfo) { @@ -319,39 +286,15 @@ namespace ts.server { const newReferences = this.getReferencedFileInfos(fileInfo); const oldReferences = fileInfo.references; - - let oldIndex = 0; - let newIndex = 0; - while (oldIndex < oldReferences.length && newIndex < newReferences.length) { - const oldReference = oldReferences[oldIndex]; - const newReference = newReferences[newIndex]; - const compare = ModuleBuilderFileInfo.compareFileInfos(oldReference, newReference); - if (compare < 0) { + enumerateInsertsAndDeletes(newReferences, oldReferences, + /*inserted*/ newReference => newReference.addReferencedBy(fileInfo), + /*deleted*/ oldReference => { // New reference is greater then current reference. That means // the current reference doesn't exist anymore after parsing. So delete // references. oldReference.removeReferencedBy(fileInfo); - oldIndex++; - } - else if (compare > 0) { - // A new reference info. Add it. - newReference.addReferencedBy(fileInfo); - newIndex++; - } - else { - // Equal. Go to next - oldIndex++; - newIndex++; - } - } - // Clean old references - for (let i = oldIndex; i < oldReferences.length; i++) { - oldReferences[i].removeReferencedBy(fileInfo); - } - // Update new references - for (let i = newIndex; i < newReferences.length; i++) { - newReferences[i].addReferencedBy(fileInfo); - } + }, + /*compare*/ ModuleBuilderFileInfo.compareFileInfos); fileInfo.references = newReferences; fileInfo.scriptVersionForReferences = fileInfo.scriptInfo.getLatestVersion(); diff --git a/src/server/project.ts b/src/server/project.ts index fab71474851..3b09fc48e85 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -554,7 +554,7 @@ namespace ts.server { for (const sourceFile of this.program.getSourceFiles()) { this.extractUnresolvedImportsFromSourceFile(sourceFile, result); } - this.lastCachedUnresolvedImportsList = toSortedReadonlyArray(result); + this.lastCachedUnresolvedImportsList = toSortedArray(result); } unresolvedImports = this.lastCachedUnresolvedImportsList; @@ -783,7 +783,7 @@ namespace ts.server { // We need to use a set here since the code can contain the same import twice, // but that will only be one dependency. // To avoid invernal conversion, the key of the referencedFiles map must be of type Path - const referencedFiles = createMap(); + const referencedFiles = createMap(); if (sourceFile.imports && sourceFile.imports.length > 0) { const checker: TypeChecker = this.program.getTypeChecker(); for (const importName of sourceFile.imports) { @@ -1057,7 +1057,7 @@ namespace ts.server { } getExternalFiles(): SortedReadonlyArray { - return toSortedReadonlyArray(flatMap(this.plugins, plugin => { + return toSortedArray(flatMap(this.plugins, plugin => { if (typeof plugin.getExternalFiles !== "function") return; try { return plugin.getExternalFiles(this); diff --git a/src/server/types.ts b/src/server/types.ts index 72d6a7c6cfc..07b94fe827e 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -20,8 +20,12 @@ declare namespace ts.server { require?(initialPath: string, moduleName: string): RequireResult; } + export interface SortedArray extends Array { + " __sortedArrayBrand": any; + } + export interface SortedReadonlyArray extends ReadonlyArray { - " __sortedReadonlyArrayBrand": any; + " __sortedArrayBrand": any; } export interface TypingInstallerRequest { diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index a97b12ff7a8..3ef37685da2 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -110,7 +110,7 @@ namespace ts.server { this.perProjectCache.set(projectName, { compilerOptions, typeAcquisition, - typings: toSortedReadonlyArray(newTypings), + typings: toSortedArray(newTypings), unresolvedImports, poisoned: false }); diff --git a/src/server/utilities.ts b/src/server/utilities.ts index a3dcd916172..30146c0a928 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -9,7 +9,7 @@ namespace ts.server { verbose } - export const emptyArray: ReadonlyArray = []; + export const emptyArray: SortedReadonlyArray = createSortedArray(); export interface Logger { close(): void; @@ -190,39 +190,45 @@ namespace ts.server { return `/dev/null/inferredProject${counter}*`; } - export function toSortedReadonlyArray(arr: string[]): SortedReadonlyArray { - arr.sort(); - return arr; + export function createSortedArray(): SortedArray { + return [] as SortedArray; } - export function enumerateInsertsAndDeletes(a: SortedReadonlyArray, b: SortedReadonlyArray, inserted: (item: T) => void, deleted: (item: T) => void, compare?: (a: T, b: T) => Comparison) { + export function toSortedArray(arr: string[]): SortedArray; + export function toSortedArray(arr: T[], comparer: Comparer): SortedArray; + export function toSortedArray(arr: T[], comparer?: Comparer): SortedArray { + arr.sort(comparer); + return arr as SortedArray; + } + + export function enumerateInsertsAndDeletes(newItems: SortedReadonlyArray, oldItems: SortedReadonlyArray, inserted: (newItem: T) => void, deleted: (oldItem: T) => void, compare?: Comparer) { compare = compare || compareValues; - let aIndex = 0; - let bIndex = 0; - const aLen = a.length; - const bLen = b.length; - while (aIndex < aLen && bIndex < bLen) { - const aItem = a[aIndex]; - const bItem = b[bIndex]; - const compareResult = compare(aItem, bItem); + let newIndex = 0; + let oldIndex = 0; + const newLen = newItems.length; + const oldLen = oldItems.length; + while (newIndex < newLen && oldIndex < oldLen) { + const newItem = newItems[newIndex]; + const oldItem = oldItems[oldIndex]; + const compareResult = compare(newItem, oldItem); if (compareResult === Comparison.LessThan) { - inserted(aItem); - aIndex++; + inserted(newItem); + newIndex++; } else if (compareResult === Comparison.GreaterThan) { - deleted(bItem); - bIndex++; + deleted(oldItem); + oldIndex++; } else { - aIndex++; - bIndex++; + newIndex++; + oldIndex++; } } - while (aIndex < aLen) { - inserted(a[aIndex++]); + while (newIndex < newLen) { + inserted(newItems[newIndex++]); } - while (bIndex < bLen) { - deleted(b[bIndex++]); + while (oldIndex < oldLen) { + deleted(oldItems[oldIndex++]); } } @@ -273,4 +279,32 @@ namespace ts.server { } } } + + export function insertSorted(array: SortedArray, insert: T, compare: Comparer): void { + if (array.length === 0) { + array.push(insert); + return; + } + + const insertIndex = binarySearch(array, insert, compare); + if (insertIndex < 0) { + array.splice(~insertIndex, 0, insert); + } + } + + export function removeSorted(array: SortedArray, remove: T, compare: Comparer): void { + if (!array || array.length === 0) { + return; + } + + if (array[0] === remove) { + array.splice(0, 1); + return; + } + + const removeIndex = binarySearch(array, remove, compare); + if (removeIndex >= 0) { + array.splice(removeIndex, 1); + } + } } \ No newline at end of file From 6cf30fbccf03a03aa174ae1ce10dc245c2fe9f55 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Jul 2017 12:29:29 -0700 Subject: [PATCH 18/22] Fix bug in importTracker: `getExportNode` must verify that we are on the LHS of a VariableDeclaration (#17205) --- src/services/importTracker.ts | 7 ++++--- .../findAllRefsExportConstEqualToClass.ts | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsExportConstEqualToClass.ts diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index f17406b16f1..417c16909df 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -453,7 +453,7 @@ namespace ts.FindAllReferences { } } else { - const exportNode = getExportNode(parent); + const exportNode = getExportNode(parent, node); if (exportNode && hasModifier(exportNode, ModifierFlags.Export)) { if (isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. @@ -558,10 +558,11 @@ namespace ts.FindAllReferences { // If a reference is a class expression, the exported node would be its parent. // If a reference is a variable declaration, the exported node would be the variable statement. - function getExportNode(parent: Node): Node | undefined { + function getExportNode(parent: Node, node: Node): Node | undefined { if (parent.kind === SyntaxKind.VariableDeclaration) { const p = parent as ts.VariableDeclaration; - return p.parent.kind === ts.SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined; + return p.name !== node ? undefined : + p.parent.kind === ts.SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined; } else { return parent; diff --git a/tests/cases/fourslash/findAllRefsExportConstEqualToClass.ts b/tests/cases/fourslash/findAllRefsExportConstEqualToClass.ts new file mode 100644 index 00000000000..a5e9bd1cd7d --- /dev/null +++ b/tests/cases/fourslash/findAllRefsExportConstEqualToClass.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: /a.ts +////class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {} +////export const [|{| "isWriteAccess": true, "isDefinition": true |}D|] = [|C|]; + +// @Filename: /b.ts +////import { [|{| "isWriteAccess": true, "isDefinition": true |}D|] } from "./a"; + +const [C0, D0, C1, D1] = test.ranges(); + +verify.singleReferenceGroup("class C", [C0, C1]); + +const d0Group = { definition: "const D: typeof C", ranges: [D0] }; +const d1Group = { definition: "import D", ranges: [D1] }; +verify.referenceGroups(D0, [d0Group, d1Group]); +verify.referenceGroups(D1, [d1Group, d0Group]); From 2ce23909b262fd9723327e0cd0ab86487a97b14f Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 17 Jul 2017 12:38:11 -0700 Subject: [PATCH 19/22] Fix error message --- src/compiler/commandLineParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 7f5f7abc821..ac2b88fbe93 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -913,7 +913,7 @@ namespace ts { catch (e) { return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message); } - return text === undefined ? createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, "File does not exist.") : text; + return text === undefined ? createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, fileName) : text; } function commandLineOptionsToMap(options: CommandLineOption[]) { From 2a219af308aada16b8d314a2b0b98a4bb06f2a9b Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Jul 2017 12:56:16 -0700 Subject: [PATCH 20/22] convertFunctionToEs6Class: Bail if this is not a JavaScript file (#17149) --- src/services/refactors/convertFunctionToEs6Class.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index a570ef1f2b8..2fb67ea98e8 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -12,7 +12,11 @@ namespace ts.refactor { registerRefactor(convertFunctionToES6Class); - function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] { + function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { + if (!isInJavaScriptFile(context.file)) { + return undefined; + } + const start = context.startPosition; const node = getTokenAtPosition(context.file, start, /*includeJsDocComment*/ false); const checker = context.program.getTypeChecker(); From 5d46ca7118b01fe5087793e0af115a61320bd65e Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Jul 2017 12:56:58 -0700 Subject: [PATCH 21/22] Reuse stored types for any[] and Promise instead of creating new ones (#17179) * Reuse stored types for any[] and Promise instead of creating new ones * Don't store anyPromiseType --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d3300ba19b..dafa75372e1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6892,7 +6892,7 @@ namespace ts { return globalFunctionType; case "Array": case "array": - return !node.typeArguments || !node.typeArguments.length ? createArrayType(anyType) : undefined; + return !node.typeArguments || !node.typeArguments.length ? anyArrayType : undefined; case "Promise": case "promise": return !node.typeArguments || !node.typeArguments.length ? createPromiseType(anyType) : undefined; From de9a67f2f3c58656faa96458109d1cc6c5206678 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Jul 2017 14:45:21 -0700 Subject: [PATCH 22/22] Issue template: Recommend to run `tsc` directly (#17246) * Issue template: Recommand to run `tsc` directly * List some common build tools --- issue_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/issue_template.md b/issue_template.md index b5872a0f9fa..e812fe7b74c 100644 --- a/issue_template.md +++ b/issue_template.md @@ -8,7 +8,7 @@ ```ts // A *self-contained* demonstration of the problem follows... - +// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc. ``` **Expected behavior:**