From ca6e2e7bb169b486c0626be52c4d53b03d603f4a Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 24 Oct 2018 11:05:56 -0700 Subject: [PATCH] Fix bug: Ensure JSDoc type range is valid (#27343) (#28008) * Fix bug: Ensure JSDoc type range is valid * Have scanJsDocToken scan keywords (#27162) * Have scanJsDocToken scan keywords * Update API * Add 'no-unnecessary-type-assertion' tslint disables --- src/compiler/commandLineParser.ts | 10 +- src/compiler/parser.ts | 21 ++- src/compiler/scanner.ts | 166 +++++++++--------- src/compiler/types.ts | 79 ++++++++- src/harness/harness.ts | 2 +- src/services/getEditsForFileRename.ts | 2 +- ...ocComments.parsesCorrectly.@link tags.json | 4 +- ...cComments.parsesCorrectly.templateTag.json | 4 +- ...Comments.parsesCorrectly.templateTag2.json | 4 +- ...Comments.parsesCorrectly.templateTag3.json | 4 +- ...Comments.parsesCorrectly.templateTag4.json | 4 +- ...Comments.parsesCorrectly.templateTag5.json | 4 +- ...Comments.parsesCorrectly.templateTag6.json | 4 +- .../reference/api/tsserverlibrary.d.ts | 3 +- tests/baselines/reference/api/typescript.d.ts | 3 +- .../jsdocUnexpectedCharacter.symbols | 5 + .../reference/jsdocUnexpectedCharacter.types | 6 + .../reference/paramTagWrapping.errors.txt | 8 +- .../compiler/jsdocUnexpectedCharacter.ts | 7 + tests/cases/fourslash/editJsdocType.ts | 13 ++ 20 files changed, 234 insertions(+), 119 deletions(-) create mode 100644 tests/baselines/reference/jsdocUnexpectedCharacter.symbols create mode 100644 tests/baselines/reference/jsdocUnexpectedCharacter.types create mode 100644 tests/cases/compiler/jsdocUnexpectedCharacter.ts create mode 100644 tests/cases/fourslash/editJsdocType.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index dcf024f77a5ec..ee1b83f7350e9 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1005,7 +1005,7 @@ namespace ts { i++; break; case "list": - const result = parseListTypeOption(opt, args[i], errors); + const result = parseListTypeOption(opt, args[i], errors); // tslint:disable-line no-unnecessary-type-assertion options[opt.name] = result || []; if (result) { i++; @@ -1654,7 +1654,7 @@ namespace ts { return undefined; } else if (optionDefinition.type === "list") { - return getCustomTypeMapOfCommandLineOption((optionDefinition).element); + return getCustomTypeMapOfCommandLineOption((optionDefinition).element); // tslint:disable-line no-unnecessary-type-assertion } else { return (optionDefinition).type; @@ -1718,7 +1718,7 @@ namespace ts { case "object": return {}; default: - return (option as CommandLineOptionOfCustomType).type.keys().next().value; + return (option as CommandLineOptionOfCustomType).type.keys().next().value; // tslint:disable-line no-unnecessary-type-assertion } } @@ -2305,7 +2305,7 @@ namespace ts { function normalizeOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue { if (isNullOrUndefined(value)) return undefined; if (option.type === "list") { - const listOption = option; + const listOption = option; // tslint:disable-line no-unnecessary-type-assertion if (listOption.element.isFilePath || !isString(listOption.element.type)) { return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => !!v); } @@ -2690,7 +2690,7 @@ namespace ts { case "boolean": return typeof value === "boolean" ? value : ""; case "list": - const elementType = (option as CommandLineOptionOfListType).element; + const elementType = (option as CommandLineOptionOfListType).element; // tslint:disable-line no-unnecessary-type-assertion return isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : ""; default: return forEachEntry(option.type, (optionEnumValue, optionStringValue) => { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 33829fccb7a7d..d2ae81ccad651 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6308,7 +6308,7 @@ namespace ts { // Parses out a JSDoc type expression. export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression { - const result = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); + const result = createNode(SyntaxKind.JSDocTypeExpression); const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken); result.type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); @@ -6517,7 +6517,7 @@ namespace ts { } } - function skipWhitespaceOrAsterisk(next: () => void): void { + function skipWhitespaceOrAsterisk(): void { if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range @@ -6532,7 +6532,7 @@ namespace ts { else if (token() === SyntaxKind.AsteriskToken) { precedingLineBreak = false; } - next(); + nextJSDocToken(); } } @@ -6542,9 +6542,8 @@ namespace ts { atToken.end = scanner.getTextPos(); nextJSDocToken(); - // Use 'nextToken' instead of 'nextJsDocToken' so we can parse a type like 'number' in `@enum number` - const tagName = parseJSDocIdentifierName(/*message*/ undefined, nextToken); - skipWhitespaceOrAsterisk(nextToken); + const tagName = parseJSDocIdentifierName(/*message*/ undefined); + skipWhitespaceOrAsterisk(); let tag: JSDocTag | undefined; switch (tagName.escapedText) { @@ -6688,7 +6687,7 @@ namespace ts { } function tryParseTypeExpression(): JSDocTypeExpression | undefined { - skipWhitespaceOrAsterisk(nextJSDocToken); + skipWhitespaceOrAsterisk(); return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; } @@ -6728,7 +6727,7 @@ namespace ts { function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; - skipWhitespaceOrAsterisk(nextJSDocToken); + skipWhitespaceOrAsterisk(); const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); skipWhitespace(); @@ -6862,7 +6861,7 @@ namespace ts { function parseTypedefTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocTypedefTag { const typeExpression = tryParseTypeExpression(); - skipWhitespaceOrAsterisk(nextJSDocToken); + skipWhitespaceOrAsterisk(); const typedefTag = createNode(SyntaxKind.JSDocTypedefTag, atToken.pos); typedefTag.atToken = atToken; @@ -7115,7 +7114,7 @@ namespace ts { return entity; } - function parseJSDocIdentifierName(message?: DiagnosticMessage, next: () => void = nextJSDocToken): Identifier { + function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier { if (!tokenIsIdentifierOrKeyword(token())) { return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); } @@ -7126,7 +7125,7 @@ namespace ts { result.escapedText = escapeLeadingUnderscores(scanner.getTokenText()); finishNode(result, end); - next(); + nextJSDocToken(); return result; } } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index b339220c38e9d..1a5c4336b6334 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -60,81 +60,87 @@ namespace ts { tryScan(callback: () => T): T; } - const textToToken = createMapFromTemplate({ - "abstract": SyntaxKind.AbstractKeyword, - "any": SyntaxKind.AnyKeyword, - "as": SyntaxKind.AsKeyword, - "boolean": SyntaxKind.BooleanKeyword, - "break": SyntaxKind.BreakKeyword, - "case": SyntaxKind.CaseKeyword, - "catch": SyntaxKind.CatchKeyword, - "class": SyntaxKind.ClassKeyword, - "continue": SyntaxKind.ContinueKeyword, - "const": SyntaxKind.ConstKeyword, - "constructor": SyntaxKind.ConstructorKeyword, - "debugger": SyntaxKind.DebuggerKeyword, - "declare": SyntaxKind.DeclareKeyword, - "default": SyntaxKind.DefaultKeyword, - "delete": SyntaxKind.DeleteKeyword, - "do": SyntaxKind.DoKeyword, - "else": SyntaxKind.ElseKeyword, - "enum": SyntaxKind.EnumKeyword, - "export": SyntaxKind.ExportKeyword, - "extends": SyntaxKind.ExtendsKeyword, - "false": SyntaxKind.FalseKeyword, - "finally": SyntaxKind.FinallyKeyword, - "for": SyntaxKind.ForKeyword, - "from": SyntaxKind.FromKeyword, - "function": SyntaxKind.FunctionKeyword, - "get": SyntaxKind.GetKeyword, - "if": SyntaxKind.IfKeyword, - "implements": SyntaxKind.ImplementsKeyword, - "import": SyntaxKind.ImportKeyword, - "in": SyntaxKind.InKeyword, - "infer": SyntaxKind.InferKeyword, - "instanceof": SyntaxKind.InstanceOfKeyword, - "interface": SyntaxKind.InterfaceKeyword, - "is": SyntaxKind.IsKeyword, - "keyof": SyntaxKind.KeyOfKeyword, - "let": SyntaxKind.LetKeyword, - "module": SyntaxKind.ModuleKeyword, - "namespace": SyntaxKind.NamespaceKeyword, - "never": SyntaxKind.NeverKeyword, - "new": SyntaxKind.NewKeyword, - "null": SyntaxKind.NullKeyword, - "number": SyntaxKind.NumberKeyword, - "object": SyntaxKind.ObjectKeyword, - "package": SyntaxKind.PackageKeyword, - "private": SyntaxKind.PrivateKeyword, - "protected": SyntaxKind.ProtectedKeyword, - "public": SyntaxKind.PublicKeyword, - "readonly": SyntaxKind.ReadonlyKeyword, - "require": SyntaxKind.RequireKeyword, - "global": SyntaxKind.GlobalKeyword, - "return": SyntaxKind.ReturnKeyword, - "set": SyntaxKind.SetKeyword, - "static": SyntaxKind.StaticKeyword, - "string": SyntaxKind.StringKeyword, - "super": SyntaxKind.SuperKeyword, - "switch": SyntaxKind.SwitchKeyword, - "symbol": SyntaxKind.SymbolKeyword, - "this": SyntaxKind.ThisKeyword, - "throw": SyntaxKind.ThrowKeyword, - "true": SyntaxKind.TrueKeyword, - "try": SyntaxKind.TryKeyword, - "type": SyntaxKind.TypeKeyword, - "typeof": SyntaxKind.TypeOfKeyword, - "undefined": SyntaxKind.UndefinedKeyword, - "unique": SyntaxKind.UniqueKeyword, - "unknown": SyntaxKind.UnknownKeyword, - "var": SyntaxKind.VarKeyword, - "void": SyntaxKind.VoidKeyword, - "while": SyntaxKind.WhileKeyword, - "with": SyntaxKind.WithKeyword, - "yield": SyntaxKind.YieldKeyword, - "async": SyntaxKind.AsyncKeyword, - "await": SyntaxKind.AwaitKeyword, - "of": SyntaxKind.OfKeyword, + const textToKeywordObj: MapLike = { + abstract: SyntaxKind.AbstractKeyword, + any: SyntaxKind.AnyKeyword, + as: SyntaxKind.AsKeyword, + boolean: SyntaxKind.BooleanKeyword, + break: SyntaxKind.BreakKeyword, + case: SyntaxKind.CaseKeyword, + catch: SyntaxKind.CatchKeyword, + class: SyntaxKind.ClassKeyword, + continue: SyntaxKind.ContinueKeyword, + const: SyntaxKind.ConstKeyword, + ["" + "constructor"]: SyntaxKind.ConstructorKeyword, + debugger: SyntaxKind.DebuggerKeyword, + declare: SyntaxKind.DeclareKeyword, + default: SyntaxKind.DefaultKeyword, + delete: SyntaxKind.DeleteKeyword, + do: SyntaxKind.DoKeyword, + else: SyntaxKind.ElseKeyword, + enum: SyntaxKind.EnumKeyword, + export: SyntaxKind.ExportKeyword, + extends: SyntaxKind.ExtendsKeyword, + false: SyntaxKind.FalseKeyword, + finally: SyntaxKind.FinallyKeyword, + for: SyntaxKind.ForKeyword, + from: SyntaxKind.FromKeyword, + function: SyntaxKind.FunctionKeyword, + get: SyntaxKind.GetKeyword, + if: SyntaxKind.IfKeyword, + implements: SyntaxKind.ImplementsKeyword, + import: SyntaxKind.ImportKeyword, + in: SyntaxKind.InKeyword, + infer: SyntaxKind.InferKeyword, + instanceof: SyntaxKind.InstanceOfKeyword, + interface: SyntaxKind.InterfaceKeyword, + is: SyntaxKind.IsKeyword, + keyof: SyntaxKind.KeyOfKeyword, + let: SyntaxKind.LetKeyword, + module: SyntaxKind.ModuleKeyword, + namespace: SyntaxKind.NamespaceKeyword, + never: SyntaxKind.NeverKeyword, + new: SyntaxKind.NewKeyword, + null: SyntaxKind.NullKeyword, + number: SyntaxKind.NumberKeyword, + object: SyntaxKind.ObjectKeyword, + package: SyntaxKind.PackageKeyword, + private: SyntaxKind.PrivateKeyword, + protected: SyntaxKind.ProtectedKeyword, + public: SyntaxKind.PublicKeyword, + readonly: SyntaxKind.ReadonlyKeyword, + require: SyntaxKind.RequireKeyword, + global: SyntaxKind.GlobalKeyword, + return: SyntaxKind.ReturnKeyword, + set: SyntaxKind.SetKeyword, + static: SyntaxKind.StaticKeyword, + string: SyntaxKind.StringKeyword, + super: SyntaxKind.SuperKeyword, + switch: SyntaxKind.SwitchKeyword, + symbol: SyntaxKind.SymbolKeyword, + this: SyntaxKind.ThisKeyword, + throw: SyntaxKind.ThrowKeyword, + true: SyntaxKind.TrueKeyword, + try: SyntaxKind.TryKeyword, + type: SyntaxKind.TypeKeyword, + typeof: SyntaxKind.TypeOfKeyword, + undefined: SyntaxKind.UndefinedKeyword, + unique: SyntaxKind.UniqueKeyword, + unknown: SyntaxKind.UnknownKeyword, + var: SyntaxKind.VarKeyword, + void: SyntaxKind.VoidKeyword, + while: SyntaxKind.WhileKeyword, + with: SyntaxKind.WithKeyword, + yield: SyntaxKind.YieldKeyword, + async: SyntaxKind.AsyncKeyword, + await: SyntaxKind.AwaitKeyword, + of: SyntaxKind.OfKeyword, + }; + + const textToKeyword = createMapFromTemplate(textToKeywordObj); + + const textToToken = createMapFromTemplate({ + ...textToKeywordObj, "{": SyntaxKind.OpenBraceToken, "}": SyntaxKind.CloseBraceToken, "(": SyntaxKind.OpenParenToken, @@ -1288,15 +1294,15 @@ namespace ts { return result; } - function getIdentifierToken(): SyntaxKind { + function getIdentifierToken(): SyntaxKind.Identifier | KeywordSyntaxKind { // Reserved words are between 2 and 11 characters long and start with a lowercase letter const len = tokenValue.length; if (len >= 2 && len <= 11) { const ch = tokenValue.charCodeAt(0); if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) { - token = textToToken.get(tokenValue)!; - if (token !== undefined) { - return token; + const keyword = textToKeyword.get(tokenValue); + if (keyword !== undefined) { + return token = keyword; } } } @@ -2016,7 +2022,7 @@ namespace ts { pos++; } tokenValue = text.substring(tokenPos, pos); - return token = SyntaxKind.Identifier; + return token = getIdentifierToken(); } else { return token = SyntaxKind.Unknown; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f0eeb932059cc..9a41aebb50164 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -24,7 +24,84 @@ namespace ts { | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral - | SyntaxKind.Unknown; + | SyntaxKind.Unknown + | KeywordSyntaxKind; + + export type KeywordSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AnyKeyword + | SyntaxKind.AsKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.BreakKeyword + | SyntaxKind.CaseKeyword + | SyntaxKind.CatchKeyword + | SyntaxKind.ClassKeyword + | SyntaxKind.ContinueKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.ConstructorKeyword + | SyntaxKind.DebuggerKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.DeleteKeyword + | SyntaxKind.DoKeyword + | SyntaxKind.ElseKeyword + | SyntaxKind.EnumKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.ExtendsKeyword + | SyntaxKind.FalseKeyword + | SyntaxKind.FinallyKeyword + | SyntaxKind.ForKeyword + | SyntaxKind.FromKeyword + | SyntaxKind.FunctionKeyword + | SyntaxKind.GetKeyword + | SyntaxKind.IfKeyword + | SyntaxKind.ImplementsKeyword + | SyntaxKind.ImportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.InferKeyword + | SyntaxKind.InstanceOfKeyword + | SyntaxKind.InterfaceKeyword + | SyntaxKind.IsKeyword + | SyntaxKind.KeyOfKeyword + | SyntaxKind.LetKeyword + | SyntaxKind.ModuleKeyword + | SyntaxKind.NamespaceKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NewKeyword + | SyntaxKind.NullKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.PackageKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.RequireKeyword + | SyntaxKind.GlobalKeyword + | SyntaxKind.ReturnKeyword + | SyntaxKind.SetKeyword + | SyntaxKind.StaticKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SuperKeyword + | SyntaxKind.SwitchKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.ThisKeyword + | SyntaxKind.ThrowKeyword + | SyntaxKind.TrueKeyword + | SyntaxKind.TryKeyword + | SyntaxKind.TypeKeyword + | SyntaxKind.TypeOfKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UniqueKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VarKeyword + | SyntaxKind.VoidKeyword + | SyntaxKind.WhileKeyword + | SyntaxKind.WithKeyword + | SyntaxKind.YieldKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.AwaitKeyword + | SyntaxKind.OfKeyword; export type JsxTokenSyntaxKind = | SyntaxKind.LessThanSlashToken diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 23ee10d741285..4358ce64d8d5b 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1159,7 +1159,7 @@ namespace Harness { } // If not a primitive, the possible types are specified in what is effectively a map of options. case "list": - return ts.parseListTypeOption(option, value, errors); + return ts.parseListTypeOption(option, value, errors); // tslint:disable-line no-unnecessary-type-assertion default: return ts.parseCustomTypeOption(option, value, errors); } diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index a18fab4766fad..6f7a26a0e785c 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -72,7 +72,7 @@ namespace ts { case "compilerOptions": forEachProperty(property.initializer, (property, propertyName) => { const option = getOptionFromName(propertyName); - if (option && (option.isFilePath || option.type === "list" && (option as CommandLineOptionOfListType).element.isFilePath)) { + if (option && (option.isFilePath || option.type === "list" && (option as CommandLineOptionOfListType).element.isFilePath)) { // tslint:disable-line no-unnecessary-type-assertion updatePaths(property); } else if (propertyName === "paths") { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json index 2ea60ed3e426a..c694d24037107 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocTag", "pos": 63, - "end": 67, + "end": 68, "atToken": { "kind": "AtToken", "pos": 63, @@ -22,7 +22,7 @@ }, "length": 1, "pos": 63, - "end": 67 + "end": 68 }, "comment": "{@link first link}\nInside {@link link text} thing" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json index cd453fce8c5aa..4d16157d91d91 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -31,7 +31,7 @@ } }, "length": 1, - "pos": 17, + "pos": 18, "end": 19 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json index bfc59a6a3bbd7..3f5f2a54ec7c4 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 17, + "pos": 18, "end": 21 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json index e6ad0c0d0f310..193c5c0eb0141 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 17, + "pos": 18, "end": 22 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json index e6ad0c0d0f310..193c5c0eb0141 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 17, + "pos": 18, "end": 22 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json index f09001e97e29b..fca64bcb43044 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 17, + "pos": 18, "end": 23 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json index 566a03b96ea36..90158499b175e 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 17, + "pos": 18, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 17, + "pos": 18, "end": 24 }, "comment": "Description of type parameters." diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 661983877dc4e..f495b882ca735 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -69,7 +69,8 @@ declare namespace ts { pos: number; end: number; } - type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown; + type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown | KeywordSyntaxKind; + type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; enum SyntaxKind { Unknown = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 82a60701b76b4..ecb745dd84d6a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -69,7 +69,8 @@ declare namespace ts { pos: number; end: number; } - type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown; + type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown | KeywordSyntaxKind; + type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; enum SyntaxKind { Unknown = 0, diff --git a/tests/baselines/reference/jsdocUnexpectedCharacter.symbols b/tests/baselines/reference/jsdocUnexpectedCharacter.symbols new file mode 100644 index 0000000000000..5a4379ebb8c17 --- /dev/null +++ b/tests/baselines/reference/jsdocUnexpectedCharacter.symbols @@ -0,0 +1,5 @@ +=== /a.js === +/** @x # */ +var UI = {}; +>UI : Symbol(UI, Decl(a.js, 1, 3)) + diff --git a/tests/baselines/reference/jsdocUnexpectedCharacter.types b/tests/baselines/reference/jsdocUnexpectedCharacter.types new file mode 100644 index 0000000000000..897e534894de3 --- /dev/null +++ b/tests/baselines/reference/jsdocUnexpectedCharacter.types @@ -0,0 +1,6 @@ +=== /a.js === +/** @x # */ +var UI = {}; +>UI : {} +>{} : {} + diff --git a/tests/baselines/reference/paramTagWrapping.errors.txt b/tests/baselines/reference/paramTagWrapping.errors.txt index 3263443dbac41..48100f0e7468c 100644 --- a/tests/baselines/reference/paramTagWrapping.errors.txt +++ b/tests/baselines/reference/paramTagWrapping.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/jsdoc/bad.js(2,10): error TS1003: Identifier expected. -tests/cases/conformance/jsdoc/bad.js(2,10): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. +tests/cases/conformance/jsdoc/bad.js(2,11): error TS1003: Identifier expected. +tests/cases/conformance/jsdoc/bad.js(2,11): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. tests/cases/conformance/jsdoc/bad.js(5,4): error TS1003: Identifier expected. tests/cases/conformance/jsdoc/bad.js(5,4): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. tests/cases/conformance/jsdoc/bad.js(6,19): error TS1003: Identifier expected. @@ -27,9 +27,9 @@ tests/cases/conformance/jsdoc/bad.js(9,20): error TS7006: Parameter 'z' implicit ==== tests/cases/conformance/jsdoc/bad.js (9 errors) ==== /** * @param * - + !!! error TS1003: Identifier expected. - + !!! error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. * {number} x Arg x. * @param {number} diff --git a/tests/cases/compiler/jsdocUnexpectedCharacter.ts b/tests/cases/compiler/jsdocUnexpectedCharacter.ts new file mode 100644 index 0000000000000..ef7a2f78c99a2 --- /dev/null +++ b/tests/cases/compiler/jsdocUnexpectedCharacter.ts @@ -0,0 +1,7 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /a.js +/** @x # */ +var UI = {}; diff --git a/tests/cases/fourslash/editJsdocType.ts b/tests/cases/fourslash/editJsdocType.ts new file mode 100644 index 0000000000000..4e5de6c5daf4b --- /dev/null +++ b/tests/cases/fourslash/editJsdocType.ts @@ -0,0 +1,13 @@ +/// + +// @allowJs: true +// @noLib: true + +// @Filename: /a.js +/////** @type/**/ */ +////const x = 0; + +goTo.marker(); +verify.quickInfoIs(""); +edit.insert(" "); +verify.quickInfoIs("");