From f5eb61a57f6bb51eb9e10c30735ae31c47d6fbb8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 16:13:40 -0700 Subject: [PATCH 01/96] Add support for parsing JSDoc types. --- src/compiler/parser.ts | 349 ++++++++++++++++++++++++++++++++++++++++- src/compiler/types.ts | 76 +++++++++ 2 files changed, 417 insertions(+), 8 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bde4cec3f3ff0..11ba8d80f88a2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1432,14 +1432,7 @@ module ts { function createNode(kind: SyntaxKind, pos?: number): Node { nodeCount++; - let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); - if (!(pos >= 0)) { - pos = scanner.getStartPos(); - } - - node.pos = pos; - node.end = pos; - return node; + return createNodeAtPosition(scanner, kind, pos); } function finishNode(node: T): T { @@ -5390,4 +5383,344 @@ module ts { export function isAssignmentOperator(token: SyntaxKind): boolean { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } + + // Parses out a JSDoc type expression. The starting position should be right at the open + // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. + function parseJSDocTypeExpression(content: string, start: number): JSDocType { + let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content); + scanner.setTextPos(start); + + // Prime the first token for us to start processing. + let token = nextToken(); + let error = false; + + parseExpected(SyntaxKind.OpenBraceToken); + let type = parseJSDocType(); + parseExpected(SyntaxKind.CloseBraceToken); + + return error ? undefined : type; + + function nextToken(): SyntaxKind { + return token = scanner.scan(); + } + + function createNode(kind: SyntaxKind, pos?: number): Node { + return createNodeAtPosition(scanner, kind, pos); + } + + function parseExpected(kind: SyntaxKind): void { + if (token === kind) { + nextToken(); + } + else { + error = true; + } + } + + function isIdentifier() { + if (token === SyntaxKind.Identifier) { + return true; + } + + return token > SyntaxKind.LastReservedWord && token <= SyntaxKind.LastKeyword; + } + + function isIdentifierOrKeyword() { + if (token === SyntaxKind.Identifier) { + return true; + } + + return token >= SyntaxKind.FirstKeyword && token <= SyntaxKind.LastKeyword; + } + + function parseJSDocType(): JSDocType { + let type = parseJSDocType(); + if (type && token === SyntaxKind.EqualsToken) { + return parseJSDocOptionalType(type); + } + + return type; + } + + function parseJSDocTypeCore(): JSDocType { + switch (token) { + case SyntaxKind.AsteriskToken: + return parseJSDocAllType(); + case SyntaxKind.QuestionToken: + return parseJSDocUnknownOrNullableType(); + case SyntaxKind.OpenParenToken: + return parseJSDocUnionType(); + case SyntaxKind.ExclamationToken: + return parseJSDocNonNullableType(); + case SyntaxKind.OpenBraceToken: + return parseJSDocRecordType(); + case SyntaxKind.FunctionKeyword: + return parseJSDocFunctionType(); + case SyntaxKind.DotDotDotToken: + return parseJSDocVariadicType(); + case SyntaxKind.NewKeyword: + return parseJSDocConstructorType(); + case SyntaxKind.ThisKeyword: + return parseJSDocThisType(); + } + + if (isIdentifier()) { + return parseJSDocTypeReference(); + } + + error = true; + return undefined; + } + + function parseJSDocThisType(): JSDocThisType { + let result = createNode(SyntaxKind.JSDocThisType); + nextToken(); + parseExpected(SyntaxKind.ColonToken); + result.type = parseJSDocType(); + return finishNode(result); + } + + function parseJSDocConstructorType(): JSDocConstructorType { + let result = createNode(SyntaxKind.JSDocConstructorType); + nextToken(); + parseExpected(SyntaxKind.ColonToken); + result.type = parseJSDocType(); + return finishNode(result); + } + + function parseJSDocVariadicType(): JSDocVariadicType { + let result = createNode(SyntaxKind.JSDocVariadicType); + nextToken(); + result.type = parseJSDocType(); + return finishNode(result); + } + + function parseJSDocFunctionType(): JSDocFunctionType { + let result = createNode(SyntaxKind.JSDocFunctionType); + nextToken(); + parseExpected(SyntaxKind.OpenParenToken); + + let parameters = >[]; + parameters.pos = scanner.getStartPos(); + + while (!error && token !== SyntaxKind.CloseParenToken && token !== SyntaxKind.EndOfFileToken) { + if (parameters.length > 0) { + parseExpected(SyntaxKind.CommaToken); + } + + parameters.push(parseJSDocType()); + } + + parameters.end = scanner.getStartPos(); + parseExpected(SyntaxKind.CloseParenToken); + + if (token === SyntaxKind.ColonToken) { + nextToken(); + result.type = parseJSDocType(); + } + + return finishNode(result); + } + + function parseJSDocOptionalType(type: JSDocType): JSDocOptionalType { + let result = createNode(SyntaxKind.JSDocOptionalType, type.pos); + nextToken(); + return finishNode(result); + } + + function parseJSDocTypeReference(): JSDocTypeReference { + let result = createNode(SyntaxKind.JSDocTypeReference); + result.name = parseIdentifier(); + + while (!error && result.name && token === SyntaxKind.DotToken) { + if (isIdentifierOrKeyword()) { + result.name = parseQualifiedName(result.name); + } + else if (token === SyntaxKind.LessThanToken) { + result.typeArguments = parseTypeArguments(); + break; + } + else { + error = true; + return undefined; + } + } + + return finishNode(result); + } + + function parseTypeArguments() { + // Move past the < + nextToken(); + + let typeArguments = >[]; + typeArguments.pos = scanner.getStartPos(); + + typeArguments.push(parseJSDocType()); + while (!error && token === SyntaxKind.CommaToken) { + nextToken(); + typeArguments.push(parseJSDocType()); + } + + typeArguments.end = scanner.getStartPos(); + + parseExpected(SyntaxKind.GreaterThanToken); + + return typeArguments; + } + + function parseQualifiedName(left: EntityName): QualifiedName { + // Move past the . + nextToken(); + + let result = createNode(SyntaxKind.QualifiedName, left.pos); + result.left = left; + result.right = parseIdentifierOrKeyword(); + + return finishNode(result); + } + + function parseIdentifierOrKeyword(): Identifier { + return parseIdentifierHelper(isIdentifierOrKeyword()); + } + + function parseIdentifier(): Identifier { + return parseIdentifierHelper(isIdentifier()); + } + + function parseIdentifierHelper(isIdentifier: boolean): Identifier { + if (isIdentifier) { + let result = createNode(SyntaxKind.Identifier); + result.text = scanner.getTokenValue(); + nextToken(); + return finishNode(result); + } + else { + error = true; + return undefined; + } + } + + function parseJSDocRecordType(): JSDocRecordType { + let result = createNode(SyntaxKind.JSDocRecordType); + nextToken(); + + let members = >[]; + members.pos = scanner.getStartPos(); + + while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken && !error) { + members.push(parseJSDocMember()); + } + + members.end = scanner.getStartPos(); + + parseExpected(SyntaxKind.CloseBraceToken); + return finishNode(result); + } + + function parseJSDocMember(): JSDocMember { + let result = createNode(SyntaxKind.JSDocMember); + result.name = parsePropertyName(); + + if (token === SyntaxKind.ColonToken) { + nextToken(); + result.type = parseJSDocType(); + } + + return finishNode(result); + } + + function parsePropertyName(): Identifier | LiteralExpression { + if (token === SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { + let result = createNode(token); + nextToken(); + return finishNode(result); + } + else { + error = true; + return undefined; + } + } + + function parseJSDocNonNullableType(): JSDocNonNullableType { + let result = createNode(SyntaxKind.JSDocNonNullableType); + nextToken(); + result.type = parseJSDocType(); + return finishNode(result); + } + + function parseJSDocUnionType(): JSDocUnionType { + let result = createNode(SyntaxKind.JSDocUnionType); + nextToken(); + + let types = >[]; + types.pos = scanner.getStartPos(); + + types.push(parseJSDocType()); + while (token === SyntaxKind.BarToken) { + nextToken(); + types.push(parseJSDocType()); + } + + types.end = scanner.getStartPos(); + + parseExpected(SyntaxKind.CloseParenToken); + + return finishNode(result); + } + + function parseJSDocAllType(): JSDocAllType { + let result = createNode(SyntaxKind.JSDocAllType); + nextToken(); + return finishNode(result); + } + + function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { + let 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) { + + let result = createNode(SyntaxKind.JSDocUnknownType, pos); + return finishNode(result); + } + else { + let result = createNode(SyntaxKind.JSDocNullableType, pos); + result.type = parseJSDocType(); + return finishNode(result); + } + } + + function finishNode(node: T): T { + node.end = scanner.getStartPos(); + return node; + } + } + + function createNodeAtPosition(scanner: Scanner, kind: SyntaxKind, pos?: number): Node { + let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); + if (!(pos >= 0)) { + pos = scanner.getStartPos(); + } + + node.pos = pos; + node.end = pos; + return node; + } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7477705796396..5f4c82b83ccec 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -269,6 +269,23 @@ module ts { // Top-level nodes SourceFile, + // JSDoc nodes. + // The * type. + JSDocAllType, + // The ? type. + JSDocUnknownType, + JSDocUnionType, + JSDocNullableType, + JSDocNonNullableType, + JSDocRecordType, + JSDocMember, + JSDocTypeReference, + JSDocOptionalType, + JSDocFunctionType, + JSDocVariadicType, + JSDocConstructorType, + JSDocThisType, + // Synthesized list SyntaxList, // Enum value count @@ -987,6 +1004,65 @@ module ts { hasTrailingNewLine?: boolean; } + export interface JSDocType extends Node { + _jsDocTypeBrand: any; + } + + export interface JSDocAllType extends JSDocType { + _JSDocAllTypeBrand: any; + } + + export interface JSDocUnknownType extends JSDocType { + _JSDocUnknownTypeBrand: any; + } + + export interface JSDocUnionType extends JSDocType { + types: NodeArray; + } + + export interface JSDocNonNullableType extends JSDocType { + type: JSDocType; + } + + export interface JSDocNullableType extends JSDocType { + type: JSDocType; + } + + export interface JSDocRecordType extends JSDocType { + member: NodeArray; + } + + export interface JSDocTypeReference extends JSDocType { + name: EntityName; + typeArguments: NodeArray + } + + export interface JSDocOptionalType extends JSDocType { + type: JSDocType; + } + + export interface JSDocFunctionType extends JSDocType { + parameters: NodeArray; + type: JSDocType; + } + + export interface JSDocVariadicType extends JSDocType { + type: JSDocType; + } + + export interface JSDocConstructorType extends JSDocType { + type: JSDocType; + } + + export interface JSDocThisType extends JSDocType { + type: JSDocType; + } + + export interface JSDocMember extends Node { + name: Identifier | LiteralExpression, + type?: JSDocType + } + // Source files are declarations when they are external modules. export interface SourceFile extends Declaration { statements: NodeArray; From 6b51c5474fa04a38aa3682389d08c4417ad7fba0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 16:43:14 -0700 Subject: [PATCH 02/96] Tests for jsdoc comment parsing. --- Jakefile | 1 + src/compiler/parser.ts | 4 +-- src/harness/harness.ts | 2 +- tests/cases/unittests/jsDocParsing.ts | 46 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/cases/unittests/jsDocParsing.ts diff --git a/Jakefile b/Jakefile index 2efd973a0218e..feafbbfdc532a 100644 --- a/Jakefile +++ b/Jakefile @@ -141,6 +141,7 @@ var harnessSources = [ return path.join(harnessDirectory, f); }).concat([ "incrementalParser.ts", + "jsDocParsing.ts", "services/colorization.ts", "services/documentRegistry.ts", "services/preProcessFile.ts", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 11ba8d80f88a2..ad1e9161e27b0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5386,7 +5386,7 @@ module ts { // Parses out a JSDoc type expression. The starting position should be right at the open // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. - function parseJSDocTypeExpression(content: string, start: number): JSDocType { + export function parseJSDocTypeExpression(content: string, start: number): JSDocType { let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content); scanner.setTextPos(start); @@ -5434,7 +5434,7 @@ module ts { } function parseJSDocType(): JSDocType { - let type = parseJSDocType(); + let type = parseJSDocTypeCore(); if (type && token === SyntaxKind.EqualsToken) { return parseJSDocOptionalType(type); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 784d8312d6901..0ef4fde11fede 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -191,7 +191,7 @@ module Utils { }; } - export function sourceFileToJSON(file: ts.SourceFile): string { + export function sourceFileToJSON(file: ts.Node): string { return JSON.stringify(file,(k, v) => { return isNodeOrArray(v) ? serializeNode(v) : v; }, " "); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts new file mode 100644 index 0000000000000..3dd5476aa61dc --- /dev/null +++ b/tests/cases/unittests/jsDocParsing.ts @@ -0,0 +1,46 @@ +/// +/// +/// + +module ts { + function parsesCorrectly(content: string, expected: string) { + let type = ts.parseJSDocTypeExpression(content, 0); + let result = Utils.sourceFileToJSON(type); + assert.equal(result, expected); + } + + function parsesIncorrectly(content: string) { + let type = ts.parseJSDocTypeExpression(content, 0); + assert.equal(type, undefined); + } + + describe("JSDocParsing", () => { + describe("parseCorrectly", () => { + it("parsesQuestionCorrectly", () => { + parsesCorrectly("{?}", + `{ + "kind": "JSDocUnknownType", + "containsParseError": false, + "pos": 1, + "end": 2 +}`); + }); + + it("parsesAsteriskCorrectly", () => { + parsesCorrectly("{*}", + `{ + "kind": "JSDocAllType", + "containsParseError": false, + "pos": 1, + "end": 2 +}`); + }); + }); + + describe("parsesIncorrectly", () => { + it("emptyType", () => { + parsesIncorrectly("{}"); + }); + }); + }); +} \ No newline at end of file From 4dba6493faaf70067dfe6f3d3128a361cc3554f5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 16:46:27 -0700 Subject: [PATCH 03/96] Additional test. --- tests/cases/unittests/jsDocParsing.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 3dd5476aa61dc..d2179b8892d41 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -33,6 +33,28 @@ module ts { "containsParseError": false, "pos": 1, "end": 2 +}`); + }); + it("parsesNullableTypeCorrectly", () => { + parsesCorrectly("{?number}", + `{ + "kind": "JSDocNullableType", + "containsParseError": false, + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "containsParseError": false, + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "containsParseError": false, + "pos": 2, + "end": 8, + "text": "number" + } + } }`); }); }); From a63e260d6ca37ae3bc11a80ef512a6beac313db4 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:01:26 -0700 Subject: [PATCH 04/96] Additional jsdoc tests. Simplify test output. --- src/compiler/parser.ts | 4 +++ src/harness/harness.ts | 4 ++- tests/cases/unittests/jsDocParsing.ts | 49 ++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ad1e9161e27b0..ed672828b1b3e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5512,6 +5512,8 @@ module ts { } parameters.end = scanner.getStartPos(); + + result.parameters = parameters; parseExpected(SyntaxKind.CloseParenToken); if (token === SyntaxKind.ColonToken) { @@ -5613,6 +5615,7 @@ module ts { } members.end = scanner.getStartPos(); + result.member = members; parseExpected(SyntaxKind.CloseBraceToken); return finishNode(result); @@ -5663,6 +5666,7 @@ module ts { } types.end = scanner.getStartPos(); + result.types = types; parseExpected(SyntaxKind.CloseParenToken); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 0ef4fde11fede..d0984f27280a2 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -229,7 +229,9 @@ module Utils { function serializeNode(n: ts.Node): any { var o: any = { kind: getKindName(n.kind) }; - o.containsParseError = ts.containsParseError(n); + if (ts.containsParseError(n)) { + o.containsParseError = true; + } ts.forEach(Object.getOwnPropertyNames(n), propertyName => { switch (propertyName) { diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index d2179b8892d41..658535ccb9371 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -16,45 +16,78 @@ module ts { describe("JSDocParsing", () => { describe("parseCorrectly", () => { - it("parsesQuestionCorrectly", () => { + it("unknownType", () => { parsesCorrectly("{?}", `{ "kind": "JSDocUnknownType", - "containsParseError": false, "pos": 1, "end": 2 }`); }); - it("parsesAsteriskCorrectly", () => { + it("allType", () => { parsesCorrectly("{*}", `{ "kind": "JSDocAllType", - "containsParseError": false, "pos": 1, "end": 2 }`); }); - it("parsesNullableTypeCorrectly", () => { + + it("nullableType", () => { parsesCorrectly("{?number}", `{ "kind": "JSDocNullableType", - "containsParseError": false, "pos": 1, "end": 8, "type": { "kind": "JSDocTypeReference", - "containsParseError": false, "pos": 2, "end": 8, "name": { "kind": "Identifier", - "containsParseError": false, "pos": 2, "end": 8, "text": "number" } } +}`) + }); + + it("unionType", () => { + debugger; + parsesCorrectly("{(number|string)}", +`{ + "kind": "JSDocUnionType", + "pos": 1, + "end": 16, + "types": { + "0": { + "kind": "JSDocTypeReference", + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 8, + "text": "number" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 9, + "end": 15, + "name": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "string" + } + }, + "length": 2, + "pos": 2, + "end": 15 + } }`); }); }); From 803a8e26aa2218cd5b18d2a3a0d49234e815d807 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:02:48 -0700 Subject: [PATCH 05/96] Add test for non-nullable type. --- tests/cases/unittests/jsDocParsing.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 658535ccb9371..ee3ef8ad254b6 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -54,6 +54,27 @@ module ts { }`) }); + it("nonNullableType", () => { + parsesCorrectly("{!number}", + `{ + "kind": "JSDocNonNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 8, + "text": "number" + } + } +}`) + }); + + it("unionType", () => { debugger; parsesCorrectly("{(number|string)}", From b5dfb0dc6a1d27e83f90f340c4dbffb51ea5d38e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:10:34 -0700 Subject: [PATCH 06/96] Add tests for record types. --- src/compiler/parser.ts | 10 +- tests/cases/unittests/jsDocParsing.ts | 252 ++++++++++++++++++++++++++ 2 files changed, 259 insertions(+), 3 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ed672828b1b3e..7af368f39a812 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5503,7 +5503,7 @@ module ts { let parameters = >[]; parameters.pos = scanner.getStartPos(); - while (!error && token !== SyntaxKind.CloseParenToken && token !== SyntaxKind.EndOfFileToken) { + while (!error && token !== SyntaxKind.CloseParenToken) { if (parameters.length > 0) { parseExpected(SyntaxKind.CommaToken); } @@ -5610,7 +5610,11 @@ module ts { let members = >[]; members.pos = scanner.getStartPos(); - while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken && !error) { + while (!error && token !== SyntaxKind.CloseBraceToken) { + if (members.length > 0) { + parseExpected(SyntaxKind.CommaToken); + } + members.push(parseJSDocMember()); } @@ -5660,7 +5664,7 @@ module ts { types.pos = scanner.getStartPos(); types.push(parseJSDocType()); - while (token === SyntaxKind.BarToken) { + while (!error && token === SyntaxKind.BarToken) { nextToken(); types.push(parseJSDocType()); } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index ee3ef8ad254b6..6907803a0450c 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -74,6 +74,258 @@ module ts { }`) }); + it("recordType1", () => { + parsesCorrectly("{{}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 3, + "member": { + "length": 0, + "pos": 2, + "end": 2 + } +}`) + }); + + it("recordType2", () => { + parsesCorrectly("{{foo}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 6, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + } + }, + "length": 1, + "pos": 2, + "end": 5 + } +}`) + }); + + it("recordType3", () => { + parsesCorrectly("{{foo: number}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 14, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + }, + "type": { + "kind": "JSDocTypeReference", + "pos": 6, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 13, + "text": "number" + } + } + }, + "length": 1, + "pos": 2, + "end": 13 + } +}`) + }); + + it("recordType4", () => { + parsesCorrectly("{{foo, bar}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 11, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + } + }, + "1": { + "kind": "JSDocMember", + "pos": 6, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 10 + } + }, + "length": 2, + "pos": 2, + "end": 10 + } +}`) + }); + + it("recordType5", () => { + parsesCorrectly("{{foo: number, bar}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 19, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + }, + "type": { + "kind": "JSDocTypeReference", + "pos": 6, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 13, + "text": "number" + } + } + }, + "1": { + "kind": "JSDocMember", + "pos": 14, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 14, + "end": 18 + } + }, + "length": 2, + "pos": 2, + "end": 18 + } +}`) + }); + + it("recordType6", () => { + parsesCorrectly("{{foo, bar: number}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 19, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + } + }, + "1": { + "kind": "JSDocMember", + "pos": 6, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 10 + }, + "type": { + "kind": "JSDocTypeReference", + "pos": 11, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 11, + "end": 18, + "text": "number" + } + } + }, + "length": 2, + "pos": 2, + "end": 18 + } +}`) + }); + + it("recordType7", () => { + parsesCorrectly("{{foo: number, bar: number}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 27, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5 + }, + "type": { + "kind": "JSDocTypeReference", + "pos": 6, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 13, + "text": "number" + } + } + }, + "1": { + "kind": "JSDocMember", + "pos": 14, + "end": 26, + "name": { + "kind": "Identifier", + "pos": 14, + "end": 18 + }, + "type": { + "kind": "JSDocTypeReference", + "pos": 19, + "end": 26, + "name": { + "kind": "Identifier", + "pos": 19, + "end": 26, + "text": "number" + } + } + }, + "length": 2, + "pos": 2, + "end": 26 + } +}`) + }); it("unionType", () => { debugger; From 80803cad28e0dfadbc54f72000b487fac586c977 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:26:18 -0700 Subject: [PATCH 07/96] tests for parsing generics. --- src/compiler/parser.ts | 69 +++---- tests/cases/unittests/jsDocParsing.ts | 262 +++++++++++++++++++++++++- 2 files changed, 297 insertions(+), 34 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7af368f39a812..6b1bab9354a2f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5434,42 +5434,45 @@ module ts { } function parseJSDocType(): JSDocType { - let type = parseJSDocTypeCore(); - if (type && token === SyntaxKind.EqualsToken) { - return parseJSDocOptionalType(type); - } + if (!error) { + let type = parseJSDocTypeCore(); + if (type && token === SyntaxKind.EqualsToken) { + return parseJSDocOptionalType(type); + } - return type; + return type; + } } function parseJSDocTypeCore(): JSDocType { - switch (token) { - case SyntaxKind.AsteriskToken: - return parseJSDocAllType(); - case SyntaxKind.QuestionToken: - return parseJSDocUnknownOrNullableType(); - case SyntaxKind.OpenParenToken: - return parseJSDocUnionType(); - case SyntaxKind.ExclamationToken: - return parseJSDocNonNullableType(); - case SyntaxKind.OpenBraceToken: - return parseJSDocRecordType(); - case SyntaxKind.FunctionKeyword: - return parseJSDocFunctionType(); - case SyntaxKind.DotDotDotToken: - return parseJSDocVariadicType(); - case SyntaxKind.NewKeyword: - return parseJSDocConstructorType(); - case SyntaxKind.ThisKeyword: - return parseJSDocThisType(); - } + if (!error) { + switch (token) { + case SyntaxKind.AsteriskToken: + return parseJSDocAllType(); + case SyntaxKind.QuestionToken: + return parseJSDocUnknownOrNullableType(); + case SyntaxKind.OpenParenToken: + return parseJSDocUnionType(); + case SyntaxKind.ExclamationToken: + return parseJSDocNonNullableType(); + case SyntaxKind.OpenBraceToken: + return parseJSDocRecordType(); + case SyntaxKind.FunctionKeyword: + return parseJSDocFunctionType(); + case SyntaxKind.DotDotDotToken: + return parseJSDocVariadicType(); + case SyntaxKind.NewKeyword: + return parseJSDocConstructorType(); + case SyntaxKind.ThisKeyword: + return parseJSDocThisType(); + } - if (isIdentifier()) { - return parseJSDocTypeReference(); - } + if (isIdentifier()) { + return parseJSDocTypeReference(); + } - error = true; - return undefined; + error = true; + } } function parseJSDocThisType(): JSDocThisType { @@ -5527,6 +5530,7 @@ module ts { function parseJSDocOptionalType(type: JSDocType): JSDocOptionalType { let result = createNode(SyntaxKind.JSDocOptionalType, type.pos); nextToken(); + result.type = type; return finishNode(result); } @@ -5535,6 +5539,8 @@ module ts { result.name = parseIdentifier(); while (!error && result.name && token === SyntaxKind.DotToken) { + nextToken(); + if (isIdentifierOrKeyword()) { result.name = parseQualifiedName(result.name); } @@ -5572,9 +5578,6 @@ module ts { } function parseQualifiedName(left: EntityName): QualifiedName { - // Move past the . - nextToken(); - let result = createNode(SyntaxKind.QualifiedName, left.pos); result.left = left; result.right = parseIdentifierOrKeyword(); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 6907803a0450c..0ecfa73e9f539 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -328,7 +328,6 @@ module ts { }); it("unionType", () => { - debugger; parsesCorrectly("{(number|string)}", `{ "kind": "JSDocUnionType", @@ -361,6 +360,267 @@ module ts { "pos": 2, "end": 15 } +}`); + }); + + it("functionType1", () => { + parsesCorrectly("{function(string, boolean)}", + `{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 26, + "parameters": { + "0": { + "kind": "JSDocTypeReference", + "pos": 10, + "end": 16, + "name": { + "kind": "Identifier", + "pos": 10, + "end": 16, + "text": "string" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 25, + "name": { + "kind": "Identifier", + "pos": 17, + "end": 25, + "text": "boolean" + } + }, + "length": 2, + "pos": 10, + "end": 25 + } +}`); + }); + + it("functionReturnType1", () => { + parsesCorrectly("{function(string, boolean)}", + `{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 26, + "parameters": { + "0": { + "kind": "JSDocTypeReference", + "pos": 10, + "end": 16, + "name": { + "kind": "Identifier", + "pos": 10, + "end": 16, + "text": "string" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 25, + "name": { + "kind": "Identifier", + "pos": 17, + "end": 25, + "text": "boolean" + } + }, + "length": 2, + "pos": 10, + "end": 25 + } +}`); + }); + + it("thisType1", () => { + parsesCorrectly("{this:a.b}", + `{ + "kind": "JSDocThisType", + "pos": 1, + "end": 9, + "type": { + "kind": "JSDocTypeReference", + "pos": 6, + "end": 9, + "name": { + "kind": "FirstNode", + "pos": 6, + "end": 9, + "left": { + "kind": "Identifier", + "pos": 6, + "end": 7, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 8, + "end": 9, + "text": "b" + } + } + } +}`); + }); + + it("newType1", () => { + parsesCorrectly("{new:a.b}", + `{ + "kind": "JSDocConstructorType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 5, + "end": 8, + "name": { + "kind": "FirstNode", + "pos": 5, + "end": 8, + "left": { + "kind": "Identifier", + "pos": 5, + "end": 6, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 7, + "end": 8, + "text": "b" + } + } + } +}`); + }); + + it("variadicType", () => { + parsesCorrectly("{...number}", + `{ + "kind": "JSDocVariadicType", + "pos": 1, + "end": 10, + "type": { + "kind": "JSDocTypeReference", + "pos": 4, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 4, + "end": 10, + "text": "number" + } + } +}`); + }); + + it("optionalType", () => { + parsesCorrectly("{number=}", + `{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 7, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 7, + "text": "number" + } + } +}`); + }); + + it("optionalNullable", () => { + parsesCorrectly("{?=}", + `{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 3, + "type": { + "kind": "JSDocUnknownType", + "pos": 1, + "end": 2 + } +}`); + }); + + it("typeReference1", () => { + parsesCorrectly("{a.}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 11, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "typeArguments": { + "0": { + "kind": "JSDocTypeReference", + "pos": 4, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 4, + "end": 10, + "text": "number" + } + }, + "length": 1, + "pos": 4, + "end": 10 + } +}`); + }); + + it("typeReference2", () => { + parsesCorrectly("{a.}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "typeArguments": { + "0": { + "kind": "JSDocTypeReference", + "pos": 4, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 4, + "end": 10, + "text": "number" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 11, + "end": 17, + "name": { + "kind": "Identifier", + "pos": 11, + "end": 17, + "text": "string" + } + }, + "length": 2, + "pos": 4, + "end": 17 + } }`); }); }); From bc1659aa0d5dbbf6dcc6c2468cf0ff841a09c043 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:42:54 -0700 Subject: [PATCH 08/96] Add negative tests for parsing jsdoc types. --- src/compiler/parser.ts | 3 +- tests/cases/unittests/jsDocParsing.ts | 179 ++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 11 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6b1bab9354a2f..7ca6cd2ce7ff9 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5641,8 +5641,9 @@ module ts { } function parsePropertyName(): Identifier | LiteralExpression { - if (token === SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { + if (isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { let result = createNode(token); + result.text = scanner.getTokenValue(); nextToken(); return finishNode(result); } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 0ecfa73e9f539..18cde770181f6 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -102,7 +102,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" } }, "length": 1, @@ -126,7 +127,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" }, "type": { "kind": "JSDocTypeReference", @@ -161,7 +163,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" } }, "1": { @@ -171,7 +174,8 @@ module ts { "name": { "kind": "Identifier", "pos": 6, - "end": 10 + "end": 10, + "text": "bar" } }, "length": 2, @@ -195,7 +199,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" }, "type": { "kind": "JSDocTypeReference", @@ -216,7 +221,8 @@ module ts { "name": { "kind": "Identifier", "pos": 14, - "end": 18 + "end": 18, + "text": "bar" } }, "length": 2, @@ -240,7 +246,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" } }, "1": { @@ -250,7 +257,8 @@ module ts { "name": { "kind": "Identifier", "pos": 6, - "end": 10 + "end": 10, + "text": "bar" }, "type": { "kind": "JSDocTypeReference", @@ -285,7 +293,8 @@ module ts { "name": { "kind": "Identifier", "pos": 2, - "end": 5 + "end": 5, + "text": "foo" }, "type": { "kind": "JSDocTypeReference", @@ -306,7 +315,8 @@ module ts { "name": { "kind": "Identifier", "pos": 14, - "end": 18 + "end": 18, + "text": "bar" }, "type": { "kind": "JSDocTypeReference", @@ -327,6 +337,31 @@ module ts { }`) }); + it("recordType8", () => { + parsesCorrectly("{{function}}", + `{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 11, + "member": { + "0": { + "kind": "JSDocMember", + "pos": 2, + "end": 10, + "name": { + "kind": "FunctionKeyword", + "pos": 2, + "end": 10, + "text": "function" + } + }, + "length": 1, + "pos": 2, + "end": 10 + } +}`) + }); + it("unionType", () => { parsesCorrectly("{(number|string)}", `{ @@ -364,6 +399,20 @@ module ts { }); it("functionType1", () => { + parsesCorrectly("{function()}", + `{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 11, + "parameters": { + "length": 0, + "pos": 10, + "end": 10 + } +}`); + }); + + it("functionType2", () => { parsesCorrectly("{function(string, boolean)}", `{ "kind": "JSDocFunctionType", @@ -621,6 +670,32 @@ module ts { "pos": 4, "end": 17 } +}`); + }); + + it("typeReference3", () => { + parsesCorrectly("{a.function}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 11, + "name": { + "kind": "FirstNode", + "pos": 1, + "end": 11, + "left": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 3, + "end": 11, + "text": "function" + } + } }`); }); }); @@ -629,6 +704,90 @@ module ts { it("emptyType", () => { parsesIncorrectly("{}"); }); + + it("trailingCommaInRecordType", () => { + parsesIncorrectly("{{a,}}"); + }); + + it("unionTypeWithTrailingBar", () => { + parsesIncorrectly("{(a|)}"); + }); + + it("unionTypeWithoutTypes", () => { + parsesIncorrectly("{()}"); + }); + + it("nullableTypeWithoutType", () => { + parsesIncorrectly("{!}"); + }); + + it("functionTypeWithTrailingComma", () => { + parsesIncorrectly("{function(a,)}"); + }); + + it("keyword", () => { + parsesIncorrectly("{var}"); + }); + + it("thisWithoutType", () => { + parsesIncorrectly("{this:}"); + }); + + it("newWithoutType", () => { + parsesIncorrectly("{new:}"); + }); + + it("variadicWithoutType", () => { + parsesIncorrectly("{...}"); + }); + + it("optionalWithoutType", () => { + parsesIncorrectly("{=}"); + }); + + it("allWithType", () => { + parsesIncorrectly("{*foo}"); + }); + + it("emptyTypeArguments", () => { + parsesIncorrectly("{a.<>}"); + }); + + it("typeArgumentsWithTrailingComma", () => { + parsesIncorrectly("{a.}"); + }); + + it("arrayType", () => { + parsesIncorrectly("{a[]}"); + }); + + it("tsFunctionType", () => { + parsesIncorrectly("{() => string}"); + }); + + it("tsConstructoType", () => { + parsesIncorrectly("{new () => string}"); + }); + + it("tupleType", () => { + parsesIncorrectly("{[number,string]}"); + }); + + it("typeOfType", () => { + parsesIncorrectly("{typeof M}"); + }); + + it("namedParameter", () => { + parsesIncorrectly("{function(a: number)}"); + }); + + it("callSignatureInRecordType", () => { + parsesIncorrectly("{{(): number}}"); + }); + + it("methodInRecordType", () => { + parsesIncorrectly("{{foo(): number}}"); + }); }); }); } \ No newline at end of file From 57e9c945829d5d613a49c8c55bfb400841b0ed84 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:44:21 -0700 Subject: [PATCH 09/96] Add additional negative test. --- tests/cases/unittests/jsDocParsing.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 18cde770181f6..470e5f94bbd8b 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -749,6 +749,10 @@ module ts { parsesIncorrectly("{*foo}"); }); + it("typeArgumentsNotFollowingDot", () => { + parsesIncorrectly("{a<>}"); + }); + it("emptyTypeArguments", () => { parsesIncorrectly("{a.<>}"); }); From c8876b02791272fd070ce245e6782e7192fe908b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 6 Apr 2015 17:48:37 -0700 Subject: [PATCH 10/96] Simplify code. --- src/compiler/parser.ts | 53 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7ca6cd2ce7ff9..41da6bbda1e64 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5445,34 +5445,33 @@ module ts { } function parseJSDocTypeCore(): JSDocType { - if (!error) { - switch (token) { - case SyntaxKind.AsteriskToken: - return parseJSDocAllType(); - case SyntaxKind.QuestionToken: - return parseJSDocUnknownOrNullableType(); - case SyntaxKind.OpenParenToken: - return parseJSDocUnionType(); - case SyntaxKind.ExclamationToken: - return parseJSDocNonNullableType(); - case SyntaxKind.OpenBraceToken: - return parseJSDocRecordType(); - case SyntaxKind.FunctionKeyword: - return parseJSDocFunctionType(); - case SyntaxKind.DotDotDotToken: - return parseJSDocVariadicType(); - case SyntaxKind.NewKeyword: - return parseJSDocConstructorType(); - case SyntaxKind.ThisKeyword: - return parseJSDocThisType(); - } - - if (isIdentifier()) { - return parseJSDocTypeReference(); - } + switch (token) { + case SyntaxKind.AsteriskToken: + return parseJSDocAllType(); + case SyntaxKind.QuestionToken: + return parseJSDocUnknownOrNullableType(); + case SyntaxKind.OpenParenToken: + return parseJSDocUnionType(); + case SyntaxKind.ExclamationToken: + return parseJSDocNonNullableType(); + case SyntaxKind.OpenBraceToken: + return parseJSDocRecordType(); + case SyntaxKind.FunctionKeyword: + return parseJSDocFunctionType(); + case SyntaxKind.DotDotDotToken: + return parseJSDocVariadicType(); + case SyntaxKind.NewKeyword: + return parseJSDocConstructorType(); + case SyntaxKind.ThisKeyword: + return parseJSDocThisType(); + } - error = true; + if (isIdentifier()) { + return parseJSDocTypeReference(); } + + error = true; + return undefined; } function parseJSDocThisType(): JSDocThisType { @@ -5538,7 +5537,7 @@ module ts { let result = createNode(SyntaxKind.JSDocTypeReference); result.name = parseIdentifier(); - while (!error && result.name && token === SyntaxKind.DotToken) { + while (!error && token === SyntaxKind.DotToken) { nextToken(); if (isIdentifierOrKeyword()) { From 8ba61f63158667aa8151c89e6e036305abe2fe86 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 11:27:42 -0700 Subject: [PATCH 11/96] Mark if nodes were parsed from a javascript file or not. --- src/compiler/parser.ts | 4 +++- src/compiler/types.ts | 10 ++++++++-- src/compiler/utilities.ts | 4 ++++ src/services/services.ts | 4 ---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 41da6bbda1e64..34daee2ec3715 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1074,7 +1074,9 @@ module ts { // Note: it should not be necessary to save/restore these flags during speculative/lookahead // parsing. These context flags are naturally stored and restored through normal recursive // descent parsing and unwinding. - let contextFlags: ParserContextFlags = 0; + let contextFlags = isJavaScript(fileName) + ? ParserContextFlags.JavaScriptFile + : ParserContextFlags.None; // Whether or not we've had a parse error since creating the last AST node. If we have // encountered an error, it will be stored on the next AST node we create. Parse errors diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5f4c82b83ccec..460a406f4a520 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -338,6 +338,8 @@ module ts { } export const enum ParserContextFlags { + None = 0, + // Set if this node was parsed in strict mode. Used for grammar error checks, as well as // checking if the node can be reused in incremental settings. StrictMode = 1 << 0, @@ -359,6 +361,10 @@ module ts { // error. ThisNodeHasError = 1 << 5, + // This node was parsed in a JavaScript file and can be processed differently. For example + // its type can be specified usign a JSDoc comment. + JavaScriptFile = 1 << 6, + // Context flags set directly by the parser. ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError, @@ -366,10 +372,10 @@ module ts { // Used during incremental parsing to determine if this node or any of its children had an // error. Computed only once and then cached. - ThisNodeOrAnySubNodesHasError = 1 << 6, + ThisNodeOrAnySubNodesHasError = 1 << 7, // Used to know if we've computed data from children and cached it in this node. - HasAggregatedChildData = 1 << 7 + HasAggregatedChildData = 1 << 8 } export const enum RelationComparisonResult { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e3efd12de0a0c..41f6db9bab255 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1815,4 +1815,8 @@ module ts { export function getLocalSymbolForExportDefault(symbol: Symbol) { return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined; } + + export function isJavaScript(fileName: string) { + return fileExtensionIs(fileName, ".js"); + } } diff --git a/src/services/services.ts b/src/services/services.ts index 12ea84eafc17a..43f3da55f96a5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2433,10 +2433,6 @@ module ts { return program.getSyntacticDiagnostics(getValidSourceFile(fileName)); } - function isJavaScript(fileName: string) { - return fileExtensionIs(fileName, ".js"); - } - /** * getSemanticDiagnostiscs return array of Diagnostics. If '-d' is not enabled, only report semantic errors * If '-d' enabled, report both semantic and emitter errors From 50bb49978829c89df72afa91c9ff0951ea1ba365 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 12:19:38 -0700 Subject: [PATCH 12/96] Support passing a start/length when creating a scanner. --- src/compiler/parser.ts | 5 +- src/compiler/scanner.ts | 111 ++++++++++++++++++++------------------ src/compiler/utilities.ts | 3 +- 3 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 34daee2ec3715..a46fdd163e0a6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5388,9 +5388,8 @@ module ts { // Parses out a JSDoc type expression. The starting position should be right at the open // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. - export function parseJSDocTypeExpression(content: string, start: number): JSDocType { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content); - scanner.setTextPos(start); + export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocType { + let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content, /*onError:*/ undefined, start, length); // Prime the first token for us to start processing. let token = nextToken(); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 3a208698c25f4..46e470f1d357d 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -23,7 +23,11 @@ module ts { reScanSlashToken(): SyntaxKind; reScanTemplateToken(): SyntaxKind; scan(): SyntaxKind; - setText(text: string): void; + + // Sets the text for the scanner to scan. An optional subrange starting point and length + // can be provided to have the scanner only scan a portion of the text. + setText(text: string, start?: number, length?: number): void; + setTextPos(textPos: number): void; // Invokes the provided callback then unconditionally restores the scanner to the state it // was in immediately prior to invoking the callback. The result of invoking the callback @@ -587,9 +591,10 @@ module ts { ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); } - export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback): Scanner { + // Creates a scanner over a (possibly unspecified) range of a piece of text. + export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner { let pos: number; // Current position (end position of text of current token) - let len: number; // Length of text + let end: number; // end of text let startPos: number; // Start position of whitespace before current token let tokenPos: number; // Start position of text of current token let token: SyntaxKind; @@ -598,6 +603,30 @@ module ts { let hasExtendedUnicodeEscape: boolean; let tokenIsUnterminated: boolean; + setText(text, start, length); + + return { + getStartPos: () => startPos, + getTextPos: () => pos, + getToken: () => token, + getTokenPos: () => tokenPos, + getTokenText: () => text.substring(tokenPos, pos), + getTokenValue: () => tokenValue, + hasExtendedUnicodeEscape: () => hasExtendedUnicodeEscape, + hasPrecedingLineBreak: () => precedingLineBreak, + isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, + isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord, + isUnterminated: () => tokenIsUnterminated, + reScanGreaterToken, + reScanSlashToken, + reScanTemplateToken, + scan, + setText, + setTextPos, + tryScan, + lookAhead, + }; + function error(message: DiagnosticMessage, length?: number): void { if (onError) { onError(message, length || 0); @@ -694,7 +723,7 @@ module ts { let result = ""; let start = pos; while (true) { - if (pos >= len) { + if (pos >= end) { result += text.substring(start, pos); tokenIsUnterminated = true; error(Diagnostics.Unterminated_string_literal); @@ -736,7 +765,7 @@ module ts { let resultingToken: SyntaxKind; while (true) { - if (pos >= len) { + if (pos >= end) { contents += text.substring(start, pos); tokenIsUnterminated = true; error(Diagnostics.Unterminated_template_literal); @@ -755,7 +784,7 @@ module ts { } // '${' - if (currChar === CharacterCodes.$ && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) { + if (currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) { contents += text.substring(start, pos); pos += 2; resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle; @@ -776,7 +805,7 @@ module ts { contents += text.substring(start, pos); pos++; - if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) { + if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } @@ -796,7 +825,7 @@ module ts { function scanEscapeSequence(): string { pos++; - if (pos >= len) { + if (pos >= end) { error(Diagnostics.Unexpected_end_of_text); return ""; } @@ -822,7 +851,7 @@ module ts { return "\""; case CharacterCodes.u: // '\u{DDDDDDDD}' - if (pos < len && text.charCodeAt(pos) === CharacterCodes.openBrace) { + if (pos < end && text.charCodeAt(pos) === CharacterCodes.openBrace) { hasExtendedUnicodeEscape = true; pos++; return scanExtendedUnicodeEscape(); @@ -838,7 +867,7 @@ module ts { // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence), // the line terminator is interpreted to be "the empty code unit sequence". case CharacterCodes.carriageReturn: - if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) { + if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } // fall through @@ -877,7 +906,7 @@ module ts { isInvalidExtendedEscape = true; } - if (pos >= len) { + if (pos >= end) { error(Diagnostics.Unexpected_end_of_text); isInvalidExtendedEscape = true; } @@ -914,7 +943,7 @@ module ts { // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX' // and return code point value if valid Unicode escape is found. Otherwise return -1. function peekUnicodeEscape(): number { - if (pos + 5 < len && text.charCodeAt(pos + 1) === CharacterCodes.u) { + if (pos + 5 < end && text.charCodeAt(pos + 1) === CharacterCodes.u) { let start = pos; pos += 2; let value = scanExactNumberOfHexDigits(4); @@ -927,7 +956,7 @@ module ts { function scanIdentifierParts(): string { let result = ""; let start = pos; - while (pos < len) { + while (pos < end) { let ch = text.charCodeAt(pos); if (isIdentifierPart(ch)) { pos++; @@ -994,7 +1023,7 @@ module ts { tokenIsUnterminated = false; while (true) { tokenPos = pos; - if (pos >= len) { + if (pos >= end) { return token = SyntaxKind.EndOfFileToken; } let ch = text.charCodeAt(pos); @@ -1007,7 +1036,7 @@ module ts { continue; } else { - if (ch === CharacterCodes.carriageReturn && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { + if (ch === CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { // consume both CR and LF pos += 2; } @@ -1025,7 +1054,7 @@ module ts { continue; } else { - while (pos < len && isWhiteSpace(text.charCodeAt(pos))) { + while (pos < end && isWhiteSpace(text.charCodeAt(pos))) { pos++; } return token = SyntaxKind.WhitespaceTrivia; @@ -1098,7 +1127,7 @@ module ts { if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; - while (pos < len) { + while (pos < end) { if (isLineBreak(text.charCodeAt(pos))) { break; } @@ -1118,7 +1147,7 @@ module ts { pos += 2; let commentClosed = false; - while (pos < len) { + while (pos < end) { let ch = text.charCodeAt(pos); if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { @@ -1153,7 +1182,7 @@ module ts { return pos++, token = SyntaxKind.SlashToken; case CharacterCodes._0: - if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) { + if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) { pos += 2; let value = scanMinimumNumberOfHexDigits(1); if (value < 0) { @@ -1163,7 +1192,7 @@ module ts { tokenValue = "" + value; return token = SyntaxKind.NumericLiteral; } - else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { pos += 2; let value = scanBinaryOrOctalDigits(/* base */ 2); if (value < 0) { @@ -1173,7 +1202,7 @@ module ts { tokenValue = "" + value; return token = SyntaxKind.NumericLiteral; } - else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { pos += 2; let value = scanBinaryOrOctalDigits(/* base */ 8); if (value < 0) { @@ -1184,7 +1213,7 @@ module ts { return token = SyntaxKind.NumericLiteral; } // Try to parse as an octal - if (pos + 1 < len && isOctalDigit(text.charCodeAt(pos + 1))) { + if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) { tokenValue = "" + scanOctalDigits(); return token = SyntaxKind.NumericLiteral; } @@ -1299,7 +1328,7 @@ module ts { default: if (isIdentifierStart(ch)) { pos++; - while (pos < len && isIdentifierPart(ch = text.charCodeAt(pos))) pos++; + while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos))) pos++; tokenValue = text.substring(tokenPos, pos); if (ch === CharacterCodes.backslash) { tokenValue += scanIdentifierParts(); @@ -1350,7 +1379,7 @@ module ts { while (true) { // If we reach the end of a file, or hit a newline, then this is an unterminated // regex. Report error and return what we have so far. - if (p >= len) { + if (p >= end) { tokenIsUnterminated = true; error(Diagnostics.Unterminated_regular_expression_literal) break; @@ -1386,7 +1415,7 @@ module ts { p++; } - while (p < len && isIdentifierPart(text.charCodeAt(p))) { + while (p < end && isIdentifierPart(text.charCodeAt(p))) { p++; } pos = p; @@ -1435,43 +1464,19 @@ module ts { return speculationHelper(callback, /*isLookahead:*/ false); } - function setText(newText: string) { + function setText(newText: string, start?: number, length?: number) { text = newText || ""; - len = text.length; - setTextPos(0); + end = length === undefined ? text.length : start + length; + setTextPos(start || 0); } function setTextPos(textPos: number) { + Debug.assert(textPos >= 0); pos = textPos; startPos = textPos; tokenPos = textPos; token = SyntaxKind.Unknown; precedingLineBreak = false; } - - setText(text); - - - return { - getStartPos: () => startPos, - getTextPos: () => pos, - getToken: () => token, - getTokenPos: () => tokenPos, - getTokenText: () => text.substring(tokenPos, pos), - getTokenValue: () => tokenValue, - hasExtendedUnicodeEscape: () => hasExtendedUnicodeEscape, - hasPrecedingLineBreak: () => precedingLineBreak, - isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, - isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord, - isUnterminated: () => tokenIsUnterminated, - reScanGreaterToken, - reScanSlashToken, - reScanTemplateToken, - scan, - setText, - setTextPos, - tryScan, - lookAhead, - }; } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 41f6db9bab255..d1358fcbcbd72 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -264,8 +264,7 @@ module ts { /* @internal */ export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan { - let scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.text); - scanner.setTextPos(pos); + let scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.text, /*onError:*/ undefined, pos); scanner.scan(); let start = scanner.getTokenPos(); return createTextSpanFromBounds(start, scanner.getTextPos()); From 604988c2f511cac78ea79627183571e927627eec Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 13:58:23 -0700 Subject: [PATCH 13/96] Add support for parsing JSDoc comments. --- src/compiler/parser.ts | 197 +++++++++++++++++++++++++++++++++++++++++ src/compiler/types.ts | 7 ++ 2 files changed, 204 insertions(+) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a46fdd163e0a6..7a5b66cdb1635 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5388,6 +5388,7 @@ module ts { // Parses out a JSDoc type expression. The starting position should be right at the open // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. + /* @internal */ export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocType { let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content, /*onError:*/ undefined, start, length); @@ -5725,6 +5726,202 @@ module ts { } } + /* @internal */ + export function parseJSDocComment(content: string, start?: number, length?: number): JSDocComment { + start = start || 0; + let end = length === undefined ? content.length : start + length; + length = end - start; + + Debug.assert(start >= 0); + Debug.assert(start <= end); + Debug.assert(end <= content.length); + + let error = false; + let type : JSDocType; + let parameterTypes: JSDocType[]; + let returnType: JSDocType; + let typeParameterNames: string[]; + + if (length >= "/** */".length) { + if (content.charCodeAt(start) === CharacterCodes.slash && + content.charCodeAt(start + 1) === CharacterCodes.asterisk && + content.charCodeAt(start + 2) === CharacterCodes.asterisk && + content.charCodeAt(start + 3) !== CharacterCodes.asterisk) { + + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + let canParseTag = true; + let seenAsterisk = true; + + for (let i = start + 3; !error && i < end; i++) { + let ch = content.charCodeAt(i); + + if (isLineBreak(ch)) { + // After a line break, we can parse a tag, and we haven't seen as asterisk + // on the next line yet. + canParseTag = true; + seenAsterisk = false; + continue; + } + + if (isWhiteSpace(ch)) { + // Whitespace doesn't affect any of our parsing. + continue; + } + + if (ch === CharacterCodes.at && canParseTag) { + i = parseTag(i); + + // Once we parse out a tag, we cannot keep parsing out tags on this line. + canParseTag = false; + continue; + } + + // Ignore the first asterisk on a line. + if (ch === CharacterCodes.asterisk) { + if (seenAsterisk) { + // If we've already seen an asterisk, then we can no longer parse a tag + // on this line. + canParseTag = false; + } + seenAsterisk = true; + continue; + } + + // Anything else is doc comment text. We can't do anything with it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. + canParseTag = false; + } + } + } + + return error ? undefined : createJSDocComment(); + + function createJSDocComment(): JSDocComment { + if (!returnType && !type && !parameterTypes && !typeParameterNames) { + return undefined; + } + + return { returnType, type, parameterTypes, typeParameterNames }; + } + + function skipWhitespace(pos: number): number { + while (pos < end && isWhiteSpace(content.charCodeAt(pos))) { + pos++; + } + + return pos; + } + + function parseTag(pos: number): number { + Debug.assert(content.charCodeAt(pos) === CharacterCodes.at); + + // Scan forward to figure out the tag name. + for (var i = pos + 1; i < end; i++) { + if (!isIdentifierStart(content.charCodeAt(i), ScriptTarget.Latest)) { + break; + } + } + + let tagName = content.substring(pos + 1, i); + switch (tagName) { + case "param": + return handleParamTag(i); + case "return": + return handleReturnTag(i); + case "template": + return handleTemplateTag(i); + case "type": + return handleTypeTag(i); + } + + return i; + } + + function handleParamTag(pos: number) { + let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); + if (!typeExpr) { + error = true; + return pos; + } + + parameterTypes = parameterTypes || []; + parameterTypes.push(typeExpr); + return typeExpr.end; + } + + function handleReturnTag(pos: number) { + if (!returnType) { + let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); + if (typeExpr) { + returnType = typeExpr; + return typeExpr.end; + } + } + + error = true; + return pos; + } + + function handleTypeTag(pos: number) { + if (!type) { + let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); + if (typeExpr) { + type = typeExpr; + return typeExpr.end; + } + } + + error = true; + return pos; + } + + function handleTemplateTag(pos: number): number { + if (!typeParameterNames) { + typeParameterNames = []; + + while (!error) { + pos = skipWhitespace(pos); + scanTypeParameterName(); + pos = skipWhitespace(pos); + if (content.charCodeAt(pos) !== CharacterCodes.comma) { + break; + } + } + + if (typeParameterNames.length > 0) { + return pos; + } + } + + error = true; + return pos; + + function scanTypeParameterName() { + for (var i = pos; i < end; i++) { + let ch = content.charCodeAt(i); + if (i === pos && isIdentifierStart(ch, ScriptTarget.Latest)) { + continue; + } + else if (i > pos && isIdentifierPart(ch, ScriptTarget.Latest)) { + continue; + } + + break; + } + + if (i === pos) { + error = true; + return; + } + + typeParameterNames.push(content.substring(pos, i)); + pos = i; + } + } + } + function createNodeAtPosition(scanner: Scanner, kind: SyntaxKind, pos?: number): Node { let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); if (!(pos >= 0)) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 460a406f4a520..b3c7579ba9e4e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1069,6 +1069,13 @@ module ts { type?: JSDocType } + export interface JSDocComment { + type?: JSDocType; + parameterTypes?: JSDocType[]; + returnType?: JSDocType; + typeParameterNames?: string[]; + } + // Source files are declarations when they are external modules. export interface SourceFile extends Declaration { statements: NodeArray; From 2e58435c33cee56ee8f1b9f294f87a9a73bbc17d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 15:27:43 -0700 Subject: [PATCH 14/96] Add tests for parsing JSDoc comments. --- src/compiler/parser.ts | 165 +++--- src/compiler/types.ts | 13 +- tests/cases/unittests/jsDocParsing.ts | 742 ++++++++++++++++++++------ 3 files changed, 666 insertions(+), 254 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7a5b66cdb1635..c06ff8af4b44c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5389,18 +5389,20 @@ module ts { // Parses out a JSDoc type expression. The starting position should be right at the open // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. /* @internal */ - export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocType { + export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocTypeExpression { let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content, /*onError:*/ undefined, start, length); // Prime the first token for us to start processing. let token = nextToken(); let error = false; + let result = createNode(SyntaxKind.JSDocTypeExpression); + parseExpected(SyntaxKind.OpenBraceToken); - let type = parseJSDocType(); + result.type = parseJSDocType(); parseExpected(SyntaxKind.CloseBraceToken); - return error ? undefined : type; + return error ? undefined : finishNode(result); function nextToken(): SyntaxKind { return token = scanner.scan(); @@ -5738,10 +5740,12 @@ module ts { let error = false; let type : JSDocType; - let parameterTypes: JSDocType[]; + let parameters: JSDocParameter[]; let returnType: JSDocType; let typeParameterNames: string[]; + let pos: number; + if (length >= "/** */".length) { if (content.charCodeAt(start) === CharacterCodes.slash && content.charCodeAt(start + 1) === CharacterCodes.asterisk && @@ -5753,9 +5757,21 @@ module ts { let canParseTag = true; let seenAsterisk = true; - for (let i = start + 3; !error && i < end; i++) { - let ch = content.charCodeAt(i); + for (pos = start + 3; !error && pos < end; ) { + let ch = content.charCodeAt(pos); + + if (ch === CharacterCodes.at && canParseTag) { + // Don't update 'pos' in this block. that will be handled inside the + // parseTag function. + + parseTag(); + + // Once we parse out a tag, we cannot keep parsing out tags on this line. + canParseTag = false; + continue; + } + pos++; if (isLineBreak(ch)) { // After a line break, we can parse a tag, and we haven't seen as asterisk // on the next line yet. @@ -5769,14 +5785,6 @@ module ts { continue; } - if (ch === CharacterCodes.at && canParseTag) { - i = parseTag(i); - - // Once we parse out a tag, we cannot keep parsing out tags on this line. - canParseTag = false; - continue; - } - // Ignore the first asterisk on a line. if (ch === CharacterCodes.asterisk) { if (seenAsterisk) { @@ -5799,126 +5807,125 @@ module ts { return error ? undefined : createJSDocComment(); function createJSDocComment(): JSDocComment { - if (!returnType && !type && !parameterTypes && !typeParameterNames) { + if (!returnType && !type && !parameters && !typeParameterNames) { return undefined; } - return { returnType, type, parameterTypes, typeParameterNames }; + return { returnType, type, parameters, typeParameterNames }; } - function skipWhitespace(pos: number): number { + function skipWhitespace(): void { while (pos < end && isWhiteSpace(content.charCodeAt(pos))) { pos++; } - - return pos; } - function parseTag(pos: number): number { + function parseTag(): void { Debug.assert(content.charCodeAt(pos) === CharacterCodes.at); + + // Skip the @ sign. + pos++; - // Scan forward to figure out the tag name. - for (var i = pos + 1; i < end; i++) { - if (!isIdentifierStart(content.charCodeAt(i), ScriptTarget.Latest)) { - break; - } - } - - let tagName = content.substring(pos + 1, i); + let tagName = scanIdentifier(); switch (tagName) { case "param": - return handleParamTag(i); + return handleParamTag(); case "return": - return handleReturnTag(i); + return handleReturnTag(); case "template": - return handleTemplateTag(i); + return handleTemplateTag(); case "type": - return handleTypeTag(i); + return handleTypeTag(); } - - return i; } - function handleParamTag(pos: number) { - let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); - if (!typeExpr) { + function parseType(): JSDocType { + let typeExpression = parseJSDocTypeExpression(content, pos, end - pos); + if (!typeExpression) { error = true; - return pos; + return undefined; + } + + pos = typeExpression.end; + return typeExpression.type; + } + + function handleParamTag() { + let type = parseType(); + if (!type) { + return; } - parameterTypes = parameterTypes || []; - parameterTypes.push(typeExpr); - return typeExpr.end; + skipWhitespace(); + + let name = scanIdentifier(); + parameters = parameters || []; + parameters.push({ name, type }); } - function handleReturnTag(pos: number) { + function handleReturnTag(): void { if (!returnType) { - let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); - if (typeExpr) { - returnType = typeExpr; - return typeExpr.end; + returnType = parseType(); + if (returnType) { + return; } } error = true; - return pos; } - function handleTypeTag(pos: number) { + function handleTypeTag(): void { if (!type) { - let typeExpr = parseJSDocTypeExpression(content, pos, end - pos); - if (typeExpr) { - type = typeExpr; - return typeExpr.end; + type = parseType(); + if (type) { + return; } } error = true; - return pos; } - function handleTemplateTag(pos: number): number { + function handleTemplateTag(): void { if (!typeParameterNames) { typeParameterNames = []; while (!error) { - pos = skipWhitespace(pos); - scanTypeParameterName(); - pos = skipWhitespace(pos); + skipWhitespace(); + let name = scanIdentifier(); + typeParameterNames.push(name); + + skipWhitespace(); if (content.charCodeAt(pos) !== CharacterCodes.comma) { - break; + return; } - } - if (typeParameterNames.length > 0) { - return pos; + pos++; } } error = true; - return pos; - - function scanTypeParameterName() { - for (var i = pos; i < end; i++) { - let ch = content.charCodeAt(i); - if (i === pos && isIdentifierStart(ch, ScriptTarget.Latest)) { - continue; - } - else if (i > pos && isIdentifierPart(ch, ScriptTarget.Latest)) { - continue; - } + } - break; + function scanIdentifier(): string { + let startPos = pos; + for (;pos < end; pos++) { + let ch = content.charCodeAt(pos); + if (pos === startPos && isIdentifierStart(ch, ScriptTarget.Latest)) { + continue; } - - if (i === pos) { - error = true; - return; + else if (pos > startPos && isIdentifierPart(ch, ScriptTarget.Latest)) { + continue; } - typeParameterNames.push(content.substring(pos, i)); - pos = i; + break; + } + + if (startPos === pos) { + error = true; + return; } + + return content.substring(startPos, pos); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b3c7579ba9e4e..bb7d36b4ff162 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -270,6 +270,7 @@ module ts { SourceFile, // JSDoc nodes. + JSDocTypeExpression, // The * type. JSDocAllType, // The ? type. @@ -1010,6 +1011,11 @@ module ts { hasTrailingNewLine?: boolean; } + // represents a top level: { type } expression in a JSDoc comment. + export interface JSDocTypeExpression extends Node { + type: JSDocType; + } + export interface JSDocType extends Node { _jsDocTypeBrand: any; } @@ -1069,9 +1075,14 @@ module ts { type?: JSDocType } + export interface JSDocParameter { + name: string; + type: JSDocType; + } + export interface JSDocComment { type?: JSDocType; - parameterTypes?: JSDocType[]; + parameters?: JSDocParameter[]; returnType?: JSDocType; typeParameterNames?: string[]; } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 470e5f94bbd8b..cdd1144d4606d 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -3,40 +3,43 @@ /// module ts { - function parsesCorrectly(content: string, expected: string) { - let type = ts.parseJSDocTypeExpression(content, 0); - let result = Utils.sourceFileToJSON(type); - assert.equal(result, expected); - } + describe("JSDocParsing", () => { + describe("TypeExpressions", () => { + function parsesCorrectly(content: string, expected: string) { + let typeExpression = ts.parseJSDocTypeExpression(content); + assert.isNotNull(typeExpression); - function parsesIncorrectly(content: string) { - let type = ts.parseJSDocTypeExpression(content, 0); - assert.equal(type, undefined); - } + let result = Utils.sourceFileToJSON(typeExpression.type); + assert.equal(result, expected); + } - describe("JSDocParsing", () => { - describe("parseCorrectly", () => { - it("unknownType", () => { - parsesCorrectly("{?}", - `{ + function parsesIncorrectly(content: string) { + let type = ts.parseJSDocTypeExpression(content); + assert.equal(type, undefined); + } + + describe("parseCorrectly", () => { + it("unknownType", () => { + parsesCorrectly("{?}", + `{ "kind": "JSDocUnknownType", "pos": 1, "end": 2 }`); - }); + }); - it("allType", () => { - parsesCorrectly("{*}", - `{ + it("allType", () => { + parsesCorrectly("{*}", + `{ "kind": "JSDocAllType", "pos": 1, "end": 2 }`); - }); + }); - it("nullableType", () => { - parsesCorrectly("{?number}", - `{ + it("nullableType", () => { + parsesCorrectly("{?number}", + `{ "kind": "JSDocNullableType", "pos": 1, "end": 8, @@ -52,11 +55,11 @@ module ts { } } }`) - }); + }); - it("nonNullableType", () => { - parsesCorrectly("{!number}", - `{ + it("nonNullableType", () => { + parsesCorrectly("{!number}", + `{ "kind": "JSDocNonNullableType", "pos": 1, "end": 8, @@ -72,11 +75,11 @@ module ts { } } }`) - }); + }); - it("recordType1", () => { - parsesCorrectly("{{}}", - `{ + it("recordType1", () => { + parsesCorrectly("{{}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 3, @@ -86,11 +89,11 @@ module ts { "end": 2 } }`) - }); + }); - it("recordType2", () => { - parsesCorrectly("{{foo}}", - `{ + it("recordType2", () => { + parsesCorrectly("{{foo}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 6, @@ -111,11 +114,11 @@ module ts { "end": 5 } }`) - }); + }); - it("recordType3", () => { - parsesCorrectly("{{foo: number}}", - `{ + it("recordType3", () => { + parsesCorrectly("{{foo: number}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 14, @@ -147,11 +150,11 @@ module ts { "end": 13 } }`) - }); + }); - it("recordType4", () => { - parsesCorrectly("{{foo, bar}}", - `{ + it("recordType4", () => { + parsesCorrectly("{{foo, bar}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 11, @@ -183,11 +186,11 @@ module ts { "end": 10 } }`) - }); + }); - it("recordType5", () => { - parsesCorrectly("{{foo: number, bar}}", - `{ + it("recordType5", () => { + parsesCorrectly("{{foo: number, bar}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 19, @@ -230,11 +233,11 @@ module ts { "end": 18 } }`) - }); + }); - it("recordType6", () => { - parsesCorrectly("{{foo, bar: number}}", - `{ + it("recordType6", () => { + parsesCorrectly("{{foo, bar: number}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 19, @@ -277,11 +280,11 @@ module ts { "end": 18 } }`) - }); + }); - it("recordType7", () => { - parsesCorrectly("{{foo: number, bar: number}}", - `{ + it("recordType7", () => { + parsesCorrectly("{{foo: number, bar: number}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 27, @@ -335,11 +338,11 @@ module ts { "end": 26 } }`) - }); + }); - it("recordType8", () => { - parsesCorrectly("{{function}}", - `{ + it("recordType8", () => { + parsesCorrectly("{{function}}", + `{ "kind": "JSDocRecordType", "pos": 1, "end": 11, @@ -360,11 +363,11 @@ module ts { "end": 10 } }`) - }); + }); - it("unionType", () => { - parsesCorrectly("{(number|string)}", -`{ + it("unionType", () => { + parsesCorrectly("{(number|string)}", + `{ "kind": "JSDocUnionType", "pos": 1, "end": 16, @@ -396,11 +399,11 @@ module ts { "end": 15 } }`); - }); + }); - it("functionType1", () => { - parsesCorrectly("{function()}", - `{ + it("functionType1", () => { + parsesCorrectly("{function()}", + `{ "kind": "JSDocFunctionType", "pos": 1, "end": 11, @@ -410,11 +413,11 @@ module ts { "end": 10 } }`); - }); + }); - it("functionType2", () => { - parsesCorrectly("{function(string, boolean)}", - `{ + it("functionType2", () => { + parsesCorrectly("{function(string, boolean)}", + `{ "kind": "JSDocFunctionType", "pos": 1, "end": 26, @@ -446,11 +449,11 @@ module ts { "end": 25 } }`); - }); + }); - it("functionReturnType1", () => { - parsesCorrectly("{function(string, boolean)}", - `{ + it("functionReturnType1", () => { + parsesCorrectly("{function(string, boolean)}", + `{ "kind": "JSDocFunctionType", "pos": 1, "end": 26, @@ -482,11 +485,11 @@ module ts { "end": 25 } }`); - }); + }); - it("thisType1", () => { - parsesCorrectly("{this:a.b}", - `{ + it("thisType1", () => { + parsesCorrectly("{this:a.b}", + `{ "kind": "JSDocThisType", "pos": 1, "end": 9, @@ -513,11 +516,11 @@ module ts { } } }`); - }); + }); - it("newType1", () => { - parsesCorrectly("{new:a.b}", - `{ + it("newType1", () => { + parsesCorrectly("{new:a.b}", + `{ "kind": "JSDocConstructorType", "pos": 1, "end": 8, @@ -544,11 +547,11 @@ module ts { } } }`); - }); + }); - it("variadicType", () => { - parsesCorrectly("{...number}", - `{ + it("variadicType", () => { + parsesCorrectly("{...number}", + `{ "kind": "JSDocVariadicType", "pos": 1, "end": 10, @@ -564,11 +567,11 @@ module ts { } } }`); - }); + }); - it("optionalType", () => { - parsesCorrectly("{number=}", - `{ + it("optionalType", () => { + parsesCorrectly("{number=}", + `{ "kind": "JSDocOptionalType", "pos": 1, "end": 8, @@ -584,11 +587,11 @@ module ts { } } }`); - }); + }); - it("optionalNullable", () => { - parsesCorrectly("{?=}", - `{ + it("optionalNullable", () => { + parsesCorrectly("{?=}", + `{ "kind": "JSDocOptionalType", "pos": 1, "end": 3, @@ -598,11 +601,11 @@ module ts { "end": 2 } }`); - }); + }); - it("typeReference1", () => { - parsesCorrectly("{a.}", - `{ + it("typeReference1", () => { + parsesCorrectly("{a.}", + `{ "kind": "JSDocTypeReference", "pos": 1, "end": 11, @@ -629,11 +632,11 @@ module ts { "end": 10 } }`); - }); + }); - it("typeReference2", () => { - parsesCorrectly("{a.}", - `{ + it("typeReference2", () => { + parsesCorrectly("{a.}", + `{ "kind": "JSDocTypeReference", "pos": 1, "end": 18, @@ -671,11 +674,11 @@ module ts { "end": 17 } }`); - }); + }); - it("typeReference3", () => { - parsesCorrectly("{a.function}", - `{ + it("typeReference3", () => { + parsesCorrectly("{a.function}", + `{ "kind": "JSDocTypeReference", "pos": 1, "end": 11, @@ -697,100 +700,491 @@ module ts { } } }`); + }); }); - }); - describe("parsesIncorrectly", () => { - it("emptyType", () => { - parsesIncorrectly("{}"); - }); + describe("parsesIncorrectly", () => { + it("emptyType", () => { + parsesIncorrectly("{}"); + }); - it("trailingCommaInRecordType", () => { - parsesIncorrectly("{{a,}}"); - }); + it("trailingCommaInRecordType", () => { + parsesIncorrectly("{{a,}}"); + }); - it("unionTypeWithTrailingBar", () => { - parsesIncorrectly("{(a|)}"); - }); + it("unionTypeWithTrailingBar", () => { + parsesIncorrectly("{(a|)}"); + }); - it("unionTypeWithoutTypes", () => { - parsesIncorrectly("{()}"); - }); + it("unionTypeWithoutTypes", () => { + parsesIncorrectly("{()}"); + }); - it("nullableTypeWithoutType", () => { - parsesIncorrectly("{!}"); - }); + it("nullableTypeWithoutType", () => { + parsesIncorrectly("{!}"); + }); - it("functionTypeWithTrailingComma", () => { - parsesIncorrectly("{function(a,)}"); - }); + it("functionTypeWithTrailingComma", () => { + parsesIncorrectly("{function(a,)}"); + }); - it("keyword", () => { - parsesIncorrectly("{var}"); - }); + it("keyword", () => { + parsesIncorrectly("{var}"); + }); - it("thisWithoutType", () => { - parsesIncorrectly("{this:}"); - }); + it("thisWithoutType", () => { + parsesIncorrectly("{this:}"); + }); - it("newWithoutType", () => { - parsesIncorrectly("{new:}"); - }); + it("newWithoutType", () => { + parsesIncorrectly("{new:}"); + }); - it("variadicWithoutType", () => { - parsesIncorrectly("{...}"); - }); + it("variadicWithoutType", () => { + parsesIncorrectly("{...}"); + }); - it("optionalWithoutType", () => { - parsesIncorrectly("{=}"); - }); + it("optionalWithoutType", () => { + parsesIncorrectly("{=}"); + }); - it("allWithType", () => { - parsesIncorrectly("{*foo}"); - }); + it("allWithType", () => { + parsesIncorrectly("{*foo}"); + }); - it("typeArgumentsNotFollowingDot", () => { - parsesIncorrectly("{a<>}"); - }); + it("typeArgumentsNotFollowingDot", () => { + parsesIncorrectly("{a<>}"); + }); - it("emptyTypeArguments", () => { - parsesIncorrectly("{a.<>}"); - }); + it("emptyTypeArguments", () => { + parsesIncorrectly("{a.<>}"); + }); - it("typeArgumentsWithTrailingComma", () => { - parsesIncorrectly("{a.}"); - }); + it("typeArgumentsWithTrailingComma", () => { + parsesIncorrectly("{a.}"); + }); - it("arrayType", () => { - parsesIncorrectly("{a[]}"); - }); + it("arrayType", () => { + parsesIncorrectly("{a[]}"); + }); - it("tsFunctionType", () => { - parsesIncorrectly("{() => string}"); - }); + it("tsFunctionType", () => { + parsesIncorrectly("{() => string}"); + }); - it("tsConstructoType", () => { - parsesIncorrectly("{new () => string}"); - }); + it("tsConstructoType", () => { + parsesIncorrectly("{new () => string}"); + }); - it("tupleType", () => { - parsesIncorrectly("{[number,string]}"); - }); + it("tupleType", () => { + parsesIncorrectly("{[number,string]}"); + }); - it("typeOfType", () => { - parsesIncorrectly("{typeof M}"); - }); + it("typeOfType", () => { + parsesIncorrectly("{typeof M}"); + }); + + it("namedParameter", () => { + parsesIncorrectly("{function(a: number)}"); + }); - it("namedParameter", () => { - parsesIncorrectly("{function(a: number)}"); + it("callSignatureInRecordType", () => { + parsesIncorrectly("{{(): number}}"); + }); + + it("methodInRecordType", () => { + parsesIncorrectly("{{foo(): number}}"); + }); }); + }); + + describe("DocComments", () => { + function parsesCorrectly(content: string, expected: string) { + let comment = ts.parseJSDocComment(content); + let result = JSON.stringify(comment, (k, v) => { + return v && v.pos !== undefined + ? JSON.parse(Utils.sourceFileToJSON(v)) + : v; + }, " "); + assert.equal(result, expected); + } + + function parsesIncorrectly(content: string) { + let type = ts.parseJSDocComment(content); + assert.equal(type, undefined); + } + + describe("parsesIncorrectly", () => { + it("emptyComment", () => { + parsesIncorrectly("/***/"); + }); + + it("threeAsterisks", () => { + parsesIncorrectly("/*** */"); + }); + + it("asteriskAfterPreamble", () => { + parsesIncorrectly("/** * @type {number} */"); + }); + + it("multipleTypes", () => { + parsesIncorrectly( +`/** + * @type {number} + * @type {string} + */`); + }); - it("callSignatureInRecordType", () => { - parsesIncorrectly("{{(): number}}"); + it("noType", () => { + parsesIncorrectly( +`/** + * @type + */`); + }); + + it("multipleReturnTypes", () => { + parsesIncorrectly( +`/** + * @return {number} + * @return {string} + */`); + }); + + it("noReturnType", () => { + parsesIncorrectly( +`/** + * @return + */`); + }); + + it("noTypeParameters", () => { + parsesIncorrectly( +`/** + * @template + */`); + }); + + it("trailingTypeParameterComma", () => { + parsesIncorrectly( +`/** + * @template T, + */`); + }); + + it("paramWithoutName", () => { + parsesIncorrectly( +`/** + * @param {number} + */`); + }); + + it("paramWithoutType", () => { + parsesIncorrectly( +`/** + * @param foo + */`); + }); + + it("paramWithoutTypeOrName", () => { + parsesIncorrectly( +`/** + * @param + */`); + }); }); - it("methodInRecordType", () => { - parsesIncorrectly("{{foo(): number}}"); + describe("parsesCorrectly", () => { + it("noLeadingAsterisk", () => { + parsesCorrectly( +`/** + @type {number} + */`, + `{ + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": 65, + "pos": 15, + "end": 21, + "text": "number" + } + } +}`); + }); + + it("leadingAsterisk", () => { + parsesCorrectly( +`/** + * @type {number} + */`, + `{ + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": 65, + "pos": 15, + "end": 21, + "text": "number" + } + } +}`); + }); + + it("typeTag", () => { + parsesCorrectly( +`/** + * @type {number} + */`, + `{ + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": 65, + "pos": 15, + "end": 21, + "text": "number" + } + } +}`); + }); + + it("returnTag1", () => { + parsesCorrectly( +`/** + * @return {number} + */`, + `{ + "returnType": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 23, + "name": { + "kind": 65, + "pos": 17, + "end": 23, + "text": "number" + } + } +}`); + }); + + it("returnTag2", () => { + parsesCorrectly( + `/** + * @return {number} Description text follows + */`, + `{ + "returnType": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 23, + "name": { + "kind": 65, + "pos": 17, + "end": 23, + "text": "number" + } + } +}`); + }); + + it("oneParamTag", () => { + parsesCorrectly( +`/** + * @param {number} name1 + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + } + } + ] +}`); + }); + + it("twoParamTag2", () => { + parsesCorrectly( +`/** + * @param {number} name1 + * @param {number} name2 + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + } + }, + { + "name": "name2", + "type": { + "kind": "JSDocTypeReference", + "pos": 42, + "end": 48, + "name": { + "kind": 65, + "pos": 42, + "end": 48, + "text": "number" + } + } + } + ] +}`); + }); + + it("paramTag1", () => { + parsesCorrectly( + `/** + * @param {number} name1 Description text follows + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + } + } + ] +}`); + }); + + it("twoParamTagOnSameLine", () => { + parsesCorrectly( +`/** + * @param {number} name1 @param {number} name2 + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + } + } + ] +}`); + }); + + it("templateTag", () => { + parsesCorrectly( +`/** + * @template T + */`, + `{ + "typeParameterNames": [ + "T" + ] +}`); + }); + + it("templateTag2", () => { + parsesCorrectly( + `/** + * @template K,V + */`, + `{ + "typeParameterNames": [ + "K", + "V" + ] +}`); + }); + + it("templateTag3", () => { + parsesCorrectly( + `/** + * @template K ,V + */`, + `{ + "typeParameterNames": [ + "K", + "V" + ] +}`); + }); + + it("templateTag4", () => { + parsesCorrectly( + `/** + * @template K, V + */`, + `{ + "typeParameterNames": [ + "K", + "V" + ] +}`); + }); + + it("templateTag5", () => { + parsesCorrectly( + `/** + * @template K , V + */`, + `{ + "typeParameterNames": [ + "K", + "V" + ] +}`); + }); + + it("templateTag6", () => { + parsesCorrectly( + `/** + * @template K , V Description of type parameters. + */`, + `{ + "typeParameterNames": [ + "K", + "V" + ] +}`); + }); }); }); }); From 3a33884efe366da2a8ff42d23a0040ab576f0dc9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 16:38:44 -0700 Subject: [PATCH 15/96] Add support for converting JSDoc types to our own types. --- src/compiler/checker.ts | 141 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 54d722f53b0f7..03a32acfabc34 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2105,8 +2105,75 @@ module ts { return type; } + function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) { + // First see if this node has a doc comment on it directly. + let jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); + return getTypeFromJSDocType(jsDocType); + } + + function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { + // First, see if this node has an @type annotation on it directly. + let sourceFile = getSourceFileOfNode(declaration); + let docComment = getJSDocComment(declaration, sourceFile); + + if (docComment && docComment.type) { + return docComment.type; + } + + if (declaration.kind === SyntaxKind.VariableDeclaration && + declaration.parent.kind === SyntaxKind.VariableDeclarationList && + declaration.parent.parent.kind === SyntaxKind.VariableStatement) { + + // @type annotation might have been on the variable statement, try that instead. + docComment = getJSDocComment(declaration.parent.parent, sourceFile); + if (docComment && docComment.type) { + return docComment.type; + } + } + else if (declaration.kind === SyntaxKind.Parameter && (declaration).name.kind === SyntaxKind.Identifier) { + // If it's a parameter, see if the parent has a jsdoc comment with an @param + // annotation. + let parameterName = ((declaration).name).text; + + docComment = getJSDocComment(declaration.parent, sourceFile); + if (docComment && docComment.parameters) { + for (let parameter of docComment.parameters) { + if (parameter.name === parameterName) { + return parameter.type; + } + } + } + } + + return undefined; + } + + function getJSDocComment(node: Node, sourceFile: SourceFile) { + let comments = getLeadingCommentRangesOfNode(node, sourceFile); + if (comments) { + for (let comment of comments) { + let jsDocComment = parseJSDocComment(sourceFile.text, comment.pos, comment.end - comment.pos); + if (jsDocComment) { + return jsDocComment; + } + } + } + + return undefined; + } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type { + if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { + // If this is a variable in a JavaScript file, then use the JSDoc type (if it has + // one as it's type), otherwise fallback to the below standard TS codepaths to + // try to figure it out. + let type = getTypeForVariableLikeDeclarationFromJSDocComment(declaration); + if (type) { + return type; + } + } + // A variable declared in a for..in statement is always of type any if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) { return anyType; @@ -2121,6 +2188,7 @@ module ts { if (isBindingPattern(declaration.parent)) { return getTypeForBindingElement(declaration); } + // Use type from type annotation if one is present if (declaration.type) { return getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); @@ -3618,6 +3686,79 @@ module ts { return links.resolvedType; } + function getTypeFromJSDocType(jsDocType: JSDocType): Type { + if (jsDocType) { + switch (jsDocType.kind) { + case SyntaxKind.JSDocAllType: + return anyType; + case SyntaxKind.JSDocUnknownType: + return unknownType; + case SyntaxKind.JSDocUnionType: + return getTypeFromJSDocUnionType(jsDocType); + case SyntaxKind.JSDocNullableType: + return getTypeFromJSDocType((jsDocType).type); + case SyntaxKind.JSDocNonNullableType: + return getTypeFromJSDocType((jsDocType).type); + case SyntaxKind.JSDocRecordType: + // NYI: + break; + case SyntaxKind.JSDocTypeReference: + return getTypeForJSDocTypeReference(jsDocType); + case SyntaxKind.JSDocOptionalType: + return getTypeFromJSDocType((jsDocType).type); + case SyntaxKind.JSDocFunctionType: + // NYI: + break; + case SyntaxKind.JSDocVariadicType: + return getTypeFromJSDocType((jsDocType).type); + case SyntaxKind.JSDocConstructorType: + // NYI: + break; + case SyntaxKind.JSDocThisType: + // NYI: + break; + } + } + } + + function getTypeForJSDocTypeReference(node: JSDocTypeReference): Type { + if (node.name.kind === SyntaxKind.Identifier) { + switch ((node.name).text) { + case "any": return anyType; + case "boolean": return booleanType; + case "number": return numberType; + case "string": return stringType; + case "symbol": return esSymbolType; + } + } + + let symbol = resolveEntityName(node.name, SymbolFlags.Type); + if (symbol) { + let type = getDeclaredTypeOfSymbol(symbol); + if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { + let typeParameters = (type).typeParameters; + if (node.typeArguments && node.typeArguments.length === typeParameters.length) { + let typeArguments = map(node.typeArguments, getTypeFromJSDocType); + for (let typeArgument in typeArguments) { + if (!typeArgument) { + return undefined; + } + } + + type = createTypeReference(type, typeArguments); + } + } + + return type; + } + + return undefined; + } + + function getTypeFromJSDocUnionType(node: JSDocUnionType): Type { + return getUnionType(map(node.types, getTypeFromJSDocType), /*noSubtypeReduction*/ true); + } + function getTypeFromTypeNodeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type { switch (node.kind) { case SyntaxKind.AnyKeyword: From 6292f3eb344b0ec8462a29a040644c0e2aa14c7a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 17:32:45 -0700 Subject: [PATCH 16/96] Add tests for JSDoc comment intellisense. --- tests/cases/fourslash/getJavaScriptCompletions1.ts | 10 ++++++++++ tests/cases/fourslash/getJavaScriptCompletions2.ts | 10 ++++++++++ tests/cases/fourslash/getJavaScriptCompletions3.ts | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions1.ts create mode 100644 tests/cases/fourslash/getJavaScriptCompletions2.ts create mode 100644 tests/cases/fourslash/getJavaScriptCompletions3.ts diff --git a/tests/cases/fourslash/getJavaScriptCompletions1.ts b/tests/cases/fourslash/getJavaScriptCompletions1.ts new file mode 100644 index 0000000000000..c4da79186c9b3 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions1.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {number} */ +////var v; +////v./**/ + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptCompletions2.ts b/tests/cases/fourslash/getJavaScriptCompletions2.ts new file mode 100644 index 0000000000000..0cb2de046a668 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions2.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {(number|string)} */ +////var v; +////v./**/ + +goTo.marker(); +verify.completionListContains("valueOf", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptCompletions3.ts b/tests/cases/fourslash/getJavaScriptCompletions3.ts new file mode 100644 index 0000000000000..13a6f1673e6b3 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions3.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {Array.} */ +////var v; +////v./**/ + +goTo.marker(); +verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From 39c8c0dbe13a80c44062b222ddc9445d467aa38e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 20:26:15 -0700 Subject: [PATCH 17/96] Add support for function return types in JSDoc comments. --- src/compiler/checker.ts | 18 ++++++++++++++++-- .../fourslash/getJavaScriptCompletions4.ts | 10 ++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 03a32acfabc34..89bbcf80e26f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2106,7 +2106,6 @@ module ts { } function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) { - // First see if this node has a doc comment on it directly. let jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); return getTypeFromJSDocType(jsDocType); } @@ -7310,12 +7309,27 @@ module ts { } } + function getReturnTypeFromJSDocComment(func: FunctionLikeDeclaration): Type { + let jsDocComment = getJSDocComment(func, getSourceFile(func)); + if (jsDocComment && jsDocComment.returnType) { + return getTypeFromJSDocType(jsDocComment.returnType); + } + } + function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type { + let type: Type; + if (func.parserContextFlags & ParserContextFlags.JavaScriptFile) { + type = getReturnTypeFromJSDocComment(func); + if (type) { + return type; + } + } + let contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); if (!func.body) { return unknownType; } - let type: Type; + if (func.body.kind !== SyntaxKind.Block) { type = checkExpressionCached(func.body, contextualMapper); } diff --git a/tests/cases/fourslash/getJavaScriptCompletions4.ts b/tests/cases/fourslash/getJavaScriptCompletions4.ts new file mode 100644 index 0000000000000..3719b8e1258cb --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions4.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @return {number} */ +////function foo(a,b) { } +////foo(1,2)./**/ + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From c8e106ecacc20eb2c922453e61f6b4fe49ba7bd3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 21:02:55 -0700 Subject: [PATCH 18/96] Don't use a sourceFile if one isn't passed in. --- src/compiler/utilities.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d1358fcbcbd72..bae860fb8baae 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -302,9 +302,9 @@ module ts { return getSpanOfTokenAtPosition(sourceFile, node.pos); } - let pos = nodeIsMissing(errorNode) - ? errorNode.pos - : skipTrivia(sourceFile.text, errorNode.pos); + let pos = sourceFile && !nodeIsMissing(errorNode) + ? skipTrivia(sourceFile.text, errorNode.pos) + : errorNode.pos; return createTextSpanFromBounds(pos, errorNode.end); } From cef25bf99abbfcb9fe502b5a16c189a602f71ff9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 21:11:12 -0700 Subject: [PATCH 19/96] Only check source file when we have one. --- src/compiler/core.ts | 7 +++++-- src/compiler/utilities.ts | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 4b93081dc3133..51ff939c8bd4a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -301,8 +301,11 @@ module ts { Debug.assert(start >= 0, "start must be non-negative, is " + start); Debug.assert(length >= 0, "length must be non-negative, is " + length); - Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); - Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); + + if (file) { + Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); + Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); + } let text = getLocaleSpecificMessage(message.key); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bae860fb8baae..da333f90c751b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -165,6 +165,10 @@ module ts { return ""; } + if (!sourceFile && node.kind === SyntaxKind.Identifier) { + return (node).text; + } + let text = sourceFile.text; return text.substring(skipTrivia(text, node.pos), node.end); } From d886b0f893a1b8880dd3041cd7a8041056ff5e82 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 21:27:43 -0700 Subject: [PATCH 20/96] Rename property. Add walking for jsdoc nodes. --- src/compiler/parser.ts | 29 ++++++++++++++++++++++++++- src/compiler/types.ts | 2 +- tests/cases/unittests/jsDocParsing.ts | 16 +++++++-------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c06ff8af4b44c..bf391fb1bdc91 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -316,6 +316,33 @@ module ts { return visitNode(cbNode, (node).expression); case SyntaxKind.MissingDeclaration: return visitNodes(cbNodes, node.decorators); + case SyntaxKind.JSDocTypeExpression: + return visitNode(cbNode, (node).type); + case SyntaxKind.JSDocUnionType: + return visitNodes(cbNodes, (node).types); + case SyntaxKind.JSDocNonNullableType: + return visitNode(cbNode, (node).type); + case SyntaxKind.JSDocNullableType: + return visitNode(cbNode, (node).type); + case SyntaxKind.JSDocRecordType: + return visitNodes(cbNodes, (node).members); + case SyntaxKind.JSDocTypeReference: + return visitNode(cbNode, (node).name) || + visitNodes(cbNodes, (node).typeArguments); + case SyntaxKind.JSDocOptionalType: + return visitNode(cbNode, (node).type); + case SyntaxKind.JSDocFunctionType: + return visitNodes(cbNodes, (node).parameters) || + 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.JSDocMember: + return visitNode(cbNode, (node).name) || + visitNode(cbNode, (node).type); } } @@ -5625,7 +5652,7 @@ module ts { } members.end = scanner.getStartPos(); - result.member = members; + result.members = members; parseExpected(SyntaxKind.CloseBraceToken); return finishNode(result); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bb7d36b4ff162..d5049228434d6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1041,7 +1041,7 @@ module ts { } export interface JSDocRecordType extends JSDocType { - member: NodeArray; + members: NodeArray; } export interface JSDocTypeReference extends JSDocType { diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index cdd1144d4606d..4ab9a424e6004 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -83,7 +83,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 3, - "member": { + "members": { "length": 0, "pos": 2, "end": 2 @@ -97,7 +97,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 6, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -122,7 +122,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 14, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -158,7 +158,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 11, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -194,7 +194,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 19, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -241,7 +241,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 19, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -288,7 +288,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 27, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, @@ -346,7 +346,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 11, - "member": { + "members": { "0": { "kind": "JSDocMember", "pos": 2, From e8a3d24e0f10c85223adf61e3234afb1f935eedd Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 21:40:46 -0700 Subject: [PATCH 21/96] Set parent pointers for JSDoc comments. --- src/compiler/parser.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bf391fb1bdc91..a958463a2cefa 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -417,14 +417,14 @@ module ts { return 0; } - function fixupParentReferences(sourceFile: SourceFile) { + function fixupParentReferences(node: Node) { // normally parent references are set during binding. However, for clients that only need // a syntax tree, and no semantic features, then the binding process is an unnecessary // overhead. This functions allows us to set all the parents, without all the expense of // binding. - let parent: Node = sourceFile; - forEachChild(sourceFile, visitNode); + let parent: Node = node; + forEachChild(node, visitNode); return; function visitNode(n: Node): void { @@ -5429,7 +5429,12 @@ module ts { result.type = parseJSDocType(); parseExpected(SyntaxKind.CloseBraceToken); - return error ? undefined : finishNode(result); + if (error) { + return undefined; + } + + fixupParentReferences(result); + return finishNode(result); function nextToken(): SyntaxKind { return token = scanner.scan(); From d319e862d133cf6f2b42457d6ace948a39159465 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 21:51:27 -0700 Subject: [PATCH 22/96] Remove special casing for nodes without parents now that we are properly setting parents. --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 7 ++----- src/compiler/parser.ts | 3 ++- src/compiler/utilities.ts | 6 +----- tests/cases/unittests/jsDocParsing.ts | 4 ++-- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89bbcf80e26f2..f6ce452dd2b99 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2151,7 +2151,7 @@ module ts { let comments = getLeadingCommentRangesOfNode(node, sourceFile); if (comments) { for (let comment of comments) { - let jsDocComment = parseJSDocComment(sourceFile.text, comment.pos, comment.end - comment.pos); + let jsDocComment = parseJSDocComment(node, sourceFile.text, comment.pos, comment.end - comment.pos); if (jsDocComment) { return jsDocComment; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 51ff939c8bd4a..4b93081dc3133 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -301,11 +301,8 @@ module ts { Debug.assert(start >= 0, "start must be non-negative, is " + start); Debug.assert(length >= 0, "length must be non-negative, is " + length); - - if (file) { - Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); - Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); - } + Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); + Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); let text = getLocaleSpecificMessage(message.key); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a958463a2cefa..6982c4cb0980c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5761,7 +5761,7 @@ module ts { } /* @internal */ - export function parseJSDocComment(content: string, start?: number, length?: number): JSDocComment { + export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { start = start || 0; let end = length === undefined ? content.length : start + length; length = end - start; @@ -5878,6 +5878,7 @@ module ts { return undefined; } + typeExpression.parent = parent; pos = typeExpression.end; return typeExpression.type; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index da333f90c751b..b70e9dd4aeeb9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -165,10 +165,6 @@ module ts { return ""; } - if (!sourceFile && node.kind === SyntaxKind.Identifier) { - return (node).text; - } - let text = sourceFile.text; return text.substring(skipTrivia(text, node.pos), node.end); } @@ -306,7 +302,7 @@ module ts { return getSpanOfTokenAtPosition(sourceFile, node.pos); } - let pos = sourceFile && !nodeIsMissing(errorNode) + let pos = !nodeIsMissing(errorNode) ? skipTrivia(sourceFile.text, errorNode.pos) : errorNode.pos; diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 4ab9a424e6004..9b913201242ff 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -800,7 +800,7 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = ts.parseJSDocComment(content); + let comment = ts.parseJSDocComment(/*parent:*/ undefined, content); let result = JSON.stringify(comment, (k, v) => { return v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) @@ -810,7 +810,7 @@ module ts { } function parsesIncorrectly(content: string) { - let type = ts.parseJSDocComment(content); + let type = ts.parseJSDocComment(/*parent:*/ undefined, content); assert.equal(type, undefined); } From 047ac2c2f1836a81dfe3da342e141fb42d09b43e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 22:00:36 -0700 Subject: [PATCH 23/96] Use actual type parameter nodes in doc comments. --- src/compiler/parser.ts | 26 +++-- src/compiler/types.ts | 2 +- tests/cases/unittests/jsDocParsing.ts | 144 +++++++++++++++++++++++--- 3 files changed, 148 insertions(+), 24 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6982c4cb0980c..d05553e2681a6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5774,7 +5774,7 @@ module ts { let type : JSDocType; let parameters: JSDocParameter[]; let returnType: JSDocType; - let typeParameterNames: string[]; + let typeParameters: TypeParameterDeclaration[]; let pos: number; @@ -5839,11 +5839,11 @@ module ts { return error ? undefined : createJSDocComment(); function createJSDocComment(): JSDocComment { - if (!returnType && !type && !parameters && !typeParameterNames) { + if (!returnType && !type && !parameters && !typeParameters) { return undefined; } - return { returnType, type, parameters, typeParameterNames }; + return { returnType, type, parameters, typeParameters }; } function skipWhitespace(): void { @@ -5919,13 +5919,27 @@ module ts { } function handleTemplateTag(): void { - if (!typeParameterNames) { - typeParameterNames = []; + if (!typeParameters) { + typeParameters = []; while (!error) { skipWhitespace(); + + let startPos = pos; let name = scanIdentifier(); - typeParameterNames.push(name); + + let identifier = createNode(SyntaxKind.Identifier); + let typeParameter = createNode(SyntaxKind.TypeParameter); + + identifier.text = name; + typeParameter.name = identifier; + + identifier.pos = typeParameter.pos = startPos; + identifier.end = typeParameter.end = pos; + + fixupParentReferences(typeParameter); + typeParameter.parent = parent; + typeParameters.push(typeParameter); skipWhitespace(); if (content.charCodeAt(pos) !== CharacterCodes.comma) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d5049228434d6..61e3f4c4ec53e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1084,7 +1084,7 @@ module ts { type?: JSDocType; parameters?: JSDocParameter[]; returnType?: JSDocType; - typeParameterNames?: string[]; + typeParameters?: TypeParameterDeclaration[]; } // Source files are declarations when they are external modules. diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 9b913201242ff..821fcfa31a0fe 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1115,8 +1115,18 @@ module ts { * @template T */`, `{ - "typeParameterNames": [ - "T" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "T", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + } ] }`); }); @@ -1127,9 +1137,29 @@ module ts { * @template K,V */`, `{ - "typeParameterNames": [ - "K", - "V" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "K", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + }, + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "V", + "pos": 20, + "end": 21 + }, + "pos": 20, + "end": 21 + } ] }`); }); @@ -1140,9 +1170,29 @@ module ts { * @template K ,V */`, `{ - "typeParameterNames": [ - "K", - "V" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "K", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + }, + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "V", + "pos": 21, + "end": 22 + }, + "pos": 21, + "end": 22 + } ] }`); }); @@ -1153,9 +1203,29 @@ module ts { * @template K, V */`, `{ - "typeParameterNames": [ - "K", - "V" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "K", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + }, + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "V", + "pos": 21, + "end": 22 + }, + "pos": 21, + "end": 22 + } ] }`); }); @@ -1166,9 +1236,29 @@ module ts { * @template K , V */`, `{ - "typeParameterNames": [ - "K", - "V" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "K", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + }, + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "V", + "pos": 22, + "end": 23 + }, + "pos": 22, + "end": 23 + } ] }`); }); @@ -1179,9 +1269,29 @@ module ts { * @template K , V Description of type parameters. */`, `{ - "typeParameterNames": [ - "K", - "V" + "typeParameters": [ + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "K", + "pos": 18, + "end": 19 + }, + "pos": 18, + "end": 19 + }, + { + "kind": "TypeParameter", + "name": { + "kind": 65, + "text": "V", + "pos": 22, + "end": 23 + }, + "pos": 22, + "end": 23 + } ] }`); }); From 0cb45c5b2a2a9db88458fa41d34bb18913f3cae9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 22:44:25 -0700 Subject: [PATCH 24/96] Add support for generic type parameters in JSDoc comments. --- src/compiler/binder.ts | 13 +++++ src/compiler/checker.ts | 55 ++++++++++--------- src/compiler/parser.ts | 20 +++++++ src/compiler/utilities.ts | 15 +++++ .../fourslash/getJavaScriptCompletions5.ts | 14 +++++ 5 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions5.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 494570c85c1b3..313193439e807 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -255,12 +255,25 @@ module ts { setBlockScopeContainer(node, /*cleanLocals*/ (symbolKind & SymbolFlags.HasLocals) === 0 && node.kind !== SyntaxKind.SourceFile); } + if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.FunctionDeclaration) { + bindJSDocTypeParameters(node); + } + } + forEachChild(node, bind); container = saveContainer; parent = saveParent; blockScopeContainer = savedBlockScopeContainer; } + function bindJSDocTypeParameters(node: FunctionLikeDeclaration) { + let jsDocComment = getJSDocComment(node, file); + if (jsDocComment) { + forEach(jsDocComment.typeParameters, bind); + } + } + function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { switch (container.kind) { case SyntaxKind.ModuleDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f6ce452dd2b99..40d90b0c3f2c9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2147,20 +2147,6 @@ module ts { return undefined; } - function getJSDocComment(node: Node, sourceFile: SourceFile) { - let comments = getLeadingCommentRangesOfNode(node, sourceFile); - if (comments) { - for (let comment of comments) { - let jsDocComment = parseJSDocComment(node, sourceFile.text, comment.pos, comment.end - comment.pos); - if (jsDocComment) { - return jsDocComment; - } - } - } - - return undefined; - } - // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type { if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { @@ -3091,9 +3077,34 @@ module ts { return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind); } + function symbolsToArray(symbols: SymbolTable): Symbol[] { + let result: Symbol[] = []; + for (let id in symbols) { + if (!isReservedMemberName(id)) { + result.push(symbols[id]); + } + } + return result; + } + + function getTypeParametersFromSignatureDeclaration(declaration: SignatureDeclaration): TypeParameter[] { + if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { + let jsDocComment = getJSDocComment(declaration, getSourceFile(declaration)); + if (jsDocComment && jsDocComment.typeParameters) { + return getTypeParametersFromTypeParameterDeclarations(jsDocComment.typeParameters); + } + } + + if (declaration.typeParameters) { + return getTypeParametersFromTypeParameterDeclarations(declaration.typeParameters); + } + + return undefined; + } + // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(typeParameterDeclarations: TypeParameterDeclaration[]): TypeParameter[] { + function getTypeParametersFromTypeParameterDeclarations(typeParameterDeclarations: TypeParameterDeclaration[]): TypeParameter[] { let result: TypeParameter[] = []; forEach(typeParameterDeclarations, node => { let tp = getDeclaredTypeOfTypeParameter(node.symbol); @@ -3104,22 +3115,12 @@ module ts { return result; } - function symbolsToArray(symbols: SymbolTable): Symbol[] { - let result: Symbol[] = []; - for (let id in symbols) { - if (!isReservedMemberName(id)) { - result.push(symbols[id]); - } - } - return result; - } - function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature { let links = getNodeLinks(declaration); if (!links.resolvedSignature) { let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClass((declaration.parent).symbol) : undefined; - let typeParameters = classType ? classType.typeParameters : - declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined; + let typeParameters = classType ? classType.typeParameters : getTypeParametersFromSignatureDeclaration(declaration); + let parameters: Symbol[] = []; let hasStringLiterals = false; let minArgumentCount = -1; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d05553e2681a6..42fa644b5861c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -470,6 +470,7 @@ module ts { // Ditch any existing LS children we may have created. This way we can avoid // moving them forward. node._children = undefined; + node._docComment = undefined; node.pos += delta; node.end += delta; @@ -904,6 +905,7 @@ module ts { intersectsChange: boolean length?: number; _children: Node[]; + _docComment: JSDocComment; } interface IncrementalNode extends Node, IncrementalElement { @@ -5760,8 +5762,26 @@ module ts { } } + interface NodeWithComment extends Node { + _docComment: JSDocComment; + } + /* @internal */ export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { + let nodeWithComment = parent; + if (nodeWithComment && nodeWithComment._docComment) { + return nodeWithComment._docComment; + } + + let result = parseJSDocCommentWorker(parent, content, start, length); + if (nodeWithComment && result) { + nodeWithComment._docComment = result; + } + + return result; + } + + function parseJSDocCommentWorker(parent: Node, content: string, start: number, length: number): JSDocComment { start = start || 0; let end = length === undefined ? content.length : start + length; length = end - start; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b70e9dd4aeeb9..e5f58c0a77678 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1818,4 +1818,19 @@ module ts { export function isJavaScript(fileName: string) { return fileExtensionIs(fileName, ".js"); } + + /* @internal */ + export function getJSDocComment(node: Node, sourceFile: SourceFile) { + let comments = getLeadingCommentRangesOfNode(node, sourceFile); + if (comments) { + for (let comment of comments) { + let jsDocComment = parseJSDocComment(node, sourceFile.text, comment.pos, comment.end - comment.pos); + if (jsDocComment) { + return jsDocComment; + } + } + } + + return undefined; + } } diff --git a/tests/cases/fourslash/getJavaScriptCompletions5.ts b/tests/cases/fourslash/getJavaScriptCompletions5.ts new file mode 100644 index 0000000000000..0cd0af6aab75c --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions5.ts @@ -0,0 +1,14 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @template T +//// * @param {T} a +//// * @return {T} */ +////function foo(a) { } +////foo(1)./**/ + +debugger; +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From 7ff85b30c3e7633179d0866eab2ecf774baa0b9b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 7 Apr 2015 23:03:49 -0700 Subject: [PATCH 25/96] Only clear children if they exist. --- src/compiler/parser.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 42fa644b5861c..6290fc7cefaa2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -469,8 +469,14 @@ module ts { // Ditch any existing LS children we may have created. This way we can avoid // moving them forward. - node._children = undefined; - node._docComment = undefined; + if (node._children) { + node._children = undefined; + } + + if (node._docComment) { + node._docComment = undefined; + } + node.pos += delta; node.end += delta; From 8564a8bd0d7720f4ab335f50ac994f94e2e17c2e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 8 Apr 2015 00:20:44 -0700 Subject: [PATCH 26/96] Add support for variadic JSDoc types. --- src/compiler/checker.ts | 9 +++++++- src/compiler/utilities.ts | 21 ++++++++++++++++++- .../fourslash/getJavaScriptCompletions6.ts | 14 +++++++++++++ .../fourslash/getJavaScriptCompletions7.ts | 13 ++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions6.ts create mode 100644 tests/cases/fourslash/getJavaScriptCompletions7.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 40d90b0c3f2c9..07aa699e98f9d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3710,7 +3710,7 @@ module ts { // NYI: break; case SyntaxKind.JSDocVariadicType: - return getTypeFromJSDocType((jsDocType).type); + return getTypeFromJSDocVariadicType(jsDocType); case SyntaxKind.JSDocConstructorType: // NYI: break; @@ -3721,6 +3721,13 @@ module ts { } } + function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { + let type = getTypeFromJSDocType(node.type); + if (type) { + return createArrayType(type); + } + } + function getTypeForJSDocTypeReference(node: JSDocTypeReference): Type { if (node.name.kind === SyntaxKind.Identifier) { switch ((node.name).text) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e5f58c0a77678..3f768486dfe72 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -820,7 +820,26 @@ module ts { } export function hasRestParameters(s: SignatureDeclaration): boolean { - return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; + let lastParameter = lastOrUndefined(s.parameters); + if (!lastParameter) { + return false; + } + + if (s.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (lastParameter.name.kind === SyntaxKind.Identifier) { + let lastParameterName = (lastParameter.name).text; + + let docComment = getJSDocComment(s, getSourceFileOfNode(s)); + if (docComment) { + let parameter = forEach(docComment.parameters, p => p.name === lastParameterName ? p : undefined); + if (parameter) { + return parameter.type.kind === SyntaxKind.JSDocVariadicType; + } + } + } + } + + return lastParameter.dotDotDotToken !== undefined; } export function isLiteralKind(kind: SyntaxKind): boolean { diff --git a/tests/cases/fourslash/getJavaScriptCompletions6.ts b/tests/cases/fourslash/getJavaScriptCompletions6.ts new file mode 100644 index 0000000000000..efbc208838338 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions6.ts @@ -0,0 +1,14 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @param {...number} a +//// */ +////function foo(a) { +//// a./**/ +////} + +debugger; +goTo.marker(); +verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptCompletions7.ts b/tests/cases/fourslash/getJavaScriptCompletions7.ts new file mode 100644 index 0000000000000..d8b01cfb757c2 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions7.ts @@ -0,0 +1,13 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @param {...number} a +//// */ +////function foo(a) { +//// a[0]./**/ +////} + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From cd2d5cd71028c9c9f8bcc2461302ee66e48f2a6e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 8 Apr 2015 00:53:23 -0700 Subject: [PATCH 27/96] Property show variadic parameters for javascript functions. --- src/compiler/checker.ts | 18 +++++++++++++++++- src/compiler/utilities.ts | 4 ---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07aa699e98f9d..fcb893b874be9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1738,8 +1738,24 @@ module ts { } } + function isVariadic(node: Node) { + if (node && node.kind === SyntaxKind.Parameter) { + let parameter = node; + if (isFunctionLike(parameter.parent)) { + let functionParent = parameter.parent; + if (parameter === lastOrUndefined(functionParent.parameters) && + hasRestParameters(functionParent)) { + + return true; + } + } + + return parameter.dotDotDotToken !== undefined; + } + } + function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { - if (hasDotDotDotToken(p.valueDeclaration)) { + if (isVariadic(p.valueDeclaration)) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3f768486dfe72..a26650112d30f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -796,10 +796,6 @@ module ts { } } - export function hasDotDotDotToken(node: Node) { - return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; - } - export function hasQuestionToken(node: Node) { if (node) { switch (node.kind) { From 2cb375a460f0bcf0a266d9dfe48805385d58421a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 8 Apr 2015 01:13:27 -0700 Subject: [PATCH 28/96] Share code for getting information about a parameter from a JSDoc comment. --- src/compiler/checker.ts | 27 ++++++++++++++++----------- src/compiler/utilities.ts | 30 ++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcb893b874be9..f6cc648d8bc47 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2145,18 +2145,12 @@ module ts { return docComment.type; } } - else if (declaration.kind === SyntaxKind.Parameter && (declaration).name.kind === SyntaxKind.Identifier) { + else if (declaration.kind === SyntaxKind.Parameter) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. - let parameterName = ((declaration).name).text; - - docComment = getJSDocComment(declaration.parent, sourceFile); - if (docComment && docComment.parameters) { - for (let parameter of docComment.parameters) { - if (parameter.name === parameterName) { - return parameter.type; - } - } + let parameter = getJSDocParameter(declaration, sourceFile); + if (parameter) { + return parameter.type; } } @@ -3131,6 +3125,17 @@ module ts { return result; } + function isVariadicOrOptional(node: ParameterDeclaration) { + if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + let docParam = getJSDocParameter(node, getSourceFile(node)); + if (docParam) { + return docParam.type.kind === SyntaxKind.JSDocVariadicType || docParam.type.kind === SyntaxKind.JSDocOptionalType; + } + } + + return !!(node.initializer || node.questionToken || node.dotDotDotToken); + } + function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature { let links = getNodeLinks(declaration); if (!links.resolvedSignature) { @@ -3147,7 +3152,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (param.initializer || param.questionToken || param.dotDotDotToken) { + if (isVariadicOrOptional(param)) { minArgumentCount = i; } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a26650112d30f..80fc03965c490 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -815,6 +815,23 @@ module ts { return false; } + export function getJSDocParameter(parameter: ParameterDeclaration, sourceFile: SourceFile): JSDocParameter { + if (parameter.name.kind === SyntaxKind.Identifier) { + // If it's a parameter, see if the parent has a jsdoc comment with an @param + // annotation. + let parameterName = (parameter.name).text; + + let docComment = getJSDocComment(parameter.parent, sourceFile); + if (docComment && docComment.parameters) { + for (let parameter of docComment.parameters) { + if (parameter.name === parameterName) { + return parameter; + } + } + } + } + } + export function hasRestParameters(s: SignatureDeclaration): boolean { let lastParameter = lastOrUndefined(s.parameters); if (!lastParameter) { @@ -822,16 +839,9 @@ module ts { } if (s.parserContextFlags & ParserContextFlags.JavaScriptFile) { - if (lastParameter.name.kind === SyntaxKind.Identifier) { - let lastParameterName = (lastParameter.name).text; - - let docComment = getJSDocComment(s, getSourceFileOfNode(s)); - if (docComment) { - let parameter = forEach(docComment.parameters, p => p.name === lastParameterName ? p : undefined); - if (parameter) { - return parameter.type.kind === SyntaxKind.JSDocVariadicType; - } - } + let parameter = getJSDocParameter(lastParameter, getSourceFileOfNode(lastParameter)); + if (parameter) { + return parameter.type.kind === SyntaxKind.JSDocVariadicType; } } From c8d8e0b41c16134804209833e40df974f8e755b7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 8 Apr 2015 01:23:43 -0700 Subject: [PATCH 29/96] Simplify parameter handling code. --- src/compiler/checker.ts | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f6cc648d8bc47..9073811f538ac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1738,28 +1738,13 @@ module ts { } } - function isVariadic(node: Node) { - if (node && node.kind === SyntaxKind.Parameter) { - let parameter = node; - if (isFunctionLike(parameter.parent)) { - let functionParent = parameter.parent; - if (parameter === lastOrUndefined(functionParent.parameters) && - hasRestParameters(functionParent)) { - - return true; - } - } - - return parameter.dotDotDotToken !== undefined; - } - } - function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { - if (isVariadic(p.valueDeclaration)) { + let parameterNode = p.valueDeclaration; + if (isVariadic(parameterNode)) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); - if (hasQuestionToken(p.valueDeclaration) || (p.valueDeclaration).initializer) { + if (isOptional(parameterNode)) { writePunctuation(writer, SyntaxKind.QuestionToken); } writePunctuation(writer, SyntaxKind.ColonToken); @@ -3126,14 +3111,30 @@ module ts { } function isVariadicOrOptional(node: ParameterDeclaration) { + return isVariadic(node) || isOptional(node); + } + + function isVariadic(node: ParameterDeclaration) { + if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + let docParam = getJSDocParameter(node, getSourceFile(node)); + if (docParam) { + return docParam.type.kind === SyntaxKind.JSDocVariadicType; + } + } + + return node.dotDotDotToken !== undefined; + } + + + function isOptional(node: ParameterDeclaration) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { let docParam = getJSDocParameter(node, getSourceFile(node)); if (docParam) { - return docParam.type.kind === SyntaxKind.JSDocVariadicType || docParam.type.kind === SyntaxKind.JSDocOptionalType; + return docParam.type.kind === SyntaxKind.JSDocOptionalType; } } - return !!(node.initializer || node.questionToken || node.dotDotDotToken); + return hasQuestionToken(node) || !!node.initializer; } function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature { From e8e1819f6494b59d8a7e2158ecfbc884932e73dc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 8 Apr 2015 01:36:04 -0700 Subject: [PATCH 30/96] Report error when ... is used in a .js file. --- .../diagnosticInformationMap.generated.ts | 1 - src/compiler/diagnosticMessages.json | 4 ---- src/services/services.ts | 6 +++++- .../getJavaScriptSemanticDiagnostics16.ts | 2 +- .../getJavaScriptSemanticDiagnostics22.ts | 15 +++++++++++++++ 5 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index b4380f4d2deaf..debb7bc7817f8 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -518,7 +518,6 @@ module ts { types_can_only_be_used_in_a_ts_file: { code: 8010, category: DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." }, type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." }, parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." }, - can_only_be_used_in_a_ts_file: { code: 8013, category: DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." }, property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." }, enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." }, type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index fe349b783439b..72cb3381f152a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2065,10 +2065,6 @@ "category": "Error", "code": 8012 }, - "'?' can only be used in a .ts file.": { - "category": "Error", - "code": 8013 - }, "'property declarations' can only be used in a .ts file.": { "category": "Error", "code": 8014 diff --git a/src/services/services.ts b/src/services/services.ts index 43f3da55f96a5..bf7cec87ec81b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2550,7 +2550,11 @@ module ts { return true; } if (parameter.questionToken) { - diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics.can_only_be_used_in_a_ts_file)); + diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); + return true; + } + if (parameter.dotDotDotToken) { + diagnostics.push(createDiagnosticForNode(parameter.dotDotDotToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "...")); return true; } if (parameter.type) { diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts index 2ccac13dbf9ea..1e114532c79d5 100644 --- a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts +++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics16.ts @@ -10,6 +10,6 @@ verify.getSemanticDiagnostics(`[ "start": 12, "length": 1, "category": "error", - "code": 8013 + "code": 8009 } ]`); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts new file mode 100644 index 0000000000000..8ad0d57922b3e --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts @@ -0,0 +1,15 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: a.js +//// function foo(...a) {} + +verify.getSemanticDiagnostics(`[ + { + "message": "'...' can only be used in a .ts file.", + "start": 13, + "length": 3, + "category": "error", + "code": 8009 + } +]`); \ No newline at end of file From e0837f8954bfc972862e21cd460ca1be347057e6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 11 Apr 2015 18:04:27 -0700 Subject: [PATCH 31/96] Treat JSDoc types as actual Typenodes. --- src/compiler/parser.ts | 13 ++++- src/compiler/types.ts | 4 +- .../fourslash/getJavaScriptCompletions8.ts | 12 +++++ tests/cases/unittests/jsDocParsing.ts | 52 +++++++++++++------ 4 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions8.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 58bf974f7e2ae..8b05d52475ec6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5549,7 +5549,7 @@ module ts { nextToken(); parseExpected(SyntaxKind.OpenParenToken); - let parameters = >[]; + let parameters = >[]; parameters.pos = scanner.getStartPos(); while (!error && token !== SyntaxKind.CloseParenToken) { @@ -5557,7 +5557,16 @@ module ts { parseExpected(SyntaxKind.CommaToken); } - parameters.push(parseJSDocType()); + let parameterType = parseJSDocType(); + if (!parameterType) { + return undefined; + } + + let parameter = createNode(SyntaxKind.Parameter, parameterType.pos); + parameter.type = parameterType; + finishNode(parameter); + + parameters.push(parameter); } parameters.end = scanner.getStartPos(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4c7ffbd3cfb48..fb1ba5bf7524a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1018,7 +1018,7 @@ module ts { type: JSDocType; } - export interface JSDocType extends Node { + export interface JSDocType extends TypeNode { _jsDocTypeBrand: any; } @@ -1056,7 +1056,7 @@ module ts { } export interface JSDocFunctionType extends JSDocType { - parameters: NodeArray; + parameters: NodeArray; type: JSDocType; } diff --git a/tests/cases/fourslash/getJavaScriptCompletions8.ts b/tests/cases/fourslash/getJavaScriptCompletions8.ts new file mode 100644 index 0000000000000..418aae676bee5 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions8.ts @@ -0,0 +1,12 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @type {function(): number} +//// */ +////var v; +////v()./**/ + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 821fcfa31a0fe..8fac15187b7ec 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -423,25 +423,35 @@ module ts { "end": 26, "parameters": { "0": { - "kind": "JSDocTypeReference", + "kind": "Parameter", "pos": 10, "end": 16, - "name": { - "kind": "Identifier", + "type": { + "kind": "JSDocTypeReference", "pos": 10, "end": 16, - "text": "string" + "name": { + "kind": "Identifier", + "pos": 10, + "end": 16, + "text": "string" + } } }, "1": { - "kind": "JSDocTypeReference", + "kind": "Parameter", "pos": 17, "end": 25, - "name": { - "kind": "Identifier", + "type": { + "kind": "JSDocTypeReference", "pos": 17, "end": 25, - "text": "boolean" + "name": { + "kind": "Identifier", + "pos": 17, + "end": 25, + "text": "boolean" + } } }, "length": 2, @@ -459,25 +469,35 @@ module ts { "end": 26, "parameters": { "0": { - "kind": "JSDocTypeReference", + "kind": "Parameter", "pos": 10, "end": 16, - "name": { - "kind": "Identifier", + "type": { + "kind": "JSDocTypeReference", "pos": 10, "end": 16, - "text": "string" + "name": { + "kind": "Identifier", + "pos": 10, + "end": 16, + "text": "string" + } } }, "1": { - "kind": "JSDocTypeReference", + "kind": "Parameter", "pos": 17, "end": 25, - "name": { - "kind": "Identifier", + "type": { + "kind": "JSDocTypeReference", "pos": 17, "end": 25, - "text": "boolean" + "name": { + "kind": "Identifier", + "pos": 17, + "end": 25, + "text": "boolean" + } } }, "length": 2, From c4ee83886a7ae230d13f3df9fe9d8ad60604a675 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 11 Apr 2015 18:15:45 -0700 Subject: [PATCH 32/96] Use a single getTypeFromTypeNode function for normal types and JSDocTypes. --- src/compiler/checker.ts | 90 ++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07055f16a85a7..df1f0f012f72b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2112,7 +2112,7 @@ module ts { function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) { let jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); - return getTypeFromJSDocType(jsDocType); + return getTypeFromTypeNode(jsDocType); } function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { @@ -3734,43 +3734,8 @@ module ts { return links.resolvedType; } - function getTypeFromJSDocType(jsDocType: JSDocType): Type { - if (jsDocType) { - switch (jsDocType.kind) { - case SyntaxKind.JSDocAllType: - return anyType; - case SyntaxKind.JSDocUnknownType: - return unknownType; - case SyntaxKind.JSDocUnionType: - return getTypeFromJSDocUnionType(jsDocType); - case SyntaxKind.JSDocNullableType: - return getTypeFromJSDocType((jsDocType).type); - case SyntaxKind.JSDocNonNullableType: - return getTypeFromJSDocType((jsDocType).type); - case SyntaxKind.JSDocRecordType: - // NYI: - break; - case SyntaxKind.JSDocTypeReference: - return getTypeForJSDocTypeReference(jsDocType); - case SyntaxKind.JSDocOptionalType: - return getTypeFromJSDocType((jsDocType).type); - case SyntaxKind.JSDocFunctionType: - // NYI: - break; - case SyntaxKind.JSDocVariadicType: - return getTypeFromJSDocVariadicType(jsDocType); - case SyntaxKind.JSDocConstructorType: - // NYI: - break; - case SyntaxKind.JSDocThisType: - // NYI: - break; - } - } - } - function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { - let type = getTypeFromJSDocType(node.type); + let type = getTypeFromTypeNode(node.type); if (type) { return createArrayType(type); } @@ -3793,7 +3758,7 @@ module ts { if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { let typeParameters = (type).typeParameters; if (node.typeArguments && node.typeArguments.length === typeParameters.length) { - let typeArguments = map(node.typeArguments, getTypeFromJSDocType); + let typeArguments = map(node.typeArguments, getTypeFromTypeNode); for (let typeArgument in typeArguments) { if (!typeArgument) { return undefined; @@ -3811,7 +3776,22 @@ module ts { } function getTypeFromJSDocUnionType(node: JSDocUnionType): Type { - return getUnionType(map(node.types, getTypeFromJSDocType), /*noSubtypeReduction*/ true); + let types = map(node.types, getTypeFromTypeNode); + for (let type of types) { + if (!type) { + return undefined; + } + } + + return getUnionType(types, /*noSubtypeReduction*/ true); + } + + function getTypeFromTypeNode(node: TypeNode): Type { + if (!node) { + return undefined; + } + + return getTypeFromTypeNodeOrHeritageClauseElement(node); } function getTypeFromTypeNodeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type { @@ -3843,7 +3823,7 @@ module ts { case SyntaxKind.UnionType: return getTypeFromUnionTypeNode(node); case SyntaxKind.ParenthesizedType: - return getTypeFromTypeNodeOrHeritageClauseElement((node).type); + return getTypeFromTypeNode((node).type); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: case SyntaxKind.TypeLiteral: @@ -3856,6 +3836,34 @@ module ts { return symbol && getDeclaredTypeOfSymbol(symbol); default: return unknownType; + case SyntaxKind.JSDocAllType: + return anyType; + case SyntaxKind.JSDocUnknownType: + return unknownType; + case SyntaxKind.JSDocUnionType: + return getTypeFromJSDocUnionType(node); + case SyntaxKind.JSDocNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocNonNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocRecordType: + // NYI: + break; + case SyntaxKind.JSDocTypeReference: + return getTypeForJSDocTypeReference(node); + case SyntaxKind.JSDocOptionalType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocFunctionType: + // NYI: + break; + case SyntaxKind.JSDocVariadicType: + return getTypeFromJSDocVariadicType(node); + case SyntaxKind.JSDocConstructorType: + // NYI: + break; + case SyntaxKind.JSDocThisType: + // NYI: + break; } } @@ -7360,7 +7368,7 @@ module ts { function getReturnTypeFromJSDocComment(func: FunctionLikeDeclaration): Type { let jsDocComment = getJSDocComment(func, getSourceFile(func)); if (jsDocComment && jsDocComment.returnType) { - return getTypeFromJSDocType(jsDocComment.returnType); + return getTypeFromTypeNode(jsDocComment.returnType); } } From 8622b35a1f6068765d7fe3ac174d5b74f6729201 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 11 Apr 2015 18:37:27 -0700 Subject: [PATCH 33/96] initial support for function types. --- src/compiler/binder.ts | 21 +++++++++++---------- src/compiler/checker.ts | 27 +++++++++++++++++++++++++-- src/compiler/types.ts | 2 +- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 88962cfb2950e..2ddf287649aea 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -52,6 +52,17 @@ module ts { } } + /* @internal */ + export function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolKind: SymbolFlags) { + symbol.flags |= symbolKind; + if (!symbol.declarations) symbol.declarations = []; + symbol.declarations.push(node); + if (symbolKind & SymbolFlags.HasExports && !symbol.exports) symbol.exports = {}; + if (symbolKind & SymbolFlags.HasMembers && !symbol.members) symbol.members = {}; + node.symbol = symbol; + if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node; + } + export function bindSourceFile(file: SourceFile): void { let start = new Date().getTime(); bindSourceFileWorker(file); @@ -86,16 +97,6 @@ module ts { } } - function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolKind: SymbolFlags) { - symbol.flags |= symbolKind; - if (!symbol.declarations) symbol.declarations = []; - symbol.declarations.push(node); - if (symbolKind & SymbolFlags.HasExports && !symbol.exports) symbol.exports = {}; - if (symbolKind & SymbolFlags.HasMembers && !symbol.members) symbol.members = {}; - node.symbol = symbol; - if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node; - } - // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. function getDeclarationName(node: Declaration): string { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index df1f0f012f72b..ce5f93d02818f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3230,6 +3230,7 @@ module ts { case SyntaxKind.SetAccessor: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: + case SyntaxKind.JSDocFunctionType: // Don't include signature if node is the implementation of an overloaded function. A node is considered // an implementation node if it has a body and the previous node is of the same kind and immediately // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). @@ -3734,6 +3735,29 @@ module ts { return links.resolvedType; } + function getTypeFromJSDocFunctionType(node: JSDocFunctionType): Type { + let isConstructSignature = node.parameters.length > 0 && node.parameters[0].kind === SyntaxKind.JSDocConstructorType; + let name = isConstructSignature ? "__new" : "__call"; + + let symbol = createSymbol(SymbolFlags.Signature, name); + addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); + node.locals = {}; + for (let i = isConstructSignature ? 1 : 0; i < node.parameters.length; i++) { + let paramName = "p" + i; + let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, name); + addDeclarationToSymbol(paramSymbol, node.parameters[i], SymbolFlags.FunctionScopedVariable); + + node.locals[paramName] = paramSymbol; + } + + let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); + typeLiteralSymbol.members = {}; + typeLiteralSymbol.members[name] = symbol + + return createObjectType(TypeFlags.Anonymous, typeLiteralSymbol); + } + function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { let type = getTypeFromTypeNode(node.type); if (type) { @@ -3854,8 +3878,7 @@ module ts { case SyntaxKind.JSDocOptionalType: return getTypeFromTypeNode((node).type); case SyntaxKind.JSDocFunctionType: - // NYI: - break; + return getTypeFromJSDocFunctionType(node); case SyntaxKind.JSDocVariadicType: return getTypeFromJSDocVariadicType(node); case SyntaxKind.JSDocConstructorType: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fb1ba5bf7524a..8f04ed4141a4c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1055,7 +1055,7 @@ module ts { type: JSDocType; } - export interface JSDocFunctionType extends JSDocType { + export interface JSDocFunctionType extends JSDocType, SignatureDeclaration { parameters: NodeArray; type: JSDocType; } From e7f61e679f87a1f0ad1e94431dc80930feb0500f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 11 Apr 2015 19:28:36 -0700 Subject: [PATCH 34/96] Add support for JSDoc construct signatures. --- src/compiler/checker.ts | 45 ++++++++++++++----- src/compiler/utilities.ts | 4 ++ .../fourslash/getJavaScriptCompletions9.ts | 12 +++++ 3 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions9.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce5f93d02818f..c5a83d16beb6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3138,6 +3138,10 @@ module ts { function isVariadic(node: ParameterDeclaration) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { + return true; + } + let docParam = getJSDocParameter(node, getSourceFile(node)); if (docParam) { return docParam.type.kind === SyntaxKind.JSDocVariadicType; @@ -3150,6 +3154,10 @@ module ts { function isOptional(node: ParameterDeclaration) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (node.type && node.type.kind === SyntaxKind.JSDocOptionalType) { + return true; + } + let docParam = getJSDocParameter(node, getSourceFile(node)); if (docParam) { return docParam.type.kind === SyntaxKind.JSDocOptionalType; @@ -3162,13 +3170,16 @@ module ts { function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature { let links = getNodeLinks(declaration); if (!links.resolvedSignature) { - let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClass((declaration.parent).symbol) : undefined; - let typeParameters = classType ? classType.typeParameters : getTypeParametersFromSignatureDeclaration(declaration); - let parameters: Symbol[] = []; let hasStringLiterals = false; let minArgumentCount = -1; - for (let i = 0, n = declaration.parameters.length; i < n; i++) { + let returnType: Type; + + let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClass((declaration.parent).symbol) : undefined; + let typeParameters = classType ? classType.typeParameters : getTypeParametersFromSignatureDeclaration(declaration); + let isJSConstructSignature = isJSDocConstructSignature(declaration); + + for (let i = isJSConstructSignature ? 1 : 0, n = declaration.parameters.length; i < n; i++) { let param = declaration.parameters[i]; parameters.push(param.symbol); if (param.type && param.type.kind === SyntaxKind.StringLiteral) { @@ -3185,12 +3196,18 @@ module ts { minArgumentCount = declaration.parameters.length; } - let returnType: Type; + if (isJSConstructSignature) { + minArgumentCount--; + } + if (classType) { returnType = classType; } + else if (isJSConstructSignature) { + returnType = getTypeFromTypeNode(declaration.parameters[0].type); + } else if (declaration.type) { - returnType = getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); + returnType = getTypeFromTypeNode(declaration.type); } else { // TypeScript 1.0 spec (April 2014): @@ -3735,8 +3752,14 @@ module ts { return links.resolvedType; } + function isJSDocConstructSignature(node: SignatureDeclaration) { + return node.kind === SyntaxKind.JSDocFunctionType && + node.parameters.length > 0 && + node.parameters[0].type.kind === SyntaxKind.JSDocConstructorType; + } + function getTypeFromJSDocFunctionType(node: JSDocFunctionType): Type { - let isConstructSignature = node.parameters.length > 0 && node.parameters[0].kind === SyntaxKind.JSDocConstructorType; + let isConstructSignature = isJSDocConstructSignature(node); let name = isConstructSignature ? "__new" : "__call"; let symbol = createSymbol(SymbolFlags.Signature, name); @@ -3744,7 +3767,7 @@ module ts { node.locals = {}; for (let i = isConstructSignature ? 1 : 0; i < node.parameters.length; i++) { let paramName = "p" + i; - let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, name); + let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, paramName); addDeclarationToSymbol(paramSymbol, node.parameters[i], SymbolFlags.FunctionScopedVariable); node.locals[paramName] = paramSymbol; @@ -3882,8 +3905,7 @@ module ts { case SyntaxKind.JSDocVariadicType: return getTypeFromJSDocVariadicType(node); case SyntaxKind.JSDocConstructorType: - // NYI: - break; + return getTypeFromTypeNode((node).type); case SyntaxKind.JSDocThisType: // NYI: break; @@ -7340,7 +7362,8 @@ module ts { if (declaration && declaration.kind !== SyntaxKind.Constructor && declaration.kind !== SyntaxKind.ConstructSignature && - declaration.kind !== SyntaxKind.ConstructorType) { + declaration.kind !== SyntaxKind.ConstructorType && + !isJSDocConstructSignature(declaration)) { // When resolved signature is a call signature (and not a construct signature) the result type is any if (compilerOptions.noImplicitAny) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6b1acc0ed9724..1f7164ff8a931 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -876,6 +876,10 @@ module ts { } if (s.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (lastParameter.type && lastParameter.type.kind === SyntaxKind.JSDocVariadicType) { + return true; + } + let parameter = getJSDocParameter(lastParameter, getSourceFileOfNode(lastParameter)); if (parameter) { return parameter.type.kind === SyntaxKind.JSDocVariadicType; diff --git a/tests/cases/fourslash/getJavaScriptCompletions9.ts b/tests/cases/fourslash/getJavaScriptCompletions9.ts new file mode 100644 index 0000000000000..1619a2ca9fc49 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions9.ts @@ -0,0 +1,12 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @type {function(new:number)} +//// */ +////var v; +////new v()./**/ + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From 17d80e7f05804209d3dcb2c86642d17a2ec9a004 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 12 Apr 2015 13:33:25 -0700 Subject: [PATCH 35/96] additional test. --- tests/cases/fourslash/getJavaScriptCompletions10.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions10.ts diff --git a/tests/cases/fourslash/getJavaScriptCompletions10.ts b/tests/cases/fourslash/getJavaScriptCompletions10.ts new file mode 100644 index 0000000000000..e69de29bb2d1d From 7d2dd0c944a17c6c2fa081e0f26d006bfe2248c5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 13 Apr 2015 18:44:15 -0700 Subject: [PATCH 36/96] Updating baselines. --- .../diagnosticInformationMap.generated.ts | 1 + .../reference/APISample_compile.types | 66 ++++++------- .../reference/APISample_linter.types | 96 +++++++++---------- .../reference/APISample_transform.types | 12 +-- .../reference/APISample_watcher.types | 96 +++++++++---------- 5 files changed, 136 insertions(+), 135 deletions(-) diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index c256d10b7791a..8893642481fdd 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -1,5 +1,6 @@ // /// +/* @internal */ module ts { export var Diagnostics = { Unterminated_string_literal: { code: 1002, category: DiagnosticCategory.Error, key: "Unterminated string literal." }, diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index d147ded3f0e94..d74de21b8515f 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -23,37 +23,37 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) >ts : any, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1074, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1146, 5)) var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1201, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1273, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1201, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1273, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) var emitResult = program.emit(); >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) >program.emit() : ts.EmitResult ->program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 767, 39)) +>program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 839, 39)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 767, 39)) +>emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 839, 39)) var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); >allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1199, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1271, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1199, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1271, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 820, 29)) +>emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 820, 29)) +>diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) allDiagnostics.forEach(diagnostic => { >allDiagnostics.forEach(diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); }) : void @@ -67,24 +67,24 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >'\n' : string console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); @@ -93,11 +93,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) >log : any >`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >1 : number @@ -111,9 +111,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var exitCode = emitResult.emitSkipped ? 1 : 0; >exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) >emitResult.emitSkipped ? 1 : 0 : number ->emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 819, 26)) +>emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 891, 26)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 819, 26)) +>emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 891, 26)) >1 : number >0 : number @@ -153,16 +153,16 @@ compile(process.argv.slice(2), { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS >target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45)) ->ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1117, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5)) +>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1189, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5)) ->ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1117, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) +>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1189, 16)) >module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) }); diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index c285bc15390d8..70b8806c29669 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 740, 5), Decl(typescript.d.ts, 1261, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1333, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,12 +33,12 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 296, 5), Decl(typescript.d.ts, 1221, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1293, 32)) switch (node.kind) { ->node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) case ts.SyntaxKind.ForStatement: >ts.SyntaxKind.ForStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForStatement, Decl(typescript.d.ts, 209, 29)) @@ -70,15 +70,15 @@ export function delint(sourceFile: ts.SourceFile) { if ((node).statement.kind !== ts.SyntaxKind.Block) { >(node).statement.kind !== ts.SyntaxKind.Block : boolean ->(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) ->(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 589, 52)) +>(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 603, 52)) >(node) : ts.IterationStatement >node : ts.IterationStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 588, 5)) +>IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 602, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 589, 52)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 603, 52)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -105,16 +105,16 @@ export function delint(sourceFile: ts.SourceFile) { >(node) : ts.IfStatement >node : ts.IfStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 583, 5)) +>IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 597, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) { >ifStatement.thenStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 585, 31)) +>ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 585, 31)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -124,25 +124,25 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); >report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 585, 31)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 585, 31)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) >"An if statement's contents should be wrapped in a block body." : string } if (ifStatement.elseStatement && >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && >ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -151,11 +151,11 @@ export function delint(sourceFile: ts.SourceFile) { ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) { >ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) >ts.SyntaxKind.IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -165,9 +165,9 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); >report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 586, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) >"An else statement's contents should be wrapped in a block body." : string } break; @@ -181,15 +181,15 @@ export function delint(sourceFile: ts.SourceFile) { let op = (node).operatorToken.kind; >op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) ->(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 497, 25)) +>(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 511, 25)) >(node) : ts.BinaryExpression >node : ts.BinaryExpression >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 495, 5)) +>BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 509, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 497, 25)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 297, 38)) +>operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 511, 25)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) { >op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken : boolean @@ -219,9 +219,9 @@ export function delint(sourceFile: ts.SourceFile) { ts.forEachChild(node, delintNode); >ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1186, 48)) +>ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1258, 48)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1186, 48)) +>forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1258, 48)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) } @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 296, 5), Decl(typescript.d.ts, 1221, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1293, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1226, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1298, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1226, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1298, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -251,9 +251,9 @@ export function delint(sourceFile: ts.SourceFile) { >console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) >log : any >`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}` : string ->sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) +>sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >1 : number @@ -286,9 +286,9 @@ fileNames.forEach(fileName => { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) >ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1190, 62)) +>ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1262, 62)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1190, 62)) +>createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1262, 62)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >readFileSync(fileName).toString() : any >readFileSync(fileName).toString : any @@ -296,11 +296,11 @@ fileNames.forEach(fileName => { >readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >toString : any ->ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1118, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5)) +>ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1190, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5)) ->ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1118, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) +>ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1190, 16)) >true : boolean // delint it diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 6e27f70d87722..1844ec2cb4589 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,17 +19,17 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1729, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1801, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1729, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1801, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) console.log(JSON.stringify(result)); >console.log(JSON.stringify(result)) : any diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index abc915e37763f..0282be6eac7ac 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -26,7 +26,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1074, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1146, 5)) const files: ts.Map<{ version: number }> = {}; >files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1295, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1367, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1288, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1287, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1360, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1359, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1287, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1288, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1359, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1360, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1737, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1809, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1737, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1809, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1735, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1807, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1735, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1807, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1733, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1805, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1733, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1805, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1339, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1411, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1339, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1411, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1542, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1614, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1542, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1614, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1541, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1613, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1541, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1613, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1550, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1622, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1550, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1552, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1622, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1624, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1552, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1624, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1313, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1385, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1313, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1385, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1311, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1383, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1311, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1383, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1312, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1384, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1312, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1384, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,31 +333,31 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >"\n" : string if (diagnostic.file) { ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 46)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -365,11 +365,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) >log : any >` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 743, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >1 : number @@ -435,9 +435,9 @@ watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }); >currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_watcher.ts, 102, 30)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) From c405e6a53afae999c78aa00a0126d271d7e668f9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 13 Apr 2015 21:25:27 -0700 Subject: [PATCH 37/96] Handle 'returns' inside JSDoc comments --- src/compiler/parser.ts | 15 +++-- src/compiler/types.ts | 1 + .../reference/APISample_compile.types | 16 ++--- .../reference/APISample_linter.types | 14 ++--- .../reference/APISample_transform.types | 4 +- .../reference/APISample_watcher.types | 62 +++++++++---------- tests/cases/unittests/jsDocParsing.ts | 20 ++++++ 7 files changed, 80 insertions(+), 52 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4777af96e25b6..79e629f56417a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5811,8 +5811,7 @@ module ts { interface NodeWithComment extends Node { _docComment: JSDocComment; } - - /* @internal */ + export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { let nodeWithComment = parent; if (nodeWithComment && nodeWithComment._docComment) { @@ -5841,6 +5840,7 @@ module ts { let parameters: JSDocParameter[]; let returnType: JSDocType; let typeParameters: TypeParameterDeclaration[]; + // let tagCounts: Map; let pos: number; @@ -5905,11 +5905,11 @@ module ts { return error ? undefined : createJSDocComment(); function createJSDocComment(): JSDocComment { - if (!returnType && !type && !parameters && !typeParameters) { + if (!returnType && !type && !parameters && !typeParameters/* && !tagCounts*/) { return undefined; } - return { returnType, type, parameters, typeParameters }; + return { returnType, type, parameters, typeParameters/*, tagCounts */}; } function skipWhitespace(): void { @@ -5925,10 +5925,17 @@ module ts { pos++; let tagName = scanIdentifier(); + //tagCounts = tagCounts || {}; + //if (!hasProperty(tagCounts, tagName)) { + // tagCounts[tagName] = 0; + //} + //tagCounts[tagName]++; + switch (tagName) { case "param": return handleParamTag(); case "return": + case "returns": return handleReturnTag(); case "template": return handleTemplateTag(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 913fdf91c5b40..f7f1a266686f8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1088,6 +1088,7 @@ module ts { parameters?: JSDocParameter[]; returnType?: JSDocType; typeParameters?: TypeParameterDeclaration[]; + // tagCounts?: Map } // Source files are declarations when they are external modules. diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index d74de21b8515f..53ebf9b086f3f 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -28,9 +28,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1273, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1274, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1273, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1274, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) @@ -46,9 +46,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1271, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1272, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1271, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1272, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) @@ -67,11 +67,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) @@ -79,9 +79,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 70b8806c29669..518bcda0d4674 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1333, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1334, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,7 +33,7 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1293, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1294, 32)) switch (node.kind) { >node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1293, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1294, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1298, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1299, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1298, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1299, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 1844ec2cb4589..9b73237447a59 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,9 +19,9 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1801, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1801, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 0282be6eac7ac..6522536fa7d6c 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1367, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1368, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1360, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1359, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1359, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1360, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1809, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1809, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1807, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1807, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1805, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1805, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1411, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1411, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1614, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1614, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1613, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1613, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1622, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1622, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1624, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1624, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1385, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1385, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1383, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1383, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1384, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1384, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,9 +333,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1272, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) @@ -350,11 +350,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1335, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 8fac15187b7ec..6ce3c7f59b28c 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1014,6 +1014,26 @@ module ts { }`); }); + it("returnsTag1", () => { + parsesCorrectly( + `/** + * @returns {number} + */`, + `{ + "returnType": { + "kind": "JSDocTypeReference", + "pos": 18, + "end": 24, + "name": { + "kind": 65, + "pos": 18, + "end": 24, + "text": "number" + } + } +}`); + }); + it("oneParamTag", () => { parsesCorrectly( `/** From 656190637788d3d4dfa4cde85a035109a51cccc0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 12:27:47 -0700 Subject: [PATCH 38/96] Add support for top level JSDoc union types. --- src/compiler/parser.ts | 79 ++++++++++++++----- .../reference/APISample_compile.types | 16 ++-- .../reference/APISample_linter.types | 22 +++--- .../reference/APISample_transform.types | 4 +- .../reference/APISample_watcher.types | 62 +++++++-------- tests/cases/unittests/jsDocParsing.ts | 36 +++++++++ 6 files changed, 147 insertions(+), 72 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 79e629f56417a..1e50865268762 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2,6 +2,8 @@ /// module ts { + export var throwOnJSDocErrors = false; + let nodeConstructors = new Array Node>(SyntaxKind.Count); /* @internal */ export let parseTime = 0; @@ -5464,8 +5466,12 @@ module ts { let result = createNode(SyntaxKind.JSDocTypeExpression); - parseExpected(SyntaxKind.OpenBraceToken); - result.type = parseJSDocType(); + parseExpected(SyntaxKind.OpenBraceToken, /*noThrow:*/ true); + if (error) { + return undefined; + } + + result.type = parseJSDocTopLevelType(); parseExpected(SyntaxKind.CloseBraceToken); if (error) { @@ -5475,6 +5481,13 @@ module ts { fixupParentReferences(result); return finishNode(result); + function setError(noThrow?: boolean, message?: string) { + error = true; + if (!noThrow && throwOnJSDocErrors) { + throw new Error(message); + } + } + function nextToken(): SyntaxKind { return token = scanner.scan(); } @@ -5483,12 +5496,12 @@ module ts { return createNodeAtPosition(scanner, kind, pos); } - function parseExpected(kind: SyntaxKind): void { + function parseExpected(kind: SyntaxKind, noThrow?: boolean): void { if (token === kind) { nextToken(); } else { - error = true; + setError(noThrow, "Expected " + (ts).SyntaxKind[kind] + ", actual: " + (ts).SyntaxKind[token]) } } @@ -5508,6 +5521,17 @@ module ts { return token >= SyntaxKind.FirstKeyword && token <= SyntaxKind.LastKeyword; } + function parseJSDocTopLevelType(): JSDocType { + var firstType = parseJSDocType(); + if (!error && token === SyntaxKind.BarToken) { + var unionType = createNode(SyntaxKind.JSDocUnionType, firstType.pos); + unionType.types = parseJSDocTypeList(firstType); + return finishNode(unionType); + } + + return firstType; + } + function parseJSDocType(): JSDocType { if (!error) { let type = parseJSDocTypeCore(); @@ -5545,7 +5569,7 @@ module ts { return parseJSDocTypeReference(); } - error = true; + setError(); return undefined; } @@ -5632,7 +5656,7 @@ module ts { break; } else { - error = true; + setError(); return undefined; } } @@ -5684,7 +5708,7 @@ module ts { return finishNode(result); } else { - error = true; + setError(); return undefined; } } @@ -5731,7 +5755,7 @@ module ts { return finishNode(result); } else { - error = true; + setError(); return undefined; } } @@ -5746,22 +5770,30 @@ module ts { function parseJSDocUnionType(): JSDocUnionType { let result = createNode(SyntaxKind.JSDocUnionType); nextToken(); + + result.types = parseJSDocTypeList(parseJSDocType()); + + parseExpected(SyntaxKind.CloseParenToken); + + return finishNode(result); + } + + function parseJSDocTypeList(firstType: JSDocType) { + if (!firstType) { + return undefined; + } let types = >[]; - types.pos = scanner.getStartPos(); + types.pos = firstType.pos; - types.push(parseJSDocType()); + types.push(firstType); while (!error && token === SyntaxKind.BarToken) { nextToken(); types.push(parseJSDocType()); } types.end = scanner.getStartPos(); - result.types = types; - - parseExpected(SyntaxKind.CloseParenToken); - - return finishNode(result); + return types; } function parseJSDocAllType(): JSDocAllType { @@ -5904,6 +5936,13 @@ module ts { return error ? undefined : createJSDocComment(); + function setError() { + error = true; + //if (throwOnJSDocErrors) { + // throw new Error(); + //} + } + function createJSDocComment(): JSDocComment { if (!returnType && !type && !parameters && !typeParameters/* && !tagCounts*/) { return undefined; @@ -5947,7 +5986,7 @@ module ts { function parseType(): JSDocType { let typeExpression = parseJSDocTypeExpression(content, pos, end - pos); if (!typeExpression) { - error = true; + setError(); return undefined; } @@ -5977,7 +6016,7 @@ module ts { } } - error = true; + setError(); } function handleTypeTag(): void { @@ -5988,7 +6027,7 @@ module ts { } } - error = true; + setError(); } function handleTemplateTag(): void { @@ -6023,7 +6062,7 @@ module ts { } } - error = true; + setError(); } function scanIdentifier(): string { @@ -6041,7 +6080,7 @@ module ts { } if (startPos === pos) { - error = true; + setError(); return; } diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 53ebf9b086f3f..d2025246cd7a1 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -28,9 +28,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1274, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1275, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1274, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1275, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) @@ -46,9 +46,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1272, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1273, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1272, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1273, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) @@ -67,11 +67,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) @@ -79,9 +79,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 518bcda0d4674..cff11f2711f9a 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1334, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1335, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,7 +33,7 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1294, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1295, 32)) switch (node.kind) { >node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) @@ -219,9 +219,9 @@ export function delint(sourceFile: ts.SourceFile) { ts.forEachChild(node, delintNode); >ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1258, 48)) +>ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1259, 48)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1258, 48)) +>forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1259, 48)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) } @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1294, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1295, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1299, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1300, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1299, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1300, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -286,9 +286,9 @@ fileNames.forEach(fileName => { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) >ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1262, 62)) +>ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1263, 62)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1262, 62)) +>createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1263, 62)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >readFileSync(fileName).toString() : any >readFileSync(fileName).toString : any diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 9b73237447a59..3d4777faedc40 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,9 +19,9 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 6522536fa7d6c..e31e743d45877 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1368, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1369, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,9 +333,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1273, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) @@ -350,11 +350,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 46)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 46)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 6ce3c7f59b28c..af6a3ac420989 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -401,6 +401,42 @@ module ts { }`); }); + it("topLevelNoParenUnionType", () => { + parsesCorrectly("{number|string}", + `{ + "kind": "JSDocUnionType", + "pos": 1, + "end": 14, + "types": { + "0": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 7, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 7, + "text": "number" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 8, + "end": 14, + "name": { + "kind": "Identifier", + "pos": 8, + "end": 14, + "text": "string" + } + }, + "length": 2, + "pos": 1, + "end": 14 + } +}`); + }); + it("functionType1", () => { parsesCorrectly("{function()}", `{ From 6599a4b74e5eba651bb01607f17020723db51815 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 12:56:16 -0700 Subject: [PATCH 39/96] Skip whitespace before parsing out a type. --- src/compiler/parser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1e50865268762..3c508f229520b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5984,6 +5984,7 @@ module ts { } function parseType(): JSDocType { + skipWhitespace(); let typeExpression = parseJSDocTypeExpression(content, pos, end - pos); if (!typeExpression) { setError(); From 49f8a419e364a4947000efd589f25b1acb6d81b2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 14:15:55 -0700 Subject: [PATCH 40/96] Add support for param tags where the type follows the identifier name. --- src/compiler/parser.ts | 35 ++++++++++++++----- tests/cases/unittests/jsDocParsing.ts | 50 +++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 3c508f229520b..cf728240bacdf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5466,7 +5466,7 @@ module ts { let result = createNode(SyntaxKind.JSDocTypeExpression); - parseExpected(SyntaxKind.OpenBraceToken, /*noThrow:*/ true); + parseExpected(SyntaxKind.OpenBraceToken); if (error) { return undefined; } @@ -5481,9 +5481,9 @@ module ts { fixupParentReferences(result); return finishNode(result); - function setError(noThrow?: boolean, message?: string) { + function setError(message?: string) { error = true; - if (!noThrow && throwOnJSDocErrors) { + if (throwOnJSDocErrors) { throw new Error(message); } } @@ -5496,12 +5496,12 @@ module ts { return createNodeAtPosition(scanner, kind, pos); } - function parseExpected(kind: SyntaxKind, noThrow?: boolean): void { + function parseExpected(kind: SyntaxKind): void { if (token === kind) { nextToken(); } else { - setError(noThrow, "Expected " + (ts).SyntaxKind[kind] + ", actual: " + (ts).SyntaxKind[token]) + setError("Expected " + (ts).SyntaxKind[kind] + ", actual: " + (ts).SyntaxKind[token]) } } @@ -5985,6 +5985,11 @@ module ts { function parseType(): JSDocType { skipWhitespace(); + + if (content.charCodeAt(pos) !== CharacterCodes.openBrace) { + return undefined; + } + let typeExpression = parseJSDocTypeExpression(content, pos, end - pos); if (!typeExpression) { setError(); @@ -5997,14 +6002,26 @@ module ts { } function handleParamTag() { - let type = parseType(); - if (!type) { - return; + skipWhitespace(); + + let type: JSDocType; + if (content.charCodeAt(pos) === CharacterCodes.openBrace) { + type = parseType(); + if (!type) { + return; + } } skipWhitespace(); - let name = scanIdentifier(); + + if (!type) { + type = parseType(); + if (!type) { + return; + } + } + parameters = parameters || []; parameters.push({ name, type }); } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index af6a3ac420989..71189337bc6ed 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1185,6 +1185,56 @@ module ts { }`); }); + it("paramTagNameThenType1", () => { + parsesCorrectly( + `/** + * @param name1 {number} + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 22, + "end": 28, + "name": { + "kind": 65, + "pos": 22, + "end": 28, + "text": "number" + } + } + } + ] +}`); + }); + + it("paramTagNameThenType2", () => { + parsesCorrectly( + `/** + * @param name1 {number} Description + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 22, + "end": 28, + "name": { + "kind": 65, + "pos": 22, + "end": 28, + "text": "number" + } + } + } + ] +}`); + }); + it("templateTag", () => { parsesCorrectly( `/** From 6732e212eb75252564bd4db69c430c52aeeb6d7c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 17:17:30 -0700 Subject: [PATCH 41/96] Add support for bracketed JSDoc parameter names. --- src/compiler/checker.ts | 2 +- src/compiler/parser.ts | 23 ++++- src/compiler/types.ts | 1 + .../reference/APISample_compile.types | 66 ++++++------- .../reference/APISample_linter.types | 34 +++---- .../reference/APISample_transform.types | 12 +-- .../reference/APISample_watcher.types | 96 +++++++++---------- .../fourslash/getJavaScriptQuickInfo1.ts | 9 ++ .../fourslash/getJavaScriptQuickInfo2.ts | 10 ++ tests/cases/unittests/jsDocParsing.ts | 26 +++++ 10 files changed, 172 insertions(+), 107 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo1.ts create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fee1e0a2c0624..21050b62e8d9a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3160,7 +3160,7 @@ module ts { let docParam = getJSDocParameter(node, getSourceFile(node)); if (docParam) { - return docParam.type.kind === SyntaxKind.JSDocOptionalType; + return docParam.isBracketed || docParam.type.kind === SyntaxKind.JSDocOptionalType; } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index cf728240bacdf..383165724bfba 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6013,7 +6013,24 @@ module ts { } skipWhitespace(); - let name = scanIdentifier(); + let name: string; + let isBracketed: boolean; + if (content.charCodeAt(pos) === CharacterCodes.openBracket) { + pos++; + name = scanIdentifier(); + isBracketed = true; + + skipWhitespace(); + if (content.charCodeAt(pos) !== CharacterCodes.closeBracket) { + setError(); + return; + } + + pos++; + } + else { + name = scanIdentifier(); + } if (!type) { type = parseType(); @@ -6023,7 +6040,7 @@ module ts { } parameters = parameters || []; - parameters.push({ name, type }); + parameters.push({ name, type, isBracketed }); } function handleReturnTag(): void { @@ -6084,6 +6101,8 @@ module ts { } function scanIdentifier(): string { + skipWhitespace(); + let startPos = pos; for (;pos < end; pos++) { let ch = content.charCodeAt(pos); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f7f1a266686f8..45c42609fe252 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1081,6 +1081,7 @@ module ts { export interface JSDocParameter { name: string; type: JSDocType; + isBracketed: boolean; } export interface JSDocComment { diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 147058c220d7f..8982f70195b86 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -23,37 +23,37 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) >ts : any, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1146, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1147, 5)) var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1275, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1276, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1275, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1276, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) var emitResult = program.emit(); >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) >program.emit() : ts.EmitResult ->program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 839, 39)) +>program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 840, 39)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 839, 39)) +>emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 840, 39)) var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); >allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1273, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1274, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1273, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1274, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) +>emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 893, 29)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 892, 29)) +>diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 893, 29)) allDiagnostics.forEach(diagnostic => { >allDiagnostics.forEach(diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); }) : void @@ -67,24 +67,24 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) >'\n' : string console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); @@ -93,11 +93,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) >log : any >`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >1 : number @@ -111,9 +111,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var exitCode = emitResult.emitSkipped ? 1 : 0; >exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) >emitResult.emitSkipped ? 1 : 0 : number ->emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 891, 26)) +>emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 892, 26)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 891, 26)) +>emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 892, 26)) >1 : number >0 : number @@ -153,16 +153,16 @@ compile(process.argv.slice(2), { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS >target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45)) ->ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1189, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) +>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1190, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) ->ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1189, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) +>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1190, 16)) >module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) }); diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index e23bc2611aa08..8a23ea4224027 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 812, 5), Decl(typescript.d.ts, 1335, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 813, 5), Decl(typescript.d.ts, 1336, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,7 +33,7 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1295, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1296, 32)) switch (node.kind) { >node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) @@ -219,9 +219,9 @@ export function delint(sourceFile: ts.SourceFile) { ts.forEachChild(node, delintNode); >ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1259, 48)) +>ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1260, 48)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1259, 48)) +>forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1260, 48)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) } @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1295, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1296, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1300, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1301, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1300, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1301, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -251,9 +251,9 @@ export function delint(sourceFile: ts.SourceFile) { >console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) >log : any >`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}` : string ->sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >1 : number @@ -286,9 +286,9 @@ fileNames.forEach(fileName => { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) >ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1263, 62)) +>ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1264, 62)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1263, 62)) +>createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1264, 62)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >readFileSync(fileName).toString() : any >readFileSync(fileName).toString : any @@ -296,11 +296,11 @@ fileNames.forEach(fileName => { >readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >toString : any ->ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1190, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) +>ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1191, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1187, 5)) ->ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1190, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) +>ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1191, 16)) >true : boolean // delint it diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 9b73237447a59..af6ed7bafdf7e 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,17 +19,17 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1802, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) console.log(JSON.stringify(result)); >console.log(JSON.stringify(result)) : any diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 2a3796d5834bf..7286beeb5c536 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -26,7 +26,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1146, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1147, 5)) const files: ts.Map<{ version: number }> = {}; >files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1368, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1369, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1360, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1361, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1810, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1808, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1806, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1412, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1615, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1614, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1623, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1625, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1386, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1384, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1385, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,31 +333,31 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1274, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1137, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) >"\n" : string if (diagnostic.file) { ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1336, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1135, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -365,11 +365,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) >log : any >` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1134, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 815, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >1 : number @@ -435,9 +435,9 @@ watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }); >currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_watcher.ts, 102, 30)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1178, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1180, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo1.ts b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts new file mode 100644 index 0000000000000..71072f1699aa2 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts @@ -0,0 +1,9 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {function(new:string,number)} */ +////var /**/v; + +goTo.marker(); +verify.quickInfoIs('var v: new (p1: number) => string'); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo2.ts b/tests/cases/fourslash/getJavaScriptQuickInfo2.ts new file mode 100644 index 0000000000000..1da049ed5c897 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo2.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @param {number} [a] */ +////function /**/f(a) { } + +debugger; +goTo.marker(); +verify.quickInfoIs('function f(a?: number): void'); \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 71189337bc6ed..af13cf47e4d5e 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1160,6 +1160,32 @@ module ts { }`); }); + it("paramTagBracketedName1", () => { + parsesCorrectly( + `/** + * @param {number} [name1] Description text follows + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + }, + "isBracketed": true + } + ] +}`); + }); + it("twoParamTagOnSameLine", () => { parsesCorrectly( `/** From da256dd8e01aa87924eb65af210ce24b306b5966 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 17:18:19 -0700 Subject: [PATCH 42/96] Delete empty test. --- tests/cases/fourslash/getJavaScriptCompletions10.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/cases/fourslash/getJavaScriptCompletions10.ts diff --git a/tests/cases/fourslash/getJavaScriptCompletions10.ts b/tests/cases/fourslash/getJavaScriptCompletions10.ts deleted file mode 100644 index e69de29bb2d1d..0000000000000 From 613bb303bcb9c04de68458eeb84365b70f553dcb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 17:19:45 -0700 Subject: [PATCH 43/96] Supported bracketed parameter names with an optional initializer. --- src/compiler/parser.ts | 8 -------- tests/cases/unittests/jsDocParsing.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 383165724bfba..afb21c4470fb4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6019,14 +6019,6 @@ module ts { pos++; name = scanIdentifier(); isBracketed = true; - - skipWhitespace(); - if (content.charCodeAt(pos) !== CharacterCodes.closeBracket) { - setError(); - return; - } - - pos++; } else { name = scanIdentifier(); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index af13cf47e4d5e..ce71523a86269 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1186,6 +1186,32 @@ module ts { }`); }); + it("paramTagBracketedName2", () => { + parsesCorrectly( + `/** + * @param {number} [ name1 = 1] Description text follows + */`, + `{ + "parameters": [ + { + "name": "name1", + "type": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 22, + "name": { + "kind": 65, + "pos": 16, + "end": 22, + "text": "number" + } + }, + "isBracketed": true + } + ] +}`); + }); + it("twoParamTagOnSameLine", () => { parsesCorrectly( `/** From 3e04643bb532570d0a1e795daa70cd072cb2678d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 17:40:32 -0700 Subject: [PATCH 44/96] Add support for parsing JSDoc array types. --- src/compiler/parser.ts | 28 ++++++--- src/compiler/types.ts | 5 ++ tests/cases/unittests/jsDocParsing.ts | 82 +++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index afb21c4470fb4..8d2390992d27e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5522,21 +5522,35 @@ module ts { } function parseJSDocTopLevelType(): JSDocType { - var firstType = parseJSDocType(); + var type = parseJSDocType(); if (!error && token === SyntaxKind.BarToken) { - var unionType = createNode(SyntaxKind.JSDocUnionType, firstType.pos); - unionType.types = parseJSDocTypeList(firstType); - return finishNode(unionType); + var unionType = createNode(SyntaxKind.JSDocUnionType, type.pos); + unionType.types = parseJSDocTypeList(type); + type = finishNode(unionType); } - return firstType; + if (!error && token === SyntaxKind.EqualsToken) { + var optionalType = createNode(SyntaxKind.JSDocOptionalType, type.pos); + nextToken(); + optionalType.type = type; + type = finishNode(optionalType); + } + + return type; } function parseJSDocType(): JSDocType { if (!error) { let type = parseJSDocTypeCore(); - if (type && token === SyntaxKind.EqualsToken) { - return parseJSDocOptionalType(type); + + while (!error && type && token === SyntaxKind.OpenBracketToken) { + let arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); + arrayType.elementType = type; + + nextToken(); + parseExpected(SyntaxKind.CloseBracketToken); + + type = finishNode(arrayType); } return type; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 45c42609fe252..d8b8a860acfbf 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -275,6 +275,7 @@ module ts { JSDocAllType, // The ? type. JSDocUnknownType, + JSDocArrayType, JSDocUnionType, JSDocNullableType, JSDocNonNullableType, @@ -1031,6 +1032,10 @@ module ts { _JSDocUnknownTypeBrand: any; } + export interface JSDocArrayType extends JSDocType { + elementType: JSDocType; + } + export interface JSDocUnionType extends JSDocType { types: NodeArray; } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index ce71523a86269..4240d0cf75dd6 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -755,6 +755,84 @@ module ts { "text": "function" } } +}`); + }); + + it("arrayType1", () => { + parsesCorrectly( + "{a[]}", + `{ + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } +}`); + }); + + it("arrayType2", () => { + parsesCorrectly( + "{a[][]}", + `{ + "kind": "JSDocArrayType", + "pos": 1, + "end": 6, + "elementType": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } + } +}`); + }); + + it("arrayType3", () => { + parsesCorrectly( + "{a[][]=}", + `{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 7, + "type": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 6, + "elementType": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } + } + } }`); }); }); @@ -820,10 +898,6 @@ module ts { parsesIncorrectly("{a.}"); }); - it("arrayType", () => { - parsesIncorrectly("{a[]}"); - }); - it("tsFunctionType", () => { parsesIncorrectly("{() => string}"); }); From f190ac88bb472e6cc2f5ea0b56f70c905f904786 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 17:46:42 -0700 Subject: [PATCH 45/96] Add type checking for JSDoc array types. --- src/compiler/checker.ts | 14 ++- .../reference/APISample_compile.types | 66 ++++++------- .../reference/APISample_linter.types | 96 +++++++++---------- .../reference/APISample_transform.types | 12 +-- .../reference/APISample_watcher.types | 96 +++++++++---------- .../fourslash/getJavaScriptQuickInfo3.ts | 10 ++ 6 files changed, 155 insertions(+), 139 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 21050b62e8d9a..e85e727500296 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3822,6 +3822,10 @@ module ts { return undefined; } + function getTypeFromJSDocArrayType(node: JSDocArrayType): Type { + return createArrayType(getTypeFromTypeNode(node.elementType)); + } + function getTypeFromJSDocUnionType(node: JSDocUnionType): Type { let types = map(node.types, getTypeFromTypeNode); for (let type of types) { @@ -3881,12 +3885,12 @@ module ts { case SyntaxKind.QualifiedName: let symbol = getSymbolInfo(node); return symbol && getDeclaredTypeOfSymbol(symbol); - default: - return unknownType; case SyntaxKind.JSDocAllType: return anyType; case SyntaxKind.JSDocUnknownType: return unknownType; + case SyntaxKind.JSDocArrayType: + return getTypeFromJSDocArrayType(node); case SyntaxKind.JSDocUnionType: return getTypeFromJSDocUnionType(node); case SyntaxKind.JSDocNullableType: @@ -3895,7 +3899,7 @@ module ts { return getTypeFromTypeNode((node).type); case SyntaxKind.JSDocRecordType: // NYI: - break; + return undefined; case SyntaxKind.JSDocTypeReference: return getTypeForJSDocTypeReference(node); case SyntaxKind.JSDocOptionalType: @@ -3908,7 +3912,9 @@ module ts { return getTypeFromTypeNode((node).type); case SyntaxKind.JSDocThisType: // NYI: - break; + return undefined; + default: + return unknownType; } } diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 8982f70195b86..ce0244c211a39 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -23,37 +23,37 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) >ts : any, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1147, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1151, 5)) var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1276, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1280, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1276, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1280, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) var emitResult = program.emit(); >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) >program.emit() : ts.EmitResult ->program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 840, 39)) +>program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 844, 39)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 840, 39)) +>emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 844, 39)) var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); >allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1274, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1278, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1274, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1278, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 893, 29)) +>emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 897, 29)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 893, 29)) +>diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 897, 29)) allDiagnostics.forEach(diagnostic => { >allDiagnostics.forEach(diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); }) : void @@ -67,24 +67,24 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) >'\n' : string console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); @@ -93,11 +93,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) >log : any >`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >1 : number @@ -111,9 +111,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var exitCode = emitResult.emitSkipped ? 1 : 0; >exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) >emitResult.emitSkipped ? 1 : 0 : number ->emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 892, 26)) +>emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 896, 26)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 892, 26)) +>emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 896, 26)) >1 : number >0 : number @@ -153,16 +153,16 @@ compile(process.argv.slice(2), { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS >target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45)) ->ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1190, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) +>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1194, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) ->ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1190, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) +>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1194, 16)) >module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) }); diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 8a23ea4224027..d2851eb9458b5 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 813, 5), Decl(typescript.d.ts, 1336, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 817, 5), Decl(typescript.d.ts, 1340, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,12 +33,12 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1296, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 311, 5), Decl(typescript.d.ts, 1300, 32)) switch (node.kind) { ->node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) case ts.SyntaxKind.ForStatement: >ts.SyntaxKind.ForStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForStatement, Decl(typescript.d.ts, 209, 29)) @@ -70,15 +70,15 @@ export function delint(sourceFile: ts.SourceFile) { if ((node).statement.kind !== ts.SyntaxKind.Block) { >(node).statement.kind !== ts.SyntaxKind.Block : boolean ->(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) ->(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 603, 52)) +>(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 604, 52)) >(node) : ts.IterationStatement >node : ts.IterationStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 602, 5)) +>IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 603, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 603, 52)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 604, 52)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -105,16 +105,16 @@ export function delint(sourceFile: ts.SourceFile) { >(node) : ts.IfStatement >node : ts.IfStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 597, 5)) +>IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 598, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) { >ifStatement.thenStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) +>ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -124,25 +124,25 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); >report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 599, 31)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) >"An if statement's contents should be wrapped in a block body." : string } if (ifStatement.elseStatement && >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && >ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -151,11 +151,11 @@ export function delint(sourceFile: ts.SourceFile) { ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) { >ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) >ts.SyntaxKind.IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -165,9 +165,9 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); >report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 600, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) >"An else statement's contents should be wrapped in a block body." : string } break; @@ -181,15 +181,15 @@ export function delint(sourceFile: ts.SourceFile) { let op = (node).operatorToken.kind; >op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) ->(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 511, 25)) +>(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 512, 25)) >(node) : ts.BinaryExpression >node : ts.BinaryExpression >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 509, 5)) +>BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 510, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 511, 25)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 311, 38)) +>operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 512, 25)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) { >op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken : boolean @@ -219,9 +219,9 @@ export function delint(sourceFile: ts.SourceFile) { ts.forEachChild(node, delintNode); >ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1260, 48)) +>ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1264, 48)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1260, 48)) +>forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1264, 48)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) } @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 310, 5), Decl(typescript.d.ts, 1296, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 311, 5), Decl(typescript.d.ts, 1300, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1301, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1305, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1301, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1305, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -251,9 +251,9 @@ export function delint(sourceFile: ts.SourceFile) { >console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) >log : any >`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}` : string ->sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >1 : number @@ -286,9 +286,9 @@ fileNames.forEach(fileName => { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) >ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1264, 62)) +>ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1268, 62)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1264, 62)) +>createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1268, 62)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >readFileSync(fileName).toString() : any >readFileSync(fileName).toString : any @@ -296,11 +296,11 @@ fileNames.forEach(fileName => { >readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >toString : any ->ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1191, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) +>ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1195, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1188, 5)) ->ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1191, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) +>ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1195, 16)) >true : boolean // delint it diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index af6ed7bafdf7e..5e8e05850ef93 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,17 +19,17 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1807, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1803, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1807, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) console.log(JSON.stringify(result)); >console.log(JSON.stringify(result)) : any diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 7286beeb5c536..a48f440d8a42c 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -26,7 +26,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1147, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1151, 5)) const files: ts.Map<{ version: number }> = {}; >files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1369, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1373, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1366, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1365, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1361, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1362, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1365, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1366, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1815, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1811, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1815, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1813, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1809, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1813, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1811, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1807, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1811, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1417, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1413, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1417, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1620, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1616, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1620, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1619, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1615, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1619, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1628, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1624, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1628, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1630, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1626, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1630, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1391, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1387, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1391, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1389, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1385, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1389, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1390, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1386, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1390, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,31 +333,31 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1275, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1138, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) >"\n" : string if (diagnostic.file) { ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1337, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1136, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -365,11 +365,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) >log : any >` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1135, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 816, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >1 : number @@ -435,9 +435,9 @@ watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }); >currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_watcher.ts, 102, 30)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1179, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1181, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo3.ts b/tests/cases/fourslash/getJavaScriptQuickInfo3.ts new file mode 100644 index 0000000000000..213b3b4ab5e2f --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo3.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @param {number[]} [a] */ +////function /**/f(a) { } + +debugger; +goTo.marker(); +verify.quickInfoIs('function f(a?: number[]): void'); \ No newline at end of file From 6c60dad716f89966959d4c3c107495b431b57d91 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 18:12:19 -0700 Subject: [PATCH 46/96] Add support for parsing nullable/non-nullable types with syntax at the end instead of the beginning. --- src/compiler/parser.ts | 35 +++++++++++++++++------ tests/cases/unittests/jsDocParsing.ts | 40 +++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8d2390992d27e..d37516a8bb9c4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5541,23 +5541,42 @@ module ts { function parseJSDocType(): JSDocType { if (!error) { - let type = parseJSDocTypeCore(); + let type = parseBasicTypeExpression(); - while (!error && type && token === SyntaxKind.OpenBracketToken) { - let arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); - arrayType.elementType = type; + while (!error && type) { + if (token === SyntaxKind.OpenBracketToken) { + let arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); + arrayType.elementType = type; - nextToken(); - parseExpected(SyntaxKind.CloseBracketToken); + nextToken(); + parseExpected(SyntaxKind.CloseBracketToken); - type = finishNode(arrayType); + type = finishNode(arrayType); + } + else if (token === SyntaxKind.QuestionToken) { + let nullableType = createNode(SyntaxKind.JSDocNullableType, type.pos); + nullableType.type = type; + + nextToken(); + type = finishNode(nullableType); + } + else if (token === SyntaxKind.ExclamationToken) { + let nonNullableType = createNode(SyntaxKind.JSDocNonNullableType, type.pos); + nonNullableType.type = type; + + nextToken(); + type = finishNode(nonNullableType); + } + else { + break; + } } return type; } } - function parseJSDocTypeCore(): JSDocType { + function parseBasicTypeExpression(): JSDocType { switch (token) { case SyntaxKind.AsteriskToken: return parseJSDocAllType(); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 4240d0cf75dd6..12e014f66593f 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -57,6 +57,26 @@ module ts { }`) }); + it("nullableType2", () => { + parsesCorrectly("{number?}", + `{ + "kind": "JSDocNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 7, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 7, + "text": "number" + } + } +}`) + }); + it("nonNullableType", () => { parsesCorrectly("{!number}", `{ @@ -77,6 +97,26 @@ module ts { }`) }); + it("nonNullableType2", () => { + parsesCorrectly("{number!}", + `{ + "kind": "JSDocNonNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 7, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 7, + "text": "number" + } + } +}`) + }); + it("recordType1", () => { parsesCorrectly("{{}}", `{ From e43fc69c6ac4fa1eb13a7f920d3420b8d440a993 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 14 Apr 2015 18:17:51 -0700 Subject: [PATCH 47/96] Support arbitrary identifier names as type reference names in JSDoc comments. --- src/compiler/parser.ts | 16 ++------- tests/cases/unittests/jsDocParsing.ts | 52 ++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d37516a8bb9c4..b937578b5384b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5505,14 +5505,6 @@ module ts { } } - function isIdentifier() { - if (token === SyntaxKind.Identifier) { - return true; - } - - return token > SyntaxKind.LastReservedWord && token <= SyntaxKind.LastKeyword; - } - function isIdentifierOrKeyword() { if (token === SyntaxKind.Identifier) { return true; @@ -5598,7 +5590,7 @@ module ts { return parseJSDocThisType(); } - if (isIdentifier()) { + if (isIdentifierOrKeyword()) { return parseJSDocTypeReference(); } @@ -5676,7 +5668,7 @@ module ts { function parseJSDocTypeReference(): JSDocTypeReference { let result = createNode(SyntaxKind.JSDocTypeReference); - result.name = parseIdentifier(); + result.name = parseIdentifierOrKeyword(); while (!error && token === SyntaxKind.DotToken) { nextToken(); @@ -5729,10 +5721,6 @@ module ts { return parseIdentifierHelper(isIdentifierOrKeyword()); } - function parseIdentifier(): Identifier { - return parseIdentifierHelper(isIdentifier()); - } - function parseIdentifierHelper(isIdentifier: boolean): Identifier { if (isIdentifier) { let result = createNode(SyntaxKind.Identifier); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 12e014f66593f..fbd65f92d15c7 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -873,6 +873,54 @@ module ts { } } } +}`); + }); + + it("keyword1", () => { + parsesCorrectly( + "{var}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 4, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 4, + "text": "var" + } +}`); + }); + + it("keyword2", () => { + parsesCorrectly( + "{null}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 5, + "text": "null" + } +}`); + }); + + it("keyword3", () => { + parsesCorrectly( + "{undefined}", + `{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 10, + "text": "undefined" + } }`); }); }); @@ -902,10 +950,6 @@ module ts { parsesIncorrectly("{function(a,)}"); }); - it("keyword", () => { - parsesIncorrectly("{var}"); - }); - it("thisWithoutType", () => { parsesIncorrectly("{this:}"); }); From 0884fdb4cf6d236b4588603fc77fc4c952e026b5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 00:04:36 -0700 Subject: [PATCH 48/96] Use undefinedType for JSDoc type results, not 'undefined' --- src/compiler/checker.ts | 159 ++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 88 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e85e727500296..8c12bc576a74d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2153,7 +2153,7 @@ module ts { // one as it's type), otherwise fallback to the below standard TS codepaths to // try to figure it out. let type = getTypeForVariableLikeDeclarationFromJSDocComment(declaration); - if (type) { + if (type && type !== unknownType) { return type; } } @@ -3806,12 +3806,6 @@ module ts { let typeParameters = (type).typeParameters; if (node.typeArguments && node.typeArguments.length === typeParameters.length) { let typeArguments = map(node.typeArguments, getTypeFromTypeNode); - for (let typeArgument in typeArguments) { - if (!typeArgument) { - return undefined; - } - } - type = createTypeReference(type, typeArguments); } } @@ -3819,7 +3813,7 @@ module ts { return type; } - return undefined; + return unknownType; } function getTypeFromJSDocArrayType(node: JSDocArrayType): Type { @@ -3828,94 +3822,83 @@ module ts { function getTypeFromJSDocUnionType(node: JSDocUnionType): Type { let types = map(node.types, getTypeFromTypeNode); - for (let type of types) { - if (!type) { - return undefined; - } - } - return getUnionType(types, /*noSubtypeReduction*/ true); } function getTypeFromTypeNode(node: TypeNode): Type { - if (!node) { - return undefined; - } - return getTypeFromTypeNodeOrHeritageClauseElement(node); } function getTypeFromTypeNodeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type { - switch (node.kind) { - case SyntaxKind.AnyKeyword: - return anyType; - case SyntaxKind.StringKeyword: - return stringType; - case SyntaxKind.NumberKeyword: - return numberType; - case SyntaxKind.BooleanKeyword: - return booleanType; - case SyntaxKind.SymbolKeyword: - return esSymbolType; - case SyntaxKind.VoidKeyword: - return voidType; - case SyntaxKind.StringLiteral: - return getTypeFromStringLiteral(node); - case SyntaxKind.TypeReference: - return getTypeFromTypeReference(node); - case SyntaxKind.HeritageClauseElement: - return getTypeFromHeritageClauseElement(node); - case SyntaxKind.TypeQuery: - return getTypeFromTypeQueryNode(node); - case SyntaxKind.ArrayType: - return getTypeFromArrayTypeNode(node); - case SyntaxKind.TupleType: - return getTypeFromTupleTypeNode(node); - case SyntaxKind.UnionType: - return getTypeFromUnionTypeNode(node); - case SyntaxKind.ParenthesizedType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - case SyntaxKind.TypeLiteral: - return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - // This function assumes that an identifier or qualified name is a type expression - // Callers should first ensure this by calling isTypeNode - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: - let symbol = getSymbolInfo(node); - return symbol && getDeclaredTypeOfSymbol(symbol); - case SyntaxKind.JSDocAllType: - return anyType; - case SyntaxKind.JSDocUnknownType: - return unknownType; - case SyntaxKind.JSDocArrayType: - return getTypeFromJSDocArrayType(node); - case SyntaxKind.JSDocUnionType: - return getTypeFromJSDocUnionType(node); - case SyntaxKind.JSDocNullableType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocNonNullableType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocRecordType: - // NYI: - return undefined; - case SyntaxKind.JSDocTypeReference: - return getTypeForJSDocTypeReference(node); - case SyntaxKind.JSDocOptionalType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocFunctionType: - return getTypeFromJSDocFunctionType(node); - case SyntaxKind.JSDocVariadicType: - return getTypeFromJSDocVariadicType(node); - case SyntaxKind.JSDocConstructorType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocThisType: - // NYI: - return undefined; - default: - return unknownType; + if (node) { + switch (node.kind) { + case SyntaxKind.AnyKeyword: + return anyType; + case SyntaxKind.StringKeyword: + return stringType; + case SyntaxKind.NumberKeyword: + return numberType; + case SyntaxKind.BooleanKeyword: + return booleanType; + case SyntaxKind.SymbolKeyword: + return esSymbolType; + case SyntaxKind.VoidKeyword: + return voidType; + case SyntaxKind.StringLiteral: + return getTypeFromStringLiteral(node); + case SyntaxKind.TypeReference: + return getTypeFromTypeReference(node); + case SyntaxKind.HeritageClauseElement: + return getTypeFromHeritageClauseElement(node); + case SyntaxKind.TypeQuery: + return getTypeFromTypeQueryNode(node); + case SyntaxKind.ArrayType: + return getTypeFromArrayTypeNode(node); + case SyntaxKind.TupleType: + return getTypeFromTupleTypeNode(node); + case SyntaxKind.UnionType: + return getTypeFromUnionTypeNode(node); + case SyntaxKind.ParenthesizedType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeLiteral: + return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); + // This function assumes that an identifier or qualified name is a type expression + // Callers should first ensure this by calling isTypeNode + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + let symbol = getSymbolInfo(node); + return symbol && getDeclaredTypeOfSymbol(symbol); + case SyntaxKind.JSDocAllType: + return anyType; + case SyntaxKind.JSDocUnknownType: + return unknownType; + case SyntaxKind.JSDocArrayType: + return getTypeFromJSDocArrayType(node); + case SyntaxKind.JSDocUnionType: + return getTypeFromJSDocUnionType(node); + case SyntaxKind.JSDocNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocNonNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocTypeReference: + return getTypeForJSDocTypeReference(node); + case SyntaxKind.JSDocOptionalType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocFunctionType: + return getTypeFromJSDocFunctionType(node); + case SyntaxKind.JSDocVariadicType: + return getTypeFromJSDocVariadicType(node); + case SyntaxKind.JSDocConstructorType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocThisType: + case SyntaxKind.JSDocRecordType: + // NYI: + } } + + return unknownType; } function instantiateList(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] { @@ -7428,7 +7411,7 @@ module ts { let type: Type; if (func.parserContextFlags & ParserContextFlags.JavaScriptFile) { type = getReturnTypeFromJSDocComment(func); - if (type) { + if (type && type !== unknownType) { return type; } } From 2bb5e5a7edf2e625b567100eed1df778d0c0b34a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 00:27:12 -0700 Subject: [PATCH 49/96] Add support for tuple types in JSDoc types. --- src/compiler/checker.ts | 7 + src/compiler/parser.ts | 29 ++++ src/compiler/types.ts | 5 + .../reference/APISample_compile.types | 66 ++++---- .../reference/APISample_linter.types | 96 ++++++------ .../reference/APISample_transform.types | 12 +- .../reference/APISample_watcher.types | 96 ++++++------ .../fourslash/getJavaScriptQuickInfo4.ts | 10 ++ tests/cases/unittests/jsDocParsing.ts | 142 +++++++++++++++++- 9 files changed, 324 insertions(+), 139 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c12bc576a74d..2eba7d1888d0e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3825,6 +3825,11 @@ module ts { return getUnionType(types, /*noSubtypeReduction*/ true); } + function getTypeFromJSDocTupleType(node: JSDocTupleType): Type { + let types = map(node.types, getTypeFromTypeNode); + return createTupleType(types); + } + function getTypeFromTypeNode(node: TypeNode): Type { return getTypeFromTypeNodeOrHeritageClauseElement(node); } @@ -3876,6 +3881,8 @@ module ts { return unknownType; case SyntaxKind.JSDocArrayType: return getTypeFromJSDocArrayType(node); + case SyntaxKind.JSDocTupleType: + return getTypeFromJSDocTupleType(node); case SyntaxKind.JSDocUnionType: return getTypeFromJSDocUnionType(node); case SyntaxKind.JSDocNullableType: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b937578b5384b..65e031128d693 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5576,6 +5576,8 @@ module ts { return parseJSDocUnknownOrNullableType(); case SyntaxKind.OpenParenToken: return parseJSDocUnionType(); + case SyntaxKind.OpenBracketToken: + return parseJSDocTupleType(); case SyntaxKind.ExclamationToken: return parseJSDocNonNullableType(); case SyntaxKind.OpenBraceToken: @@ -5788,6 +5790,33 @@ module ts { return finishNode(result); } + function parseJSDocTupleType(): JSDocTupleType { + let result = createNode(SyntaxKind.JSDocTupleType); + nextToken(); + + let types = >[]; + types.pos = scanner.getStartPos(); + + while (!error) { + if (token === SyntaxKind.CloseBracketToken) { + break; + } + + if (types.length) { + parseExpected(SyntaxKind.CommaToken); + } + + types.push(parseJSDocType()); + } + + types.end = scanner.getStartPos(); + + result.types = types; + parseExpected(SyntaxKind.CloseBracketToken); + + return finishNode(result); + } + function parseJSDocUnionType(): JSDocUnionType { let result = createNode(SyntaxKind.JSDocUnionType); nextToken(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d8b8a860acfbf..154e5c95281b5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -277,6 +277,7 @@ module ts { JSDocUnknownType, JSDocArrayType, JSDocUnionType, + JSDocTupleType, JSDocNullableType, JSDocNonNullableType, JSDocRecordType, @@ -1040,6 +1041,10 @@ module ts { types: NodeArray; } + export interface JSDocTupleType extends JSDocType { + types: NodeArray; + } + export interface JSDocNonNullableType extends JSDocType { type: JSDocType; } diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index ce0244c211a39..43bff446e304b 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -23,37 +23,37 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) >ts : any, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1151, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1155, 5)) var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1280, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1284, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1280, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1284, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) var emitResult = program.emit(); >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) >program.emit() : ts.EmitResult ->program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 844, 39)) +>program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 848, 39)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 844, 39)) +>emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 848, 39)) var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); >allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1278, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1282, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1278, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1282, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 897, 29)) +>emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 901, 29)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 897, 29)) +>diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 901, 29)) allDiagnostics.forEach(diagnostic => { >allDiagnostics.forEach(diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); }) : void @@ -67,24 +67,24 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1283, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1283, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >'\n' : string console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); @@ -93,11 +93,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) >log : any >`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >1 : number @@ -111,9 +111,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var exitCode = emitResult.emitSkipped ? 1 : 0; >exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) >emitResult.emitSkipped ? 1 : 0 : number ->emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 896, 26)) +>emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 900, 26)) >emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 896, 26)) +>emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 900, 26)) >1 : number >0 : number @@ -153,16 +153,16 @@ compile(process.argv.slice(2), { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS >target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45)) ->ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1194, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) +>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1198, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) ->ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1194, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) +>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1198, 16)) >module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) }); diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index d2851eb9458b5..f7d6cae1e15f6 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 817, 5), Decl(typescript.d.ts, 1340, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 821, 5), Decl(typescript.d.ts, 1344, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,12 +33,12 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 311, 5), Decl(typescript.d.ts, 1300, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1304, 32)) switch (node.kind) { ->node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) case ts.SyntaxKind.ForStatement: >ts.SyntaxKind.ForStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForStatement, Decl(typescript.d.ts, 209, 29)) @@ -70,15 +70,15 @@ export function delint(sourceFile: ts.SourceFile) { if ((node).statement.kind !== ts.SyntaxKind.Block) { >(node).statement.kind !== ts.SyntaxKind.Block : boolean ->(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) ->(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 604, 52)) +>(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) +>(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 605, 52)) >(node) : ts.IterationStatement >node : ts.IterationStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 603, 5)) +>IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 604, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 604, 52)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 605, 52)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -105,16 +105,16 @@ export function delint(sourceFile: ts.SourceFile) { >(node) : ts.IfStatement >node : ts.IfStatement >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 598, 5)) +>IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 599, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) { >ifStatement.thenStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) +>ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -124,25 +124,25 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); >report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) +>ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 600, 31)) +>thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) >"An if statement's contents should be wrapped in a block body." : string } if (ifStatement.elseStatement && >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean >ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && >ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) >ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -151,11 +151,11 @@ export function delint(sourceFile: ts.SourceFile) { ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) { >ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) >ts.SyntaxKind.IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) >ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) @@ -165,9 +165,9 @@ export function delint(sourceFile: ts.SourceFile) { report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); >report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.") : void >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) >ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 601, 33)) +>elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) >"An else statement's contents should be wrapped in a block body." : string } break; @@ -181,15 +181,15 @@ export function delint(sourceFile: ts.SourceFile) { let op = (node).operatorToken.kind; >op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) ->(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 512, 25)) +>(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) +>(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 513, 25)) >(node) : ts.BinaryExpression >node : ts.BinaryExpression >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 510, 5)) +>BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 511, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 512, 25)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 312, 38)) +>operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 513, 25)) +>kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) { >op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken : boolean @@ -219,9 +219,9 @@ export function delint(sourceFile: ts.SourceFile) { ts.forEachChild(node, delintNode); >ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1264, 48)) +>ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1268, 48)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1264, 48)) +>forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1268, 48)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) } @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 311, 5), Decl(typescript.d.ts, 1300, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1304, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1305, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1309, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1305, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1309, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -251,9 +251,9 @@ export function delint(sourceFile: ts.SourceFile) { >console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) >log : any >`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}` : string ->sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >1 : number @@ -286,9 +286,9 @@ fileNames.forEach(fileName => { let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) >ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1268, 62)) +>ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1272, 62)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1268, 62)) +>createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1272, 62)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >readFileSync(fileName).toString() : any >readFileSync(fileName).toString : any @@ -296,11 +296,11 @@ fileNames.forEach(fileName => { >readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) >fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) >toString : any ->ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1195, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) +>ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1199, 16)) +>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1192, 5)) ->ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1195, 16)) +>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) +>ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1199, 16)) >true : boolean // delint it diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 5e8e05850ef93..e5bc33d53512f 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,17 +19,17 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1807, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1811, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1807, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1811, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) console.log(JSON.stringify(result)); >console.log(JSON.stringify(result)) : any diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index a48f440d8a42c..e7b726a7df86c 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -26,7 +26,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1151, 5)) +>CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1155, 5)) const files: ts.Map<{ version: number }> = {}; >files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1373, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1377, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1366, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1365, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1370, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1369, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1365, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1366, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1369, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1370, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1815, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1819, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1815, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1819, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1813, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1817, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1813, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1817, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1811, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1815, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1811, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1815, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1417, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1421, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1417, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1421, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1620, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1624, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1620, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1624, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1619, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1623, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1619, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1623, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1628, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1632, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1628, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1630, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1632, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1634, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1630, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1634, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1391, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1395, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1391, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1395, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1389, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1393, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1389, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1393, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1390, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1394, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1390, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1394, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,31 +333,31 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1283, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1279, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1283, 67)) +>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1142, 23)) +>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >"\n" : string if (diagnostic.file) { ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1341, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1345, 26)) +>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1140, 25)) +>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any @@ -365,11 +365,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) >log : any >` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) +>diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) +>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1139, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 820, 29)) +>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) +>fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) >line + 1 : number >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >1 : number @@ -435,9 +435,9 @@ watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }); >currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_watcher.ts, 102, 30)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) +>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) +>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1183, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1185, 17)) +>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) +>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo4.ts b/tests/cases/fourslash/getJavaScriptQuickInfo4.ts new file mode 100644 index 0000000000000..c2a1095d23573 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo4.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @param {[number,string]} [a] */ +////function /**/f(a) { } + +debugger; +goTo.marker(); +verify.quickInfoIs('function f(a?: [number, string]): void'); \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index fbd65f92d15c7..10537cd444a6d 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -921,6 +921,132 @@ module ts { "end": 10, "text": "undefined" } +}`); + }); + + it("tupleType0", () => { + parsesCorrectly( + "{[]}", + `{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 3, + "types": { + "length": 0, + "pos": 2, + "end": 2 + } +}`); + }); + + it("tupleType1", () => { + parsesCorrectly( + "{[number]}", + `{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 9, + "types": { + "0": { + "kind": "JSDocTypeReference", + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 8, + "text": "number" + } + }, + "length": 1, + "pos": 2, + "end": 8 + } +}`); + }); + + it("tupleType2", () => { + parsesCorrectly( + "{[number,string]}", + `{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 16, + "types": { + "0": { + "kind": "JSDocTypeReference", + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 8, + "text": "number" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 9, + "end": 15, + "name": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "string" + } + }, + "length": 2, + "pos": 2, + "end": 15 + } +}`); + }); + + it("tupleType3", () => { + parsesCorrectly( + "{[number,string,boolean]}", + `{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 24, + "types": { + "0": { + "kind": "JSDocTypeReference", + "pos": 2, + "end": 8, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 8, + "text": "number" + } + }, + "1": { + "kind": "JSDocTypeReference", + "pos": 9, + "end": 15, + "name": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "string" + } + }, + "2": { + "kind": "JSDocTypeReference", + "pos": 16, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 16, + "end": 23, + "text": "boolean" + } + }, + "length": 3, + "pos": 2, + "end": 23 + } }`); }); }); @@ -990,10 +1116,6 @@ module ts { parsesIncorrectly("{new () => string}"); }); - it("tupleType", () => { - parsesIncorrectly("{[number,string]}"); - }); - it("typeOfType", () => { parsesIncorrectly("{typeof M}"); }); @@ -1009,6 +1131,18 @@ module ts { it("methodInRecordType", () => { parsesIncorrectly("{{foo(): number}}"); }); + + it("tupleTypeWithComma", () => { + parsesIncorrectly( "{[,]}"); + }); + + it("tupleTypeWithTrailingComma", () => { + parsesIncorrectly("{[number,]}"); + }); + + it("tupleTypeWithLeadingComma", () => { + parsesIncorrectly("{[,number]}"); + }); }); }); From 0c8e6693c271109ec8ffccc673a785c575c77a28 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 18:04:29 -0700 Subject: [PATCH 50/96] Properly set parents for all js doc nodes. --- src/compiler/parser.ts | 8 ++- .../reference/APISample_compile.types | 16 ++--- .../reference/APISample_linter.types | 14 ++--- .../reference/APISample_transform.types | 4 +- .../reference/APISample_watcher.types | 62 +++++++++---------- 5 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5df6f101b20bf..7b5efa07656fc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -321,6 +321,10 @@ module ts { return visitNode(cbNode, (node).type); case SyntaxKind.JSDocUnionType: return visitNodes(cbNodes, (node).types); + case SyntaxKind.JSDocTupleType: + return visitNodes(cbNodes, (node).types); + case SyntaxKind.JSDocArrayType: + return visitNode(cbNode, (node).elementType); case SyntaxKind.JSDocNonNullableType: return visitNode(cbNode, (node).type); case SyntaxKind.JSDocNullableType: @@ -367,11 +371,13 @@ module ts { export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); } - + + /* @internal */ export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { return JSDocParser.parseJSDocComment(parent, content, start, length); } + /* @internal */ export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocTypeExpression { return JSDocParser.parseJSDocTypeExpression(content, start, length); } diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 7c17fcad1c745..676394cfedc27 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -28,9 +28,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var program = ts.createProgram(fileNames, options); >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1309, 113)) +>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1307, 113)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1309, 113)) +>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1307, 113)) >fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) @@ -46,9 +46,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] >ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1307, 98)) +>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1305, 98)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1307, 98)) +>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1305, 98)) >program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 901, 29)) @@ -67,11 +67,11 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void >line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) >character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) @@ -79,9 +79,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); >message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1308, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1308, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index cfb775ffd88fa..f2a7c475ae5f7 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -22,7 +22,7 @@ export function delint(sourceFile: ts.SourceFile) { >delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 821, 5), Decl(typescript.d.ts, 1369, 5)) +>SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 821, 5), Decl(typescript.d.ts, 1367, 5)) delintNode(sourceFile); >delintNode(sourceFile) : void @@ -33,7 +33,7 @@ export function delint(sourceFile: ts.SourceFile) { >delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1329, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1327, 32)) switch (node.kind) { >node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) @@ -230,20 +230,20 @@ export function delint(sourceFile: ts.SourceFile) { >report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) >ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1329, 32)) +>Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1327, 32)) >message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); >line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) >character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) >sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1334, 53)) +>node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1332, 53)) >node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1334, 53)) +>getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1332, 53)) console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); >console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index d12871f8f3ffb..76622027caa23 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -19,9 +19,9 @@ const source = "let x: string = 'string'"; let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); >result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) >ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1836, 5)) +>ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1834, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1836, 5)) +>transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1834, 5)) >source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) >{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } >module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 6b18d443b27af..0930a1ebbff59 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -59,7 +59,7 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const servicesHost: ts.LanguageServiceHost = { >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1402, 5)) +>LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1400, 5)) >{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } getScriptFileNames: () => rootFileNames, @@ -103,11 +103,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); >ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1395, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1394, 5)) +>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1393, 27)) +>ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1392, 5)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1394, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1395, 27)) +>ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1392, 5)) +>fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1393, 27)) >fs.readFileSync(fileName).toString() : any >fs.readFileSync(fileName).toString : any >fs.readFileSync(fileName) : any @@ -136,9 +136,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) >ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1844, 44)) +>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1842, 44)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1844, 44)) +>getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1842, 44)) >options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) }; @@ -147,14 +147,14 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) >ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1842, 97)) +>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1840, 97)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1842, 97)) +>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1840, 97)) >servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) >ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1840, 193)) +>ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1838, 193)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1840, 193)) +>createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1838, 193)) // Now let's watch the files rootFileNames.forEach(fileName => { @@ -231,16 +231,16 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let output = services.getEmitOutput(fileName); >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) >services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1446, 132)) +>services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1444, 132)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1446, 132)) +>getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1444, 132)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) if (!output.emitSkipped) { >!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1649, 34)) +>output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1647, 34)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1649, 34)) +>emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1647, 34)) console.log(`Emitting ${fileName}`); >console.log(`Emitting ${fileName}`) : any @@ -268,9 +268,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { output.outputFiles.forEach(o => { >output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void >output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1648, 26)) +>output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1646, 26)) >output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1648, 26)) +>outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1646, 26)) >forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) >o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) @@ -280,12 +280,12 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >fs.writeFileSync : any >fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) >writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1657, 26)) +>o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1655, 26)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1657, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1659, 36)) +>name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1655, 26)) +>o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1657, 36)) >o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1659, 36)) +>text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1657, 36)) >"utf8" : string }); @@ -302,24 +302,24 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] >services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1420, 63)) +>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1418, 63)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1420, 63)) +>getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1418, 63)) .concat(services.getSyntacticDiagnostics(fileName)) >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1418, 37)) +>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1416, 37)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1418, 37)) +>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1416, 37)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) .concat(services.getSemanticDiagnostics(fileName)); >concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) >services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1419, 64)) +>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1417, 64)) >services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1419, 64)) +>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1417, 64)) >fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) allDiagnostics.forEach(diagnostic => { @@ -333,9 +333,9 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); >message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) >ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1308, 67)) +>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) >ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1308, 67)) +>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) >diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) @@ -350,11 +350,11 @@ function watch(rootFileNames: string[], options: ts.CompilerOptions) { >line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) >character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) >diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1370, 26)) +>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) >diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) >diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) >start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) From 6ac6ed8ac61a190eedcdd55c84e9e832e6d6f1cd Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 18:49:29 -0700 Subject: [PATCH 51/96] Simplify initialization/cleanup in the parser. --- src/compiler/parser.ts | 77 +++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7b5efa07656fc..b1e021ec6cfdc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -392,6 +392,7 @@ module ts { const disallowInAndDecoratorContext = ParserContextFlags.DisallowIn | ParserContextFlags.Decorator; let sourceFile: SourceFile; + let parseDiagnostics: Diagnostic[]; let syntaxCursor: IncrementalParser.SyntaxCursor; let token: SyntaxKind; @@ -480,9 +481,20 @@ module ts { let parseErrorBeforeNextFinishedNode: boolean = false; export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile { + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); + + let result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + + clearState(); + + return result; + } + + function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor) { sourceText = _sourceText; syntaxCursor = _syntaxCursor; + parseDiagnostics = []; parsingContext = 0; identifiers = {}; identifierCount = 0; @@ -491,14 +503,30 @@ module ts { contextFlags = isJavaScript(fileName) ? ParserContextFlags.JavaScriptFile : ParserContextFlags.None; parseErrorBeforeNextFinishedNode = false; - createSourceFile(fileName, languageVersion); - // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - token = nextToken(); + } + + function clearState() { + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. + scanner.setText(""); + scanner.setOnError(undefined); + + // Clear any data. We don't want to accidently hold onto it for too long. + parseDiagnostics = undefined; + sourceFile = undefined; + identifiers = undefined; + syntaxCursor = undefined; + sourceText = undefined; + } + + function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean): SourceFile { + sourceFile = createSourceFile(fileName, languageVersion); + // Prime the scanner. + token = nextToken(); processReferenceComments(sourceFile); sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement); @@ -510,26 +538,13 @@ module ts { sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; + sourceFile.parseDiagnostics = parseDiagnostics; if (setParentNodes) { fixupParentReferences(sourceFile); } - syntaxCursor = undefined; - - // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. - scanner.setText(""); - scanner.setOnError(undefined); - - let result = sourceFile; - - // Clear any data. We don't want to accidently hold onto it for too long. - sourceFile = undefined; - identifiers = undefined; - syntaxCursor = undefined; - sourceText = undefined; - - return result; + return sourceFile; } export function fixupParentReferences(sourceFile: Node) { @@ -557,18 +572,18 @@ module ts { } } - function createSourceFile(fileName: string, languageVersion: ScriptTarget) { - sourceFile = createNode(SyntaxKind.SourceFile, /*pos*/ 0); + function createSourceFile(fileName: string, languageVersion: ScriptTarget): SourceFile { + let sourceFile = createNode(SyntaxKind.SourceFile, /*pos*/ 0); sourceFile.pos = 0; sourceFile.end = sourceText.length; sourceFile.text = sourceText; - - sourceFile.parseDiagnostics = []; sourceFile.bindDiagnostics = []; sourceFile.languageVersion = languageVersion; sourceFile.fileName = normalizePath(fileName); sourceFile.flags = fileExtensionIs(sourceFile.fileName, ".d.ts") ? NodeFlags.DeclarationFile : 0; + + return sourceFile; } function setContextFlag(val: Boolean, flag: ParserContextFlags) { @@ -702,9 +717,9 @@ module ts { function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): void { // Don't report another error if it would just be at the same position as the last error. - let lastError = lastOrUndefined(sourceFile.parseDiagnostics); + let lastError = lastOrUndefined(parseDiagnostics); if (!lastError || start !== lastError.start) { - sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0)); + parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0)); } // Mark that we've encountered an error. We'll set an appropriate bit on the next @@ -749,7 +764,7 @@ module ts { // Keep track of the state we'll need to rollback to if lookahead fails (or if the // caller asked us to always reset our state). let saveToken = token; - let saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length; + let saveParseDiagnosticsLength = parseDiagnostics.length; let saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; // Note: it is not actually necessary to save/restore the context flags here. That's @@ -771,7 +786,7 @@ module ts { // then unconditionally restore us to where we were. if (!result || isLookAhead) { token = saveToken; - sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength; + parseDiagnostics.length = saveParseDiagnosticsLength; parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; } @@ -1240,7 +1255,7 @@ module ts { // test elements only if we are not already in strict mode if (checkForStrictMode && !inStrictModeContext()) { if (isPrologueDirective(element)) { - if (isUseStrictPrologueDirective(sourceFile, element)) { + if (isUseStrictPrologueDirective(element)) { setStrictModeContext(true); checkForStrictMode = false; } @@ -1265,9 +1280,9 @@ module ts { } /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(sourceFile: SourceFile, node: Node): boolean { + function isUseStrictPrologueDirective(node: Node): boolean { Debug.assert(isPrologueDirective(node)); - let nodeText = getSourceTextOfNodeFromSourceFile(sourceFile, (node).expression); + let nodeText = getTextOfNodeFromSourceText(sourceText, (node).expression); // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the // string to contain unicode escapes (as per ES5). @@ -4815,7 +4830,7 @@ module ts { referencedFiles.push(fileReference); } if (diagnosticMessage) { - sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage)); + parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage)); } } else { @@ -4823,7 +4838,7 @@ module ts { let amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment); if (amdModuleNameMatchResult) { if (amdModuleName) { - sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments)); + parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments)); } amdModuleName = amdModuleNameMatchResult[2]; } From 9169acf729bf3c8e211dae32beda92f00da73d15 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 19:03:13 -0700 Subject: [PATCH 52/96] Proactively parse out js doc comments for .js files. --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 8 +++--- src/compiler/parser.ts | 58 +++++++++++++++++++++++++++------------ src/compiler/types.ts | 17 ++++++------ src/compiler/utilities.ts | 19 ++----------- 5 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2ddf287649aea..ee52fbedd402a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -270,7 +270,7 @@ module ts { } function bindJSDocTypeParameters(node: FunctionLikeDeclaration) { - let jsDocComment = getJSDocComment(node, file); + let jsDocComment = node.jsDocComment; if (jsDocComment) { forEach(jsDocComment.typeParameters, bind); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b00485944d18e..f8d7c110e2eda 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2118,7 +2118,7 @@ module ts { function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { // First, see if this node has an @type annotation on it directly. let sourceFile = getSourceFileOfNode(declaration); - let docComment = getJSDocComment(declaration, sourceFile); + let docComment = declaration.jsDocComment; if (docComment && docComment.type) { return docComment.type; @@ -2129,7 +2129,7 @@ module ts { declaration.parent.parent.kind === SyntaxKind.VariableStatement) { // @type annotation might have been on the variable statement, try that instead. - docComment = getJSDocComment(declaration.parent.parent, sourceFile); + docComment = declaration.parent.parent.jsDocComment; if (docComment && docComment.type) { return docComment.type; } @@ -3089,7 +3089,7 @@ module ts { function getTypeParametersFromSignatureDeclaration(declaration: SignatureDeclaration): TypeParameter[] { if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { - let jsDocComment = getJSDocComment(declaration, getSourceFile(declaration)); + let jsDocComment = declaration.jsDocComment; if (jsDocComment && jsDocComment.typeParameters) { return getTypeParametersFromTypeParameterDeclarations(jsDocComment.typeParameters); } @@ -7438,7 +7438,7 @@ module ts { } function getReturnTypeFromJSDocComment(func: FunctionLikeDeclaration): Type { - let jsDocComment = getJSDocComment(func, getSourceFile(func)); + let jsDocComment = func.jsDocComment; if (jsDocComment && jsDocComment.returnType) { return getTypeFromTypeNode(jsDocComment.returnType); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b1e021ec6cfdc..ccf2c2b963d14 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -373,11 +373,13 @@ module ts { } /* @internal */ + // Exposed only for testing. export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { return JSDocParser.parseJSDocComment(parent, content, start, length); } /* @internal */ + // Exposed only for testing. export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocTypeExpression { return JSDocParser.parseJSDocTypeExpression(content, start, length); } @@ -544,9 +546,46 @@ module ts { fixupParentReferences(sourceFile); } + // If this is a javascript file, proactively see if we can get JSDoc comments for + // relevant nodes in the file. We'll use these to provide typing informaion if they're + // available. + if (isJavaScript(fileName)) { + parseJSDocComments(); + } + return sourceFile; } + function parseJSDocComments() { + forEachChild(sourceFile, visit); + return; + + function visit(node: Node) { + // Add additional cases as necessary depending on how we see JSDoc comments used + // in the wild. + switch (node.kind) { + case SyntaxKind.VariableStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Parameter: + parseJSDocComment(node); + } + + forEachChild(node, visit); + } + } + + function parseJSDocComment(node: Node) { + let comments = getLeadingCommentRangesOfNode(node, sourceFile); + if (comments) { + for (let comment of comments) { + let jsDocComment = ts.parseJSDocComment(node, sourceText, comment.pos, comment.end - comment.pos); + if (jsDocComment) { + node.jsDocComment = jsDocComment; + } + } + } + } + export function fixupParentReferences(sourceFile: Node) { // normally parent references are set during binding. However, for clients that only need // a syntax tree, and no semantic features, then the binding process is an unnecessary @@ -5016,6 +5055,7 @@ module ts { // Ditch any existing LS children we may have created. This way we can avoid // moving them forward. node._children = undefined; + node.jsDocComment = undefined; node.pos += delta; node.end += delta; @@ -5916,25 +5956,7 @@ module ts { } } - interface NodeWithComment extends Node { - _docComment: JSDocComment; - } - export function parseJSDocComment(parent: Node, content: string, start: number, length: number): JSDocComment { - let nodeWithComment = parent; - if (nodeWithComment && nodeWithComment._docComment) { - return nodeWithComment._docComment; - } - - let result = parseJSDocCommentWorker(parent, content, start, length); - if (nodeWithComment && result) { - nodeWithComment._docComment = result; - } - - return result; - } - - function parseJSDocCommentWorker(parent: Node, content: string, start: number, length: number): JSDocComment { start = start || 0; let end = length === undefined ? content.length : start + length; length = end - start; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index adaf793fc34c9..49f7da6c884a8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -395,14 +395,15 @@ module ts { // Specific context the parser was in when this node was created. Normally undefined. // Only set when the parser was in some interesting context (like async/yield). /* @internal */ parserContextFlags?: ParserContextFlags; - decorators?: NodeArray; // Array of decorators (in document order) - modifiers?: ModifiersArray; // Array of modifiers - /* @internal */ id?: number; // Unique id (used to look up NodeLinks) - parent?: Node; // Parent node (initialized by binding) - /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) - /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) - /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) - /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) + decorators?: NodeArray; // Array of decorators (in document order) + modifiers?: ModifiersArray; // Array of modifiers + /* @internal */ id?: number; // Unique id (used to look up NodeLinks) + parent?: Node; // Parent node (initialized by binding + /* @internal */ jsDocComment?: JSDocComment; // JSDoc for the node, if it has any. Only for .js files. + /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) + /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) + /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) + /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) } export interface NodeArray extends Array, TextRange { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 07872732c76f9..39766dc0b3a3d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -855,7 +855,7 @@ module ts { // annotation. let parameterName = (parameter.name).text; - let docComment = getJSDocComment(parameter.parent, sourceFile); + let docComment = parameter.parent.jsDocComment; if (docComment && docComment.parameters) { for (let parameter of docComment.parameters) { if (parameter.name === parameterName) { @@ -1726,21 +1726,6 @@ module ts { export function isJavaScript(fileName: string) { return fileExtensionIs(fileName, ".js"); } - - /* @internal */ - export function getJSDocComment(node: Node, sourceFile: SourceFile) { - let comments = getLeadingCommentRangesOfNode(node, sourceFile); - if (comments) { - for (let comment of comments) { - let jsDocComment = parseJSDocComment(node, sourceFile.text, comment.pos, comment.end - comment.pos); - if (jsDocComment) { - return jsDocComment; - } - } - } - - return undefined; - } } module ts { @@ -1958,4 +1943,4 @@ module ts { return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength:*/ newEndN - oldStartN); } -} +} From 8645b69243fcf23074d8122ee167e2bad418c0f8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 21:54:28 -0700 Subject: [PATCH 53/96] Utilize the core parsing functionality to support parsing JSDoc expressions. --- src/compiler/core.ts | 6 +- .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 + src/compiler/parser.ts | 2033 ++++++++--------- src/compiler/types.ts | 6 +- src/compiler/utilities.ts | 2 +- src/harness/harness.ts | 10 +- .../fourslash/getJavaScriptQuickInfo1.ts | 1 + tests/cases/unittests/jsDocParsing.ts | 271 ++- 9 files changed, 1174 insertions(+), 1160 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 808400683327a..769e2add94a9c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -301,8 +301,10 @@ module ts { Debug.assert(start >= 0, "start must be non-negative, is " + start); Debug.assert(length >= 0, "length must be non-negative, is " + length); - Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); - Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); + if (file) { + Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`); + Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`); + } let text = getLocaleSpecificMessage(message.key); diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index db9d635a76644..c2657430cedb1 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -175,6 +175,7 @@ module ts { Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" }, Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." }, Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." }, + _0_tag_already_specified: { code: 1218, category: DiagnosticCategory.Error, key: "'{0}' tag already specified." }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 71c520285622b..4983f71bdc103 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -687,6 +687,10 @@ "category": "Error", "code": 1217 }, + "'{0}' tag already specified.": { + "category": "Error", + "code": 1218 + }, "Duplicate identifier '{0}'.": { "category": "Error", "code": 2300 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ccf2c2b963d14..bfbd14cd3e185 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -345,9 +345,9 @@ module ts { return visitNode(cbNode, (node).type); case SyntaxKind.JSDocThisType: return visitNode(cbNode, (node).type); - case SyntaxKind.JSDocMember: - return visitNode(cbNode, (node).name) || - visitNode(cbNode, (node).type); + case SyntaxKind.JSDocRecordMember: + return visitNode(cbNode, (node).name) || + visitNode(cbNode, (node).type); } } @@ -374,14 +374,14 @@ module ts { /* @internal */ // Exposed only for testing. - export function parseJSDocComment(parent: Node, content: string, start?: number, length?: number): JSDocComment { - return JSDocParser.parseJSDocComment(parent, content, start, length); + export function parseJSDocComment(content: string, start?: number, length?: number) { + return Parser.JSDocParser.parseJSDocCommentForTests(content, start, length); } /* @internal */ // Exposed only for testing. - export function parseJSDocTypeExpression(content: string, start?: number, length?: number): JSDocTypeExpression { - return JSDocParser.parseJSDocTypeExpression(content, start, length); + export function parseJSDocTypeExpression(content: string, start?: number, length?: number) { + return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); } // Implement the parser as a singleton module. We do this for perf reasons because creating @@ -550,13 +550,13 @@ module ts { // relevant nodes in the file. We'll use these to provide typing informaion if they're // available. if (isJavaScript(fileName)) { - parseJSDocComments(); + addJSDocComments(); } return sourceFile; } - function parseJSDocComments() { + function addJSDocComments() { forEachChild(sourceFile, visit); return; @@ -567,18 +567,18 @@ module ts { case SyntaxKind.VariableStatement: case SyntaxKind.FunctionDeclaration: case SyntaxKind.Parameter: - parseJSDocComment(node); + addJSDocComment(node); } forEachChild(node, visit); } } - function parseJSDocComment(node: Node) { + function addJSDocComment(node: Node) { let comments = getLeadingCommentRangesOfNode(node, sourceFile); if (comments) { for (let comment of comments) { - let jsDocComment = ts.parseJSDocComment(node, sourceText, comment.pos, comment.end - comment.pos); + let jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); if (jsDocComment) { node.jsDocComment = jsDocComment; } @@ -1003,16 +1003,28 @@ module ts { token === SyntaxKind.NumericLiteral; } - function parsePropertyName(): DeclarationName { + function parsePropertyNameWorker(allowComputedPropertyNames: boolean): DeclarationName { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { return parseLiteralNode(/*internName:*/ true); } - if (token === SyntaxKind.OpenBracketToken) { + if (allowComputedPropertyNames && token === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); } return parseIdentifierName(); } + function parsePropertyName(): DeclarationName { + return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true); + } + + function parseSimplePropertyName(): Identifier | LiteralExpression { + return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ false); + } + + function isSimplePropertyName() { + return token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || isIdentifierOrKeyword(); + } + function parseComputedPropertyName(): ComputedPropertyName { // PropertyName[Yield,GeneratorParameter] : // LiteralPropertyName @@ -1152,6 +1164,12 @@ module ts { return isHeritageClause(); case ParsingContext.ImportOrExportSpecifiers: return isIdentifierOrKeyword(); + case ParsingContext.JSDocFunctionParameters: + case ParsingContext.JSDocTypeArguments: + case ParsingContext.JSDocTupleTypes: + return JSDocParser.isJSDocType(); + case ParsingContext.JSDocRecordMembers: + return isSimplePropertyName(); } Debug.fail("Non-exhaustive case in 'isListElement'."); @@ -1237,6 +1255,14 @@ module ts { return token === SyntaxKind.GreaterThanToken || token === SyntaxKind.OpenParenToken; case ParsingContext.HeritageClauses: return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.CloseBraceToken; + 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; } } @@ -1642,6 +1668,10 @@ module ts { case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected; case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected; case ParsingContext.ImportOrExportSpecifiers: 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; } }; @@ -4913,7 +4943,7 @@ module ts { : undefined); } - export function createNodeAtPosition(scanner: Scanner, kind: SyntaxKind, pos?: number): Node { + function createNodeAtPosition(scanner: Scanner, kind: SyntaxKind, pos?: number): Node { let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); if (!(pos >= 0)) { pos = scanner.getStartPos(); @@ -4946,6 +4976,10 @@ module 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 } @@ -4954,1265 +4988,1170 @@ module ts { True, Unknown } - } - module IncrementalParser { - export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { - aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive); + export module 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; + } - checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); - if (textChangeRangeIsUnchanged(textChangeRange)) { - // if the text didn't change, then we can just return our current source file as-is. - return sourceFile; + return isIdentifierOrKeyword(); } - if (sourceFile.statements.length === 0) { - // If we don't have any statements in the current source file, then there's no real - // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setNodeParents*/ true) - } + export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) { + initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined); + let jsDocTypeExpression = parseJSDocTypeExpression(start, length); + let diagnostics = parseDiagnostics; + clearState(); - // Make sure we're not trying to incrementally update a source file more than once. Once - // we do an update the original source file is considered unusbale from that point onwards. - // - // This is because we do incremental parsing in-place. i.e. we take nodes from the old - // tree and give them new positions and parents. From that point on, trusting the old - // tree at all is not possible as far too much of it may violate invariants. - let incrementalSourceFile = sourceFile; - Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); - incrementalSourceFile.hasBeenIncrementallyParsed = true; + return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined; + } - let oldText = sourceFile.text; - let syntaxCursor = createSyntaxCursor(sourceFile); + // Parses out a JSDoc type expression. The starting position should be right at the open + // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. + /* @internal */ + export function parseJSDocTypeExpression(start: number, length: number): JSDocTypeExpression { + scanner.setText(sourceText, start, length); + + // Prime the first token for us to start processing. + token = nextToken(); + if (token !== SyntaxKind.OpenBraceToken) { + return undefined; + } - // Make the actual change larger so that we know to reparse anything whose lookahead - // might have intersected the change. - let changeRange = extendToAffectedRange(sourceFile, textChangeRange); - checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); + let result = createNode(SyntaxKind.JSDocTypeExpression); - // Ensure that extending the affected range only moved the start of the change range - // earlier in the file. - Debug.assert(changeRange.span.start <= textChangeRange.span.start); - Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span)); - Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange))); + parseExpected(SyntaxKind.OpenBraceToken); + result.type = parseJSDocTopLevelType(); + parseExpected(SyntaxKind.CloseBraceToken); - // The is the amount the nodes after the edit range need to be adjusted. It can be - // positive (if the edit added characters), negative (if the edit deleted characters) - // or zero (if this was a pure overwrite with nothing added/removed). - let delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + fixupParentReferences(result); + return finishNode(result); + } - // If we added or removed characters during the edit, then we need to go and adjust all - // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they - // may move backward (if we deleted chars). - // - // Doing this helps us out in two ways. First, it means that any nodes/tokens we want - // to reuse are already at the appropriate position in the new text. That way when we - // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes - // it very easy to determine if we can reuse a node. If the node's position is at where - // we are in the text, then we can reuse it. Otherwise we can't. If the node's position - // is ahead of us, then we'll need to rescan tokens. If the node's position is behind - // us, then we'll need to skip it or crumble it as appropriate - // - // We will also adjust the positions of nodes that intersect the change range as well. - // By doing this, we ensure that all the positions in the old tree are consistent, not - // just the positions of nodes entirely before/after the change range. By being - // consistent, we can then easily map from positions to nodes in the old tree easily. - // - // Also, mark any syntax elements that intersect the changed span. We know, up front, - // that we cannot reuse these elements. - updateTokenPositionsAndMarkElements(incrementalSourceFile, - changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); + function setError(message: DiagnosticMessage) { + parseErrorAtCurrentToken(message); + // error = true; + if (throwOnJSDocErrors) { + throw new Error(message.key); + } + } - // Now that we've set up our internal incremental state just proceed and parse the - // source file in the normal fashion. When possible the parser will retrieve and - // reuse nodes from the old tree. - // - // Note: passing in 'true' for setNodeParents is very important. When incrementally - // parsing, we will be reusing nodes from the old tree, and placing it into new - // parents. If we don't set the parents now, we'll end up with an observably - // inconsistent tree. Setting the parents on the new tree should be very fast. We - // will immediately bail out of walking any subtrees when we can see that their parents - // are already correct. - let result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true) + function parseJSDocTopLevelType(): JSDocType { + var type = parseJSDocType(); + if (token === SyntaxKind.BarToken) { + var unionType = createNode(SyntaxKind.JSDocUnionType, type.pos); + unionType.types = parseJSDocTypeList(type); + type = finishNode(unionType); + } - return result; - } + if (token === SyntaxKind.EqualsToken) { + var optionalType = createNode(SyntaxKind.JSDocOptionalType, type.pos); + nextToken(); + optionalType.type = type; + type = finishNode(optionalType); + } - function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) { - if (isArray) { - visitArray(element); - } - else { - visitNode(element); + return type; } - return; - function visitNode(node: IncrementalNode) { - if (aggressiveChecks && shouldCheckNode(node)) { - var text = oldText.substring(node.pos, node.end); - } + function parseJSDocType(): JSDocType { + let type = parseBasicTypeExpression(); - // Ditch any existing LS children we may have created. This way we can avoid - // moving them forward. - node._children = undefined; - node.jsDocComment = undefined; - node.pos += delta; - node.end += delta; + while (true) { + if (token === SyntaxKind.OpenBracketToken) { + let arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); + arrayType.elementType = type; - if (aggressiveChecks && shouldCheckNode(node)) { - Debug.assert(text === newText.substring(node.pos, node.end)); + nextToken(); + parseExpected(SyntaxKind.CloseBracketToken); + + type = finishNode(arrayType); + } + else if (token === SyntaxKind.QuestionToken) { + let nullableType = createNode(SyntaxKind.JSDocNullableType, type.pos); + nullableType.type = type; + + nextToken(); + type = finishNode(nullableType); + } + else if (token === SyntaxKind.ExclamationToken) { + let nonNullableType = createNode(SyntaxKind.JSDocNonNullableType, type.pos); + nonNullableType.type = type; + + nextToken(); + type = finishNode(nonNullableType); + } + else { + break; + } } - forEachChild(node, visitNode, visitArray); - checkNodePositions(node, aggressiveChecks); + return type; } - function visitArray(array: IncrementalNodeArray) { - array._children = undefined; - array.pos += delta; - array.end += delta; + //return parseJSDocTypeReference(); - for (let node of array) { - visitNode(node); + //} + + 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: + return parseJSDocFunctionType(); + case SyntaxKind.DotDotDotToken: + return parseJSDocVariadicType(); + case SyntaxKind.NewKeyword: + return parseJSDocConstructorType(); + case SyntaxKind.ThisKeyword: + return parseJSDocThisType(); } + + return parseJSDocTypeReference(); } - } - function shouldCheckNode(node: Node) { - switch (node.kind) { - case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.Identifier: - return true; + function parseJSDocThisType(): JSDocThisType { + let result = createNode(SyntaxKind.JSDocThisType); + nextToken(); + parseExpected(SyntaxKind.ColonToken); + result.type = parseJSDocType(); + return finishNode(result); } - return false; - } + function parseJSDocConstructorType(): JSDocConstructorType { + let result = createNode(SyntaxKind.JSDocConstructorType); + nextToken(); + parseExpected(SyntaxKind.ColonToken); + result.type = parseJSDocType(); + return finishNode(result); + } - function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { - Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); - Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); - Debug.assert(element.pos <= element.end); + function parseJSDocVariadicType(): JSDocVariadicType { + let result = createNode(SyntaxKind.JSDocVariadicType); + nextToken(); + result.type = parseJSDocType(); + return finishNode(result); + } - // We have an element that intersects the change range in some way. It may have its - // start, or its end (or both) in the changed range. We want to adjust any part - // that intersects such that the final tree is in a consistent state. i.e. all - // chlidren have spans within the span of their parent, and all siblings are ordered - // properly. + function parseJSDocFunctionType(): JSDocFunctionType { + let result = createNode(SyntaxKind.JSDocFunctionType); + nextToken(); - // We may need to update both the 'pos' and the 'end' of the element. + parseExpected(SyntaxKind.OpenParenToken); + result.parameters = parseDelimitedList(ParsingContext.JSDocFunctionParameters, parseJSDocParameter); + checkForTrailingComma(result.parameters); + parseExpected(SyntaxKind.CloseParenToken); - // If the 'pos' is before the start of the change, then we don't need to touch it. - // If it isn't, then the 'pos' must be inside the change. How we update it will - // depend if delta is positive or negative. If delta is positive then we have - // something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that started in the change range to still be - // starting at the same position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that started in the 'X' range will keep its position. - // However any element htat started after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that started in the 'Y' range will - // be adjusted to have their start at the end of the 'Z' range. - // - // The element will keep its position if possible. Or Move backward to the new-end - // if it's in the 'Y' range. - element.pos = Math.min(element.pos, changeRangeNewEnd); + if (token === SyntaxKind.ColonToken) { + nextToken(); + result.type = parseJSDocType(); + } - // If the 'end' is after the change range, then we always adjust it by the delta - // amount. However, if the end is in the change range, then how we adjust it - // will depend on if delta is positive or negative. If delta is positive then we - // have something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that ended inside the change range to keep its - // end position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that ended in the 'X' range will keep its position. - // However any element htat ended after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that ended in the 'Y' range will - // be adjusted to have their end at the end of the 'Z' range. - if (element.end >= changeRangeOldEnd) { - // Element ends after the change range. Always adjust the end pos. - element.end += delta; - } - else { - // Element ends in the change range. The element will keep its position if - // possible. Or Move backward to the new-end if it's in the 'Y' range. - element.end = Math.min(element.end, changeRangeNewEnd); + return finishNode(result); } - Debug.assert(element.pos <= element.end); - if (element.parent) { - Debug.assert(element.pos >= element.parent.pos); - Debug.assert(element.end <= element.parent.end); + function parseJSDocParameter(): ParameterDeclaration { + let parameter = createNode(SyntaxKind.Parameter); + parameter.type = parseJSDocType(); + return finishNode(parameter); } - } - function checkNodePositions(node: Node, aggressiveChecks: boolean) { - if (aggressiveChecks) { - let pos = node.pos; - forEachChild(node, child => { - Debug.assert(child.pos >= pos); - pos = child.end; - }); - Debug.assert(pos <= node.end); + function parseJSDocOptionalType(type: JSDocType): JSDocOptionalType { + let result = createNode(SyntaxKind.JSDocOptionalType, type.pos); + nextToken(); + result.type = type; + return finishNode(result); } - } - - function updateTokenPositionsAndMarkElements( - sourceFile: IncrementalNode, - changeStart: number, - changeRangeOldEnd: number, - changeRangeNewEnd: number, - delta: number, - oldText: string, - newText: string, - aggressiveChecks: boolean): void { - visitNode(sourceFile); - return; + function parseJSDocTypeReference(): JSDocTypeReference { + let result = createNode(SyntaxKind.JSDocTypeReference); + result.name = parseSimplePropertyName(); - function visitNode(child: IncrementalNode) { - Debug.assert(child.pos <= child.end); - if (child.pos > changeRangeOldEnd) { - // Node is entirely past the change range. We need to move both its pos and - // end, forward or backward appropriately. - moveElementEntirelyPastChangeRange(child, /*isArray:*/ false, delta, oldText, newText, aggressiveChecks); - return; + while (parseOptional(SyntaxKind.DotToken)) { + if (token === SyntaxKind.LessThanToken) { + result.typeArguments = parseTypeArguments(); + break; + } + else { + result.name = parseQualifiedName(result.name); + } } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - let fullEnd = child.end; - if (fullEnd >= changeStart) { - child.intersectsChange = true; - child._children = undefined; + return finishNode(result); + } - // Adjust the pos or end (or both) of the intersecting element accordingly. - adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - forEachChild(child, visitNode, visitArray); + function parseTypeArguments() { + // Move past the < + nextToken(); + let typeArguments = parseDelimitedList(ParsingContext.JSDocTypeArguments, parseJSDocType); + checkForTrailingComma(typeArguments); + checkForEmptyTypeArgumentList(typeArguments); + parseExpected(SyntaxKind.GreaterThanToken); - checkNodePositions(child, aggressiveChecks); - return; + return typeArguments; + } + + function checkForEmptyTypeArgumentList(typeArguments: NodeArray) { + if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) { + let start = typeArguments.pos - "<".length; + let end = skipTrivia(sourceText, typeArguments.end) + ">".length; + return parseErrorAtPosition(start, end - start, Diagnostics.Type_argument_list_cannot_be_empty); } + } - // Otherwise, the node is entirely before the change range. No need to do anything with it. - Debug.assert(fullEnd < changeStart); + function parseQualifiedName(left: EntityName): QualifiedName { + let result = createNode(SyntaxKind.QualifiedName, left.pos); + result.left = left; + result.right = parseIdentifierName(); + + return finishNode(result); } - function visitArray(array: IncrementalNodeArray) { - Debug.assert(array.pos <= array.end); - if (array.pos > changeRangeOldEnd) { - // Array is entirely after the change range. We need to move it, and move any of - // its children. - moveElementEntirelyPastChangeRange(array, /*isArray:*/ true, delta, oldText, newText, aggressiveChecks); - return; - } + function parseJSDocRecordType(): JSDocRecordType { + let result = createNode(SyntaxKind.JSDocRecordType); + nextToken(); + result.members = parseDelimitedList(ParsingContext.JSDocRecordMembers, parseJSDocRecordMember); + checkForTrailingComma(result.members); + parseExpected(SyntaxKind.CloseBraceToken); + return finishNode(result); + } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - let fullEnd = array.end; - if (fullEnd >= changeStart) { - array.intersectsChange = true; - array._children = undefined; + function parseJSDocRecordMember(): JSDocRecordMember { + let result = createNode(SyntaxKind.JSDocRecordMember); + result.name = parseSimplePropertyName(); - // Adjust the pos or end (or both) of the intersecting array accordingly. - adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (let node of array) { - visitNode(node); - } - return; + if (token === SyntaxKind.ColonToken) { + nextToken(); + result.type = parseJSDocType(); } - // Otherwise, the array is entirely before the change range. No need to do anything with it. - Debug.assert(fullEnd < changeStart); + return finishNode(result); } - } - function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange { - // Consider the following code: - // void foo() { /; } - // - // If the text changes with an insertion of / just before the semicolon then we end up with: - // void foo() { //; } - // - // If we were to just use the changeRange a is, then we would not rescan the { token - // (as it does not intersect the actual original change range). Because an edit may - // change the token touching it, we actually need to look back *at least* one token so - // that the prior token sees that change. - let maxLookahead = 1; + function parseJSDocNonNullableType(): JSDocNonNullableType { + let result = createNode(SyntaxKind.JSDocNonNullableType); + nextToken(); + result.type = parseJSDocType(); + return finishNode(result); + } - let start = changeRange.span.start; + function parseJSDocTupleType(): JSDocTupleType { + let result = createNode(SyntaxKind.JSDocTupleType); + nextToken(); + result.types = parseDelimitedList(ParsingContext.JSDocTupleTypes, parseJSDocType); + checkForTrailingComma(result.types); + parseExpected(SyntaxKind.CloseBracketToken); - // the first iteration aligns us with the change start. subsequent iteration move us to - // the left by maxLookahead tokens. We only need to do this as long as we're not at the - // start of the tree. - for (let i = 0; start > 0 && i <= maxLookahead; i++) { - let nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); - Debug.assert(nearestNode.pos <= start); - let position = nearestNode.pos; + return finishNode(result); + } - start = Math.max(0, position - 1); + function checkForTrailingComma(list: NodeArray) { + if (parseDiagnostics.length === 0 && list.hasTrailingComma) { + let start = list.end - ",".length; + parseErrorAtPosition(start, ",".length, Diagnostics.Trailing_comma_not_allowed); + } } - let finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span)); - let finalLength = changeRange.newLength + (changeRange.span.start - start); + function parseJSDocUnionType(): JSDocUnionType { + let result = createNode(SyntaxKind.JSDocUnionType); + nextToken(); + result.types = parseJSDocTypeList(parseJSDocType()); - return createTextChangeRange(finalSpan, finalLength); - } + parseExpected(SyntaxKind.CloseParenToken); - function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { - let bestResult: Node = sourceFile; - let lastNodeEntirelyBeforePosition: Node; + return finishNode(result); + } - forEachChild(sourceFile, visit); + function parseJSDocTypeList(firstType: JSDocType) { + Debug.assert(!!firstType); - if (lastNodeEntirelyBeforePosition) { - let lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); - if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { - bestResult = lastChildOfLastEntireNodeBeforePosition; + let types = >[]; + types.pos = firstType.pos; + + types.push(firstType); + while (parseOptional(SyntaxKind.BarToken)) { + types.push(parseJSDocType()); } + + types.end = scanner.getStartPos(); + return types; } - return bestResult; + function parseJSDocAllType(): JSDocAllType { + let result = createNode(SyntaxKind.JSDocAllType); + nextToken(); + return finishNode(result); + } - function getLastChild(node: Node): Node { - while (true) { - let lastChild = getLastChildWorker(node); - if (lastChild) { - node = lastChild; - } - else { - return node; - } + function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { + let 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) { + + let result = createNode(SyntaxKind.JSDocUnknownType, pos); + return finishNode(result); + } + else { + let result = createNode(SyntaxKind.JSDocNullableType, pos); + result.type = parseJSDocType(); + return finishNode(result); } } - function getLastChildWorker(node: Node): Node { - let last: Node = undefined; - forEachChild(node, child => { - if (nodeIsPresent(child)) { - last = child; - } - }); - return last; + export function parseJSDocCommentForTests(content: string, start: number, length: number) { + initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined); + let jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); + let diagnostics = parseDiagnostics; + clearState(); + + return jsDocComment ? { jsDocComment, diagnostics } : undefined; } - function visit(child: Node) { - if (nodeIsMissing(child)) { - // Missing nodes are effectively invisible to us. We never even consider them - // When trying to find the nearest node before us. - return; - } + export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment { + let content = sourceText; + start = start || 0; + let end = length === undefined ? content.length : start + length; + length = end - start; - // If the child intersects this position, then this node is currently the nearest - // node that starts before the position. - if (child.pos <= position) { - if (child.pos >= bestResult.pos) { - // This node starts before the position, and is closer to the position than - // the previous best node we found. It is now the new best node. - bestResult = child; - } + Debug.assert(start >= 0); + Debug.assert(start <= end); + Debug.assert(end <= content.length); - // Now, the node may overlap the position, or it may end entirely before the - // position. If it overlaps with the position, then either it, or one of its - // children must be the nearest node before the position. So we can just - // recurse into this child to see if we can find something better. - if (position < child.end) { - // The nearest node is either this child, or one of the children inside - // of it. We've already marked this child as the best so far. Recurse - // in case one of the children is better. - forEachChild(child, visit); + let type: JSDocType; + let parameters: JSDocParameter[]; + let returnType: JSDocType; + let typeParameters: TypeParameterDeclaration[]; + // let tagCounts: Map; + + let pos: number; + + if (length >= "/** */".length) { + if (content.charCodeAt(start) === CharacterCodes.slash && + content.charCodeAt(start + 1) === CharacterCodes.asterisk && + content.charCodeAt(start + 2) === CharacterCodes.asterisk && + content.charCodeAt(start + 3) !== CharacterCodes.asterisk) { + + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + let canParseTag = true; + let seenAsterisk = true; + + for (pos = start + 3; pos < end;) { + let ch = content.charCodeAt(pos); + pos++; + + if (ch === CharacterCodes.at && canParseTag) { + parseTag(); + + // Once we parse out a tag, we cannot keep parsing out tags on this line. + canParseTag = false; + continue; + } - // Once we look at the children of this node, then there's no need to - // continue any further. - return true; - } - else { - Debug.assert(child.end <= position); - // The child ends entirely before this position. Say you have the following - // (where $ is the position) - // - // ? $ : <...> <...> - // - // We would want to find the nearest preceding node in "complex expr 2". - // To support that, we keep track of this node, and once we're done searching - // for a best node, we recurse down this node to see if we can find a good - // result in it. - // - // This approach allows us to quickly skip over nodes that are entirely - // before the position, while still allowing us to find any nodes in the - // last one that might be what we want. - lastNodeEntirelyBeforePosition = child; - } - } - else { - Debug.assert(child.pos > position); - // We're now at a node that is entirely past the position we're searching for. - // This node (and all following nodes) could never contribute to the result, - // so just skip them by returning 'true' here. - return true; - } - } - } + if (isLineBreak(ch)) { + // After a line break, we can parse a tag, and we haven't seen as asterisk + // on the next line yet. + canParseTag = true; + seenAsterisk = false; + continue; + } - function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { - let oldText = sourceFile.text; - if (textChangeRange) { - Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); + if (isWhiteSpace(ch)) { + // Whitespace doesn't affect any of our parsing. + continue; + } - if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) { - let oldTextPrefix = oldText.substr(0, textChangeRange.span.start); - let newTextPrefix = newText.substr(0, textChangeRange.span.start); - Debug.assert(oldTextPrefix === newTextPrefix); + // Ignore the first asterisk on a line. + if (ch === CharacterCodes.asterisk) { + if (seenAsterisk) { + // If we've already seen an asterisk, then we can no longer parse a tag + // on this line. + canParseTag = false; + } + seenAsterisk = true; + continue; + } - let oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length); - let newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length); - Debug.assert(oldTextSuffix === newTextSuffix); + // Anything else is doc comment text. We can't do anything with it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. + canParseTag = false; + } + } } - } - } - - interface IncrementalElement extends TextRange { - parent?: Node; - intersectsChange: boolean - length?: number; - _children: Node[]; - } - export interface IncrementalNode extends Node, IncrementalElement { - hasBeenIncrementallyParsed: boolean - } - - interface IncrementalNodeArray extends NodeArray, IncrementalElement { - length: number - } + return createJSDocComment(); - // Allows finding nodes in the source file at a certain position in an efficient manner. - // The implementation takes advantage of the calling pattern it knows the parser will - // make in order to optimize finding nodes as quickly as possible. - export interface SyntaxCursor { - currentNode(position: number): IncrementalNode; - } + function createJSDocComment(): JSDocComment { + if (!returnType && !type && !parameters && !typeParameters/* && !tagCounts*/) { + return undefined; + } - function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor { - let currentArray: NodeArray = sourceFile.statements; - let currentArrayIndex = 0; + return { returnType, type, parameters, typeParameters/*, tagCounts */ }; + } - Debug.assert(currentArrayIndex < currentArray.length); - let current = currentArray[currentArrayIndex]; - let lastQueriedPosition = InvalidPosition.Value; + function skipWhitespace(): void { + while (pos < end && isWhiteSpace(content.charCodeAt(pos))) { + pos++; + } + } - return { - currentNode(position: number) { - // Only compute the current node if the position is different than the last time - // we were asked. The parser commonly asks for the node at the same position - // twice. Once to know if can read an appropriate list element at a certain point, - // and then to actually read and consume the node. - if (position !== lastQueriedPosition) { - // Much of the time the parser will need the very next node in the array that - // we just returned a node from.So just simply check for that case and move - // forward in the array instead of searching for the node again. - if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { - currentArrayIndex++; - current = currentArray[currentArrayIndex]; + function parseTag(): void { + Debug.assert(content.charCodeAt(pos - 1) === CharacterCodes.at); + + let startPos = pos; + let tagName = scanIdentifier(); + if (tagName) { + switch (tagName) { + case "param": + return handleParamTag(); + case "return": + case "returns": + return handleReturnTag(tagName, startPos); + case "template": + return handleTemplateTag(tagName, startPos); + case "type": + return handleTypeTag(tagName, startPos); } + } + } - // If we don't have a node, or the node we have isn't in the right position, - // then try to find a viable node at the position requested. - if (!current || current.pos !== position) { - findHighestListElementThatStartsAtPosition(position); - } + function parseType(): JSDocType { + skipWhitespace(); + + if (content.charCodeAt(pos) !== CharacterCodes.openBrace) { + return undefined; } - // Cache this query so that we don't do any extra work if the parser calls back - // into us. Note: this is very common as the parser will make pairs of calls like - // 'isListElement -> parseListElement'. If we were unable to find a node when - // called with 'isListElement', we don't want to redo the work when parseListElement - // is called immediately after. - lastQueriedPosition = position; + let typeExpression = parseJSDocTypeExpression(pos, end - pos); + if (!typeExpression) { + return undefined; + } - // Either we don'd have a node, or we have a node at the position being asked for. - Debug.assert(!current || current.pos === position); - return current; + typeExpression.parent = parent; + pos = typeExpression.end; + return typeExpression.type; } - }; - // Finds the highest element in the tree we can find that starts at the provided position. - // The element must be a direct child of some node list in the tree. This way after we - // return it, we can easily return its next sibling in the list. - function findHighestListElementThatStartsAtPosition(position: number) { - // Clear out any cached state about the last node we found. - currentArray = undefined; - currentArrayIndex = InvalidPosition.Value; - current = undefined; + function handleParamTag() { + skipWhitespace(); - // Recurse into the source file to find the highest node at this position. - forEachChild(sourceFile, visitNode, visitArray); - return; + let type: JSDocType; + if (content.charCodeAt(pos) === CharacterCodes.openBrace) { + type = parseType(); + if (!type) { + return; + } + } - function visitNode(node: Node) { - if (position >= node.pos && position < node.end) { - // Position was within this node. Keep searching deeper to find the node. - forEachChild(node, visitNode, visitArray); + skipWhitespace(); + let name: string; + let isBracketed: boolean; + if (content.charCodeAt(pos) === CharacterCodes.openBracket) { + pos++; + skipWhitespace(); + name = scanIdentifier(); + isBracketed = true; + } + else { + name = scanIdentifier(); + } - // don't procede any futher in the search. - return true; + if (!name) { + return; } - // position wasn't in this node, have to keep searching. - return false; + if (!type) { + type = parseType(); + if (!type) { + return; + } + } + + parameters = parameters || []; + parameters.push({ name, type, isBracketed }); } - function visitArray(array: NodeArray) { - if (position >= array.pos && position < array.end) { - // position was in this array. Search through this array to see if we find a - // viable element. - for (let i = 0, n = array.length; i < n; i++) { - let child = array[i]; - if (child) { - if (child.pos === position) { - // Found the right node. We're done. - currentArray = array; - currentArrayIndex = i; - current = child; - return true; - } - else { - if (child.pos < position && position < child.end) { - // Position in somewhere within this child. Search in it and - // stop searching in this array. - forEachChild(child, visitNode, visitArray); - return true; - } - } - } - } + function handleReturnTag(tag: string, startPos: number): void { + if (returnType) { + parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); + return; } - // position wasn't in this array, have to keep searching. - return false; + returnType = parseType(); } - } - } - const enum InvalidPosition { - Value = -1 - } - } + function handleTypeTag(tag: string, startPos: number): void { + if (type) { + parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); + return; + } - module JSDocParser { - // Parses out a JSDoc type expression. The starting position should be right at the open - // curly in the type expression. Returns 'undefined' if it encounters any errors while parsing. - /* @internal */ - export function parseJSDocTypeExpression(content: string, start: number, length: number): JSDocTypeExpression { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true, content, /*onError:*/ undefined, start, length); - - // Prime the first token for us to start processing. - let token = nextToken(); - let error = false; + type = parseType(); + } - let result = createNode(SyntaxKind.JSDocTypeExpression); + function handleTemplateTag(tag: string, startPos: number): void { + if (typeParameters) { + parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); + return; + } - parseExpected(SyntaxKind.OpenBraceToken); - if (error) { - return undefined; - } + typeParameters = []; - result.type = parseJSDocTopLevelType(); - parseExpected(SyntaxKind.CloseBraceToken); + while (true) { + skipWhitespace(); - if (error) { - return undefined; - } + let startPos = pos; + let name = scanIdentifier(); + if (!name) { + parseErrorAtPosition(startPos, 0, Diagnostics.Identifier_expected); + return; + } - Parser.fixupParentReferences(result); - return finishNode(result); + let identifier = createNode(SyntaxKind.Identifier); + let typeParameter = createNode(SyntaxKind.TypeParameter); - function setError(message?: string) { - error = true; - if (throwOnJSDocErrors) { - throw new Error(message); - } - } + identifier.text = name; + typeParameter.name = identifier; - function nextToken(): SyntaxKind { - return token = scanner.scan(); - } + identifier.pos = typeParameter.pos = startPos; + identifier.end = typeParameter.end = pos; - function createNode(kind: SyntaxKind, pos?: number): Node { - return Parser.createNodeAtPosition(scanner, kind, pos); - } + Parser.fixupParentReferences(typeParameter); + typeParameter.parent = parent; + typeParameters.push(typeParameter); - function parseExpected(kind: SyntaxKind): void { - if (token === kind) { - nextToken(); - } - else { - setError("Expected " + (ts).SyntaxKind[kind] + ", actual: " + (ts).SyntaxKind[token]) - } - } + skipWhitespace(); + if (content.charCodeAt(pos) !== CharacterCodes.comma) { + return; + } - function isIdentifierOrKeyword() { - if (token === SyntaxKind.Identifier) { - return true; + pos++; + } } - return token >= SyntaxKind.FirstKeyword && token <= SyntaxKind.LastKeyword; - } - - function parseJSDocTopLevelType(): JSDocType { - var type = parseJSDocType(); - if (!error && token === SyntaxKind.BarToken) { - var unionType = createNode(SyntaxKind.JSDocUnionType, type.pos); - unionType.types = parseJSDocTypeList(type); - type = finishNode(unionType); - } - - if (!error && token === SyntaxKind.EqualsToken) { - var optionalType = createNode(SyntaxKind.JSDocOptionalType, type.pos); - nextToken(); - optionalType.type = type; - type = finishNode(optionalType); - } - - return type; - } - - function parseJSDocType(): JSDocType { - if (!error) { - let type = parseBasicTypeExpression(); - - while (!error && type) { - if (token === SyntaxKind.OpenBracketToken) { - let arrayType = createNode(SyntaxKind.JSDocArrayType, type.pos); - arrayType.elementType = type; - - nextToken(); - parseExpected(SyntaxKind.CloseBracketToken); - - type = finishNode(arrayType); + function scanIdentifier(): string { + let startPos = pos; + for (; pos < end; pos++) { + let ch = content.charCodeAt(pos); + if (pos === startPos && isIdentifierStart(ch, ScriptTarget.Latest)) { + continue; } - else if (token === SyntaxKind.QuestionToken) { - let nullableType = createNode(SyntaxKind.JSDocNullableType, type.pos); - nullableType.type = type; - - nextToken(); - type = finishNode(nullableType); + else if (pos > startPos && isIdentifierPart(ch, ScriptTarget.Latest)) { + continue; } - else if (token === SyntaxKind.ExclamationToken) { - let nonNullableType = createNode(SyntaxKind.JSDocNonNullableType, type.pos); - nonNullableType.type = type; - nextToken(); - type = finishNode(nonNullableType); - } - else { - break; - } + 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: - return parseJSDocFunctionType(); - case SyntaxKind.DotDotDotToken: - return parseJSDocVariadicType(); - case SyntaxKind.NewKeyword: - return parseJSDocConstructorType(); - case SyntaxKind.ThisKeyword: - return parseJSDocThisType(); - } + if (startPos === pos) { + return undefined; + } - if (isIdentifierOrKeyword()) { - return parseJSDocTypeReference(); + return content.substring(startPos, pos); } - - setError(); - return undefined; } + } + } - function parseJSDocThisType(): JSDocThisType { - let result = createNode(SyntaxKind.JSDocThisType); - nextToken(); - parseExpected(SyntaxKind.ColonToken); - result.type = parseJSDocType(); - return finishNode(result); - } + module IncrementalParser { + export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { + aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive); - function parseJSDocConstructorType(): JSDocConstructorType { - let result = createNode(SyntaxKind.JSDocConstructorType); - nextToken(); - parseExpected(SyntaxKind.ColonToken); - result.type = parseJSDocType(); - return finishNode(result); + checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); + if (textChangeRangeIsUnchanged(textChangeRange)) { + // if the text didn't change, then we can just return our current source file as-is. + return sourceFile; } - function parseJSDocVariadicType(): JSDocVariadicType { - let result = createNode(SyntaxKind.JSDocVariadicType); - nextToken(); - result.type = parseJSDocType(); - return finishNode(result); + if (sourceFile.statements.length === 0) { + // If we don't have any statements in the current source file, then there's no real + // way to incrementally parse. So just do a full parse instead. + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setNodeParents*/ true) } - function parseJSDocFunctionType(): JSDocFunctionType { - let result = createNode(SyntaxKind.JSDocFunctionType); - nextToken(); - parseExpected(SyntaxKind.OpenParenToken); - - let parameters = >[]; - parameters.pos = scanner.getStartPos(); + // Make sure we're not trying to incrementally update a source file more than once. Once + // we do an update the original source file is considered unusbale from that point onwards. + // + // This is because we do incremental parsing in-place. i.e. we take nodes from the old + // tree and give them new positions and parents. From that point on, trusting the old + // tree at all is not possible as far too much of it may violate invariants. + let incrementalSourceFile = sourceFile; + Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); + incrementalSourceFile.hasBeenIncrementallyParsed = true; - while (!error && token !== SyntaxKind.CloseParenToken) { - if (parameters.length > 0) { - parseExpected(SyntaxKind.CommaToken); - } + let oldText = sourceFile.text; + let syntaxCursor = createSyntaxCursor(sourceFile); - let parameterType = parseJSDocType(); - if (!parameterType) { - return undefined; - } + // Make the actual change larger so that we know to reparse anything whose lookahead + // might have intersected the change. + let changeRange = extendToAffectedRange(sourceFile, textChangeRange); + checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); - let parameter = createNode(SyntaxKind.Parameter, parameterType.pos); - parameter.type = parameterType; - finishNode(parameter); + // Ensure that extending the affected range only moved the start of the change range + // earlier in the file. + Debug.assert(changeRange.span.start <= textChangeRange.span.start); + Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span)); + Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange))); - parameters.push(parameter); - } + // The is the amount the nodes after the edit range need to be adjusted. It can be + // positive (if the edit added characters), negative (if the edit deleted characters) + // or zero (if this was a pure overwrite with nothing added/removed). + let delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length; - parameters.end = scanner.getStartPos(); + // If we added or removed characters during the edit, then we need to go and adjust all + // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they + // may move backward (if we deleted chars). + // + // Doing this helps us out in two ways. First, it means that any nodes/tokens we want + // to reuse are already at the appropriate position in the new text. That way when we + // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes + // it very easy to determine if we can reuse a node. If the node's position is at where + // we are in the text, then we can reuse it. Otherwise we can't. If the node's position + // is ahead of us, then we'll need to rescan tokens. If the node's position is behind + // us, then we'll need to skip it or crumble it as appropriate + // + // We will also adjust the positions of nodes that intersect the change range as well. + // By doing this, we ensure that all the positions in the old tree are consistent, not + // just the positions of nodes entirely before/after the change range. By being + // consistent, we can then easily map from positions to nodes in the old tree easily. + // + // Also, mark any syntax elements that intersect the changed span. We know, up front, + // that we cannot reuse these elements. + updateTokenPositionsAndMarkElements(incrementalSourceFile, + changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - result.parameters = parameters; - parseExpected(SyntaxKind.CloseParenToken); + // Now that we've set up our internal incremental state just proceed and parse the + // source file in the normal fashion. When possible the parser will retrieve and + // reuse nodes from the old tree. + // + // Note: passing in 'true' for setNodeParents is very important. When incrementally + // parsing, we will be reusing nodes from the old tree, and placing it into new + // parents. If we don't set the parents now, we'll end up with an observably + // inconsistent tree. Setting the parents on the new tree should be very fast. We + // will immediately bail out of walking any subtrees when we can see that their parents + // are already correct. + let result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true) - if (token === SyntaxKind.ColonToken) { - nextToken(); - result.type = parseJSDocType(); - } + return result; + } - return finishNode(result); + function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) { + if (isArray) { + visitArray(element); } - - function parseJSDocOptionalType(type: JSDocType): JSDocOptionalType { - let result = createNode(SyntaxKind.JSDocOptionalType, type.pos); - nextToken(); - result.type = type; - return finishNode(result); + else { + visitNode(element); } + return; - function parseJSDocTypeReference(): JSDocTypeReference { - let result = createNode(SyntaxKind.JSDocTypeReference); - result.name = parseIdentifierOrKeyword(); - - while (!error && token === SyntaxKind.DotToken) { - nextToken(); - - if (isIdentifierOrKeyword()) { - result.name = parseQualifiedName(result.name); - } - else if (token === SyntaxKind.LessThanToken) { - result.typeArguments = parseTypeArguments(); - break; - } - else { - setError(); - return undefined; - } + function visitNode(node: IncrementalNode) { + if (aggressiveChecks && shouldCheckNode(node)) { + var text = oldText.substring(node.pos, node.end); } - return finishNode(result); - } - - function parseTypeArguments() { - // Move past the < - nextToken(); - - let typeArguments = >[]; - typeArguments.pos = scanner.getStartPos(); + // Ditch any existing LS children we may have created. This way we can avoid + // moving them forward. + node._children = undefined; + node.jsDocComment = undefined; + node.pos += delta; + node.end += delta; - typeArguments.push(parseJSDocType()); - while (!error && token === SyntaxKind.CommaToken) { - nextToken(); - typeArguments.push(parseJSDocType()); + if (aggressiveChecks && shouldCheckNode(node)) { + Debug.assert(text === newText.substring(node.pos, node.end)); } - typeArguments.end = scanner.getStartPos(); - - parseExpected(SyntaxKind.GreaterThanToken); - - return typeArguments; + forEachChild(node, visitNode, visitArray); + checkNodePositions(node, aggressiveChecks); } - function parseQualifiedName(left: EntityName): QualifiedName { - let result = createNode(SyntaxKind.QualifiedName, left.pos); - result.left = left; - result.right = parseIdentifierOrKeyword(); - - return finishNode(result); - } + function visitArray(array: IncrementalNodeArray) { + array._children = undefined; + array.pos += delta; + array.end += delta; - function parseIdentifierOrKeyword(): Identifier { - return parseIdentifierHelper(isIdentifierOrKeyword()); + for (let node of array) { + visitNode(node); + } } + } - function parseIdentifierHelper(isIdentifier: boolean): Identifier { - if (isIdentifier) { - let result = createNode(SyntaxKind.Identifier); - result.text = scanner.getTokenValue(); - nextToken(); - return finishNode(result); - } - else { - setError(); - return undefined; - } + function shouldCheckNode(node: Node) { + switch (node.kind) { + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.Identifier: + return true; } - function parseJSDocRecordType(): JSDocRecordType { - let result = createNode(SyntaxKind.JSDocRecordType); - nextToken(); + return false; + } - let members = >[]; - members.pos = scanner.getStartPos(); + function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { + Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); + Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); + Debug.assert(element.pos <= element.end); - while (!error && token !== SyntaxKind.CloseBraceToken) { - if (members.length > 0) { - parseExpected(SyntaxKind.CommaToken); - } + // We have an element that intersects the change range in some way. It may have its + // start, or its end (or both) in the changed range. We want to adjust any part + // that intersects such that the final tree is in a consistent state. i.e. all + // chlidren have spans within the span of their parent, and all siblings are ordered + // properly. - members.push(parseJSDocMember()); - } + // We may need to update both the 'pos' and the 'end' of the element. - members.end = scanner.getStartPos(); - result.members = members; + // If the 'pos' is before the start of the change, then we don't need to touch it. + // If it isn't, then the 'pos' must be inside the change. How we update it will + // depend if delta is positive or negative. If delta is positive then we have + // something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that started in the change range to still be + // starting at the same position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that started in the 'X' range will keep its position. + // However any element htat started after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that started in the 'Y' range will + // be adjusted to have their start at the end of the 'Z' range. + // + // The element will keep its position if possible. Or Move backward to the new-end + // if it's in the 'Y' range. + element.pos = Math.min(element.pos, changeRangeNewEnd); - parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(result); + // If the 'end' is after the change range, then we always adjust it by the delta + // amount. However, if the end is in the change range, then how we adjust it + // will depend on if delta is positive or negative. If delta is positive then we + // have something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that ended inside the change range to keep its + // end position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that ended in the 'X' range will keep its position. + // However any element htat ended after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that ended in the 'Y' range will + // be adjusted to have their end at the end of the 'Z' range. + if (element.end >= changeRangeOldEnd) { + // Element ends after the change range. Always adjust the end pos. + element.end += delta; } - - function parseJSDocMember(): JSDocMember { - let result = createNode(SyntaxKind.JSDocMember); - result.name = parsePropertyName(); - - if (token === SyntaxKind.ColonToken) { - nextToken(); - result.type = parseJSDocType(); - } - - return finishNode(result); + else { + // Element ends in the change range. The element will keep its position if + // possible. Or Move backward to the new-end if it's in the 'Y' range. + element.end = Math.min(element.end, changeRangeNewEnd); } - function parsePropertyName(): Identifier | LiteralExpression { - if (isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { - let result = createNode(token); - result.text = scanner.getTokenValue(); - nextToken(); - return finishNode(result); - } - else { - setError(); - return undefined; - } + Debug.assert(element.pos <= element.end); + if (element.parent) { + Debug.assert(element.pos >= element.parent.pos); + Debug.assert(element.end <= element.parent.end); } + } - function parseJSDocNonNullableType(): JSDocNonNullableType { - let result = createNode(SyntaxKind.JSDocNonNullableType); - nextToken(); - result.type = parseJSDocType(); - return finishNode(result); + function checkNodePositions(node: Node, aggressiveChecks: boolean) { + if (aggressiveChecks) { + let pos = node.pos; + forEachChild(node, child => { + Debug.assert(child.pos >= pos); + pos = child.end; + }); + Debug.assert(pos <= node.end); } + } - function parseJSDocTupleType(): JSDocTupleType { - let result = createNode(SyntaxKind.JSDocTupleType); - nextToken(); - - let types = >[]; - types.pos = scanner.getStartPos(); - - while (!error) { - if (token === SyntaxKind.CloseBracketToken) { - break; - } + function updateTokenPositionsAndMarkElements( + sourceFile: IncrementalNode, + changeStart: number, + changeRangeOldEnd: number, + changeRangeNewEnd: number, + delta: number, + oldText: string, + newText: string, + aggressiveChecks: boolean): void { - if (types.length) { - parseExpected(SyntaxKind.CommaToken); - } + visitNode(sourceFile); + return; - types.push(parseJSDocType()); + function visitNode(child: IncrementalNode) { + Debug.assert(child.pos <= child.end); + if (child.pos > changeRangeOldEnd) { + // Node is entirely past the change range. We need to move both its pos and + // end, forward or backward appropriately. + moveElementEntirelyPastChangeRange(child, /*isArray:*/ false, delta, oldText, newText, aggressiveChecks); + return; } - types.end = scanner.getStartPos(); - - result.types = types; - parseExpected(SyntaxKind.CloseBracketToken); - - return finishNode(result); - } - - function parseJSDocUnionType(): JSDocUnionType { - let result = createNode(SyntaxKind.JSDocUnionType); - nextToken(); - - result.types = parseJSDocTypeList(parseJSDocType()); - - parseExpected(SyntaxKind.CloseParenToken); - - return finishNode(result); - } - - function parseJSDocTypeList(firstType: JSDocType) { - if (!firstType) { - return undefined; - } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + let fullEnd = child.end; + if (fullEnd >= changeStart) { + child.intersectsChange = true; + child._children = undefined; - let types = >[]; - types.pos = firstType.pos; + // Adjust the pos or end (or both) of the intersecting element accordingly. + adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + forEachChild(child, visitNode, visitArray); - types.push(firstType); - while (!error && token === SyntaxKind.BarToken) { - nextToken(); - types.push(parseJSDocType()); + checkNodePositions(child, aggressiveChecks); + return; } - types.end = scanner.getStartPos(); - return types; - } - - function parseJSDocAllType(): JSDocAllType { - let result = createNode(SyntaxKind.JSDocAllType); - nextToken(); - return finishNode(result); + // Otherwise, the node is entirely before the change range. No need to do anything with it. + Debug.assert(fullEnd < changeStart); } - function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { - let 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) { - - let result = createNode(SyntaxKind.JSDocUnknownType, pos); - return finishNode(result); - } - else { - let result = createNode(SyntaxKind.JSDocNullableType, pos); - result.type = parseJSDocType(); - return finishNode(result); + function visitArray(array: IncrementalNodeArray) { + Debug.assert(array.pos <= array.end); + if (array.pos > changeRangeOldEnd) { + // Array is entirely after the change range. We need to move it, and move any of + // its children. + moveElementEntirelyPastChangeRange(array, /*isArray:*/ true, delta, oldText, newText, aggressiveChecks); + return; } - } - function finishNode(node: T): T { - node.end = scanner.getStartPos(); - return node; - } - } - - export function parseJSDocComment(parent: Node, content: string, start: number, length: number): JSDocComment { - start = start || 0; - let end = length === undefined ? content.length : start + length; - length = end - start; - - Debug.assert(start >= 0); - Debug.assert(start <= end); - Debug.assert(end <= content.length); - - let error = false; - let type: JSDocType; - let parameters: JSDocParameter[]; - let returnType: JSDocType; - let typeParameters: TypeParameterDeclaration[]; - // let tagCounts: Map; - - let pos: number; - - if (length >= "/** */".length) { - if (content.charCodeAt(start) === CharacterCodes.slash && - content.charCodeAt(start + 1) === CharacterCodes.asterisk && - content.charCodeAt(start + 2) === CharacterCodes.asterisk && - content.charCodeAt(start + 3) !== CharacterCodes.asterisk) { - - // Initially we can parse out a tag. We also have seen a starting asterisk. - // This is so that /** * @type */ doesn't parse. - let canParseTag = true; - let seenAsterisk = true; - - for (pos = start + 3; !error && pos < end;) { - let ch = content.charCodeAt(pos); - - if (ch === CharacterCodes.at && canParseTag) { - // Don't update 'pos' in this block. that will be handled inside the - // parseTag function. - - parseTag(); - - // Once we parse out a tag, we cannot keep parsing out tags on this line. - canParseTag = false; - continue; - } - - pos++; - if (isLineBreak(ch)) { - // After a line break, we can parse a tag, and we haven't seen as asterisk - // on the next line yet. - canParseTag = true; - seenAsterisk = false; - continue; - } - - if (isWhiteSpace(ch)) { - // Whitespace doesn't affect any of our parsing. - continue; - } - - // Ignore the first asterisk on a line. - if (ch === CharacterCodes.asterisk) { - if (seenAsterisk) { - // If we've already seen an asterisk, then we can no longer parse a tag - // on this line. - canParseTag = false; - } - seenAsterisk = true; - continue; - } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + let fullEnd = array.end; + if (fullEnd >= changeStart) { + array.intersectsChange = true; + array._children = undefined; - // Anything else is doc comment text. We can't do anything with it. Because it - // wasn't a tag, we can no longer parse a tag on this line until we hit the next - // line break. - canParseTag = false; + // Adjust the pos or end (or both) of the intersecting array accordingly. + adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + for (let node of array) { + visitNode(node); } + return; } + + // Otherwise, the array is entirely before the change range. No need to do anything with it. + Debug.assert(fullEnd < changeStart); } + } - return error ? undefined : createJSDocComment(); + function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange { + // Consider the following code: + // void foo() { /; } + // + // If the text changes with an insertion of / just before the semicolon then we end up with: + // void foo() { //; } + // + // If we were to just use the changeRange a is, then we would not rescan the { token + // (as it does not intersect the actual original change range). Because an edit may + // change the token touching it, we actually need to look back *at least* one token so + // that the prior token sees that change. + let maxLookahead = 1; - function setError() { - error = true; - //if (throwOnJSDocErrors) { - // throw new Error(); - //} - } + let start = changeRange.span.start; - function createJSDocComment(): JSDocComment { - if (!returnType && !type && !parameters && !typeParameters/* && !tagCounts*/) { - return undefined; - } + // the first iteration aligns us with the change start. subsequent iteration move us to + // the left by maxLookahead tokens. We only need to do this as long as we're not at the + // start of the tree. + for (let i = 0; start > 0 && i <= maxLookahead; i++) { + let nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); + Debug.assert(nearestNode.pos <= start); + let position = nearestNode.pos; - return { returnType, type, parameters, typeParameters/*, tagCounts */ }; + start = Math.max(0, position - 1); } - function skipWhitespace(): void { - while (pos < end && isWhiteSpace(content.charCodeAt(pos))) { - pos++; - } - } + let finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span)); + let finalLength = changeRange.newLength + (changeRange.span.start - start); - function parseTag(): void { - Debug.assert(content.charCodeAt(pos) === CharacterCodes.at); - - // Skip the @ sign. - pos++; - - let tagName = scanIdentifier(); - //tagCounts = tagCounts || {}; - //if (!hasProperty(tagCounts, tagName)) { - // tagCounts[tagName] = 0; - //} - //tagCounts[tagName]++; - - switch (tagName) { - case "param": - return handleParamTag(); - case "return": - case "returns": - return handleReturnTag(); - case "template": - return handleTemplateTag(); - case "type": - return handleTypeTag(); - } - } + return createTextChangeRange(finalSpan, finalLength); + } - function parseType(): JSDocType { - skipWhitespace(); + function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { + let bestResult: Node = sourceFile; + let lastNodeEntirelyBeforePosition: Node; - if (content.charCodeAt(pos) !== CharacterCodes.openBrace) { - return undefined; - } + forEachChild(sourceFile, visit); - let typeExpression = parseJSDocTypeExpression(content, pos, end - pos); - if (!typeExpression) { - setError(); - return undefined; + if (lastNodeEntirelyBeforePosition) { + let lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); + if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { + bestResult = lastChildOfLastEntireNodeBeforePosition; } - - typeExpression.parent = parent; - pos = typeExpression.end; - return typeExpression.type; } - function handleParamTag() { - skipWhitespace(); + return bestResult; - let type: JSDocType; - if (content.charCodeAt(pos) === CharacterCodes.openBrace) { - type = parseType(); - if (!type) { - return; + function getLastChild(node: Node): Node { + while (true) { + let lastChild = getLastChildWorker(node); + if (lastChild) { + node = lastChild; + } + else { + return node; } } + } - skipWhitespace(); - let name: string; - let isBracketed: boolean; - if (content.charCodeAt(pos) === CharacterCodes.openBracket) { - pos++; - name = scanIdentifier(); - isBracketed = true; - } - else { - name = scanIdentifier(); + function getLastChildWorker(node: Node): Node { + let last: Node = undefined; + forEachChild(node, child => { + if (nodeIsPresent(child)) { + last = child; + } + }); + return last; + } + + function visit(child: Node) { + if (nodeIsMissing(child)) { + // Missing nodes are effectively invisible to us. We never even consider them + // When trying to find the nearest node before us. + return; } - if (!type) { - type = parseType(); - if (!type) { - return; + // If the child intersects this position, then this node is currently the nearest + // node that starts before the position. + if (child.pos <= position) { + if (child.pos >= bestResult.pos) { + // This node starts before the position, and is closer to the position than + // the previous best node we found. It is now the new best node. + bestResult = child; } - } - parameters = parameters || []; - parameters.push({ name, type, isBracketed }); - } + // Now, the node may overlap the position, or it may end entirely before the + // position. If it overlaps with the position, then either it, or one of its + // children must be the nearest node before the position. So we can just + // recurse into this child to see if we can find something better. + if (position < child.end) { + // The nearest node is either this child, or one of the children inside + // of it. We've already marked this child as the best so far. Recurse + // in case one of the children is better. + forEachChild(child, visit); - function handleReturnTag(): void { - if (!returnType) { - returnType = parseType(); - if (returnType) { - return; + // Once we look at the children of this node, then there's no need to + // continue any further. + return true; + } + else { + Debug.assert(child.end <= position); + // The child ends entirely before this position. Say you have the following + // (where $ is the position) + // + // ? $ : <...> <...> + // + // We would want to find the nearest preceding node in "complex expr 2". + // To support that, we keep track of this node, and once we're done searching + // for a best node, we recurse down this node to see if we can find a good + // result in it. + // + // This approach allows us to quickly skip over nodes that are entirely + // before the position, while still allowing us to find any nodes in the + // last one that might be what we want. + lastNodeEntirelyBeforePosition = child; } } - - setError(); + else { + Debug.assert(child.pos > position); + // We're now at a node that is entirely past the position we're searching for. + // This node (and all following nodes) could never contribute to the result, + // so just skip them by returning 'true' here. + return true; + } } + } - function handleTypeTag(): void { - if (!type) { - type = parseType(); - if (type) { - return; - } - } + function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { + let oldText = sourceFile.text; + if (textChangeRange) { + Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - setError(); - } + if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) { + let oldTextPrefix = oldText.substr(0, textChangeRange.span.start); + let newTextPrefix = newText.substr(0, textChangeRange.span.start); + Debug.assert(oldTextPrefix === newTextPrefix); - function handleTemplateTag(): void { - if (!typeParameters) { - typeParameters = []; + let oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length); + let newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length); + Debug.assert(oldTextSuffix === newTextSuffix); + } + } + } - while (!error) { - skipWhitespace(); + interface IncrementalElement extends TextRange { + parent?: Node; + intersectsChange: boolean + length?: number; + _children: Node[]; + } - let startPos = pos; - let name = scanIdentifier(); + export interface IncrementalNode extends Node, IncrementalElement { + hasBeenIncrementallyParsed: boolean + } - let identifier = createNode(SyntaxKind.Identifier); - let typeParameter = createNode(SyntaxKind.TypeParameter); + interface IncrementalNodeArray extends NodeArray, IncrementalElement { + length: number + } - identifier.text = name; - typeParameter.name = identifier; + // Allows finding nodes in the source file at a certain position in an efficient manner. + // The implementation takes advantage of the calling pattern it knows the parser will + // make in order to optimize finding nodes as quickly as possible. + export interface SyntaxCursor { + currentNode(position: number): IncrementalNode; + } - identifier.pos = typeParameter.pos = startPos; - identifier.end = typeParameter.end = pos; + function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor { + let currentArray: NodeArray = sourceFile.statements; + let currentArrayIndex = 0; - Parser.fixupParentReferences(typeParameter); - typeParameter.parent = parent; - typeParameters.push(typeParameter); + Debug.assert(currentArrayIndex < currentArray.length); + let current = currentArray[currentArrayIndex]; + let lastQueriedPosition = InvalidPosition.Value; - skipWhitespace(); - if (content.charCodeAt(pos) !== CharacterCodes.comma) { - return; + return { + currentNode(position: number) { + // Only compute the current node if the position is different than the last time + // we were asked. The parser commonly asks for the node at the same position + // twice. Once to know if can read an appropriate list element at a certain point, + // and then to actually read and consume the node. + if (position !== lastQueriedPosition) { + // Much of the time the parser will need the very next node in the array that + // we just returned a node from.So just simply check for that case and move + // forward in the array instead of searching for the node again. + if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { + currentArrayIndex++; + current = currentArray[currentArrayIndex]; } - pos++; + // If we don't have a node, or the node we have isn't in the right position, + // then try to find a viable node at the position requested. + if (!current || current.pos !== position) { + findHighestListElementThatStartsAtPosition(position); + } } + + // Cache this query so that we don't do any extra work if the parser calls back + // into us. Note: this is very common as the parser will make pairs of calls like + // 'isListElement -> parseListElement'. If we were unable to find a node when + // called with 'isListElement', we don't want to redo the work when parseListElement + // is called immediately after. + lastQueriedPosition = position; + + // Either we don'd have a node, or we have a node at the position being asked for. + Debug.assert(!current || current.pos === position); + return current; } + }; - setError(); - } + // Finds the highest element in the tree we can find that starts at the provided position. + // The element must be a direct child of some node list in the tree. This way after we + // return it, we can easily return its next sibling in the list. + function findHighestListElementThatStartsAtPosition(position: number) { + // Clear out any cached state about the last node we found. + currentArray = undefined; + currentArrayIndex = InvalidPosition.Value; + current = undefined; + + // Recurse into the source file to find the highest node at this position. + forEachChild(sourceFile, visitNode, visitArray); + return; - function scanIdentifier(): string { - skipWhitespace(); + function visitNode(node: Node) { + if (position >= node.pos && position < node.end) { + // Position was within this node. Keep searching deeper to find the node. + forEachChild(node, visitNode, visitArray); - let startPos = pos; - for (; pos < end; pos++) { - let ch = content.charCodeAt(pos); - if (pos === startPos && isIdentifierStart(ch, ScriptTarget.Latest)) { - continue; - } - else if (pos > startPos && isIdentifierPart(ch, ScriptTarget.Latest)) { - continue; + // don't procede any futher in the search. + return true; } - break; + // position wasn't in this node, have to keep searching. + return false; } - if (startPos === pos) { - setError(); - return; - } + function visitArray(array: NodeArray) { + if (position >= array.pos && position < array.end) { + // position was in this array. Search through this array to see if we find a + // viable element. + for (let i = 0, n = array.length; i < n; i++) { + let child = array[i]; + if (child) { + if (child.pos === position) { + // Found the right node. We're done. + currentArray = array; + currentArrayIndex = i; + current = child; + return true; + } + else { + if (child.pos < position && position < child.end) { + // Position in somewhere within this child. Search in it and + // stop searching in this array. + forEachChild(child, visitNode, visitArray); + return true; + } + } + } + } + } - return content.substring(startPos, pos); + // position wasn't in this array, have to keep searching. + return false; + } } } + + const enum InvalidPosition { + Value = -1 + } } } \ No newline at end of file diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 49f7da6c884a8..cadc9dc027bfc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -281,7 +281,7 @@ module ts { JSDocNullableType, JSDocNonNullableType, JSDocRecordType, - JSDocMember, + JSDocRecordMember, JSDocTypeReference, JSDocOptionalType, JSDocFunctionType, @@ -1055,7 +1055,7 @@ module ts { } export interface JSDocRecordType extends JSDocType { - members: NodeArray; + members: NodeArray; } export interface JSDocTypeReference extends JSDocType { @@ -1084,7 +1084,7 @@ module ts { type: JSDocType; } - export interface JSDocMember extends Node { + export interface JSDocRecordMember extends Node { name: Identifier | LiteralExpression, type?: JSDocType } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 39766dc0b3a3d..fc5df690bdadf 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -850,7 +850,7 @@ module ts { } export function getJSDocParameter(parameter: ParameterDeclaration, sourceFile: SourceFile): JSDocParameter { - if (parameter.name.kind === SyntaxKind.Identifier) { + if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. let parameterName = (parameter.name).text; diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d0984f27280a2..a18436e20786d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -196,7 +196,11 @@ module Utils { return isNodeOrArray(v) ? serializeNode(v) : v; }, " "); - function getKindName(k: number): string { + function getKindName(k: number|string): string { + if (typeof k === "string") { + return k; + } + return (ts).SyntaxKind[k] } @@ -249,6 +253,10 @@ module Utils { // Blacklist of items we never put in the baseline file. break; + case "originalKeywordKind": + o[propertyName] = getKindName((n)[propertyName]); + break; + case "flags": // Print out flags with their enum names. o[propertyName] = getNodeFlagName(n.flags); diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo1.ts b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts index 71072f1699aa2..9a9fa4f622244 100644 --- a/tests/cases/fourslash/getJavaScriptQuickInfo1.ts +++ b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts @@ -5,5 +5,6 @@ /////** @type {function(new:string,number)} */ ////var /**/v; +debugger; goTo.marker(); verify.quickInfoIs('var v: new (p1: number) => string'); \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 10537cd444a6d..0a08c106fc070 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -4,18 +4,28 @@ module ts { describe("JSDocParsing", () => { + //function nodeToJSON(file: ts.Node): string { + // return JSON.stringify(Utils.serializeNode(file), (k, v) => { + // return isNodeOrArray(v) ? Utils.serializeNode(v) : v; + // }, " "); + //} + + //function isNodeOrArray(a: any): boolean { + // return a !== undefined && typeof a.pos === "number"; + //} + describe("TypeExpressions", () => { function parsesCorrectly(content: string, expected: string) { - let typeExpression = ts.parseJSDocTypeExpression(content); - assert.isNotNull(typeExpression); + let typeAndDiagnostics = ts.parseJSDocTypeExpression(content); + assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0); - let result = Utils.sourceFileToJSON(typeExpression.type); + let result = Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type); assert.equal(result, expected); } function parsesIncorrectly(content: string) { let type = ts.parseJSDocTypeExpression(content); - assert.equal(type, undefined); + assert.isTrue(!type || type.diagnostics.length > 0); } describe("parseCorrectly", () => { @@ -51,6 +61,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -71,6 +82,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 7, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -91,6 +103,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -111,6 +124,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 7, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -139,7 +153,7 @@ module ts { "end": 6, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 5, "name": { @@ -164,7 +178,7 @@ module ts { "end": 14, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 13, "name": { @@ -181,6 +195,7 @@ module ts { "kind": "Identifier", "pos": 6, "end": 13, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -200,7 +215,7 @@ module ts { "end": 11, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 5, "name": { @@ -211,7 +226,7 @@ module ts { } }, "1": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 6, "end": 10, "name": { @@ -236,7 +251,7 @@ module ts { "end": 19, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 13, "name": { @@ -253,12 +268,13 @@ module ts { "kind": "Identifier", "pos": 6, "end": 13, + "originalKeywordKind": "NumberKeyword", "text": "number" } } }, "1": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 14, "end": 18, "name": { @@ -283,7 +299,7 @@ module ts { "end": 19, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 5, "name": { @@ -294,7 +310,7 @@ module ts { } }, "1": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 6, "end": 18, "name": { @@ -311,6 +327,7 @@ module ts { "kind": "Identifier", "pos": 11, "end": 18, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -330,7 +347,7 @@ module ts { "end": 27, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 13, "name": { @@ -347,12 +364,13 @@ module ts { "kind": "Identifier", "pos": 6, "end": 13, + "originalKeywordKind": "NumberKeyword", "text": "number" } } }, "1": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 14, "end": 26, "name": { @@ -369,6 +387,7 @@ module ts { "kind": "Identifier", "pos": 19, "end": 26, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -388,13 +407,14 @@ module ts { "end": 11, "members": { "0": { - "kind": "JSDocMember", + "kind": "JSDocRecordMember", "pos": 2, "end": 10, "name": { - "kind": "FunctionKeyword", + "kind": "Identifier", "pos": 2, "end": 10, + "originalKeywordKind": "FunctionKeyword", "text": "function" } }, @@ -420,6 +440,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -431,6 +452,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "originalKeywordKind": "StringKeyword", "text": "string" } }, @@ -456,6 +478,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 7, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -467,6 +490,7 @@ module ts { "kind": "Identifier", "pos": 8, "end": 14, + "originalKeywordKind": "StringKeyword", "text": "string" } }, @@ -510,6 +534,7 @@ module ts { "kind": "Identifier", "pos": 10, "end": 16, + "originalKeywordKind": "StringKeyword", "text": "string" } } @@ -526,6 +551,7 @@ module ts { "kind": "Identifier", "pos": 17, "end": 25, + "originalKeywordKind": "BooleanKeyword", "text": "boolean" } } @@ -556,6 +582,7 @@ module ts { "kind": "Identifier", "pos": 10, "end": 16, + "originalKeywordKind": "StringKeyword", "text": "string" } } @@ -572,6 +599,7 @@ module ts { "kind": "Identifier", "pos": 17, "end": 25, + "originalKeywordKind": "BooleanKeyword", "text": "boolean" } } @@ -659,6 +687,7 @@ module ts { "kind": "Identifier", "pos": 4, "end": 10, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -679,6 +708,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 7, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -720,6 +750,7 @@ module ts { "kind": "Identifier", "pos": 4, "end": 10, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -751,6 +782,7 @@ module ts { "kind": "Identifier", "pos": 4, "end": 10, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -762,6 +794,7 @@ module ts { "kind": "Identifier", "pos": 11, "end": 17, + "originalKeywordKind": "StringKeyword", "text": "string" } }, @@ -792,6 +825,7 @@ module ts { "kind": "Identifier", "pos": 3, "end": 11, + "originalKeywordKind": "FunctionKeyword", "text": "function" } } @@ -887,6 +921,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 4, + "originalKeywordKind": "VarKeyword", "text": "var" } }`); @@ -903,6 +938,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 5, + "originalKeywordKind": "NullKeyword", "text": "null" } }`); @@ -955,6 +991,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -981,6 +1018,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -992,6 +1030,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "originalKeywordKind": "StringKeyword", "text": "string" } }, @@ -1018,6 +1057,7 @@ module ts { "kind": "Identifier", "pos": 2, "end": 8, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -1029,6 +1069,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "originalKeywordKind": "StringKeyword", "text": "string" } }, @@ -1040,6 +1081,7 @@ module ts { "kind": "Identifier", "pos": 16, "end": 23, + "originalKeywordKind": "BooleanKeyword", "text": "boolean" } }, @@ -1148,8 +1190,10 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = ts.parseJSDocComment(/*parent:*/ undefined, content); - let result = JSON.stringify(comment, (k, v) => { + let comment = ts.parseJSDocComment(content); + Debug.assert(comment && comment.diagnostics.length === 0); + + let result = JSON.stringify(comment.jsDocComment, (k, v) => { return v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v; @@ -1158,8 +1202,8 @@ module ts { } function parsesIncorrectly(content: string) { - let type = ts.parseJSDocComment(/*parent:*/ undefined, content); - assert.equal(type, undefined); + let type = ts.parseJSDocComment(content); + assert.isTrue(!type || type.diagnostics.length > 0); } describe("parsesIncorrectly", () => { @@ -1175,18 +1219,18 @@ module ts { parsesIncorrectly("/** * @type {number} */"); }); - it("multipleTypes", () => { + it("noType", () => { parsesIncorrectly( `/** - * @type {number} - * @type {string} + * @type */`); }); - it("noType", () => { + it("multipleTypes", () => { parsesIncorrectly( `/** - * @type + * @type {number} + * @type {string} */`); }); @@ -1253,9 +1297,10 @@ module ts { "pos": 15, "end": 21, "name": { - "kind": 65, + "kind": "Identifier", "pos": 15, "end": 21, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1273,9 +1318,10 @@ module ts { "pos": 15, "end": 21, "name": { - "kind": 65, + "kind": "Identifier", "pos": 15, "end": 21, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1293,9 +1339,10 @@ module ts { "pos": 15, "end": 21, "name": { - "kind": 65, + "kind": "Identifier", "pos": 15, "end": 21, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1313,9 +1360,10 @@ module ts { "pos": 17, "end": 23, "name": { - "kind": 65, + "kind": "Identifier", "pos": 17, "end": 23, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1333,9 +1381,10 @@ module ts { "pos": 17, "end": 23, "name": { - "kind": 65, + "kind": "Identifier", "pos": 17, "end": 23, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1353,9 +1402,10 @@ module ts { "pos": 18, "end": 24, "name": { - "kind": 65, + "kind": "Identifier", "pos": 18, "end": 24, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1376,9 +1426,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1402,9 +1453,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1416,9 +1468,10 @@ module ts { "pos": 42, "end": 48, "name": { - "kind": 65, + "kind": "Identifier", "pos": 42, "end": 48, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1441,9 +1494,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1466,9 +1520,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -1492,9 +1547,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } }, @@ -1518,9 +1574,10 @@ module ts { "pos": 16, "end": 22, "name": { - "kind": 65, + "kind": "Identifier", "pos": 16, "end": 22, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1543,9 +1600,10 @@ module ts { "pos": 22, "end": 28, "name": { - "kind": 65, + "kind": "Identifier", "pos": 22, "end": 28, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1568,9 +1626,10 @@ module ts { "pos": 22, "end": 28, "name": { - "kind": 65, + "kind": "Identifier", "pos": 22, "end": 28, + "originalKeywordKind": "NumberKeyword", "text": "number" } } @@ -1588,14 +1647,14 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "T", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "T" + } } ] }`); @@ -1610,25 +1669,25 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "K", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "K" + } }, { "kind": "TypeParameter", + "pos": 20, + "end": 21, "name": { - "kind": 65, - "text": "V", + "kind": "Identifier", "pos": 20, - "end": 21 - }, - "pos": 20, - "end": 21 + "end": 21, + "text": "V" + } } ] }`); @@ -1643,25 +1702,25 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "K", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "K" + } }, { "kind": "TypeParameter", + "pos": 21, + "end": 22, "name": { - "kind": 65, - "text": "V", + "kind": "Identifier", "pos": 21, - "end": 22 - }, - "pos": 21, - "end": 22 + "end": 22, + "text": "V" + } } ] }`); @@ -1676,25 +1735,25 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "K", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "K" + } }, { "kind": "TypeParameter", + "pos": 21, + "end": 22, "name": { - "kind": 65, - "text": "V", + "kind": "Identifier", "pos": 21, - "end": 22 - }, - "pos": 21, - "end": 22 + "end": 22, + "text": "V" + } } ] }`); @@ -1709,25 +1768,25 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "K", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "K" + } }, { "kind": "TypeParameter", + "pos": 22, + "end": 23, "name": { - "kind": 65, - "text": "V", + "kind": "Identifier", "pos": 22, - "end": 23 - }, - "pos": 22, - "end": 23 + "end": 23, + "text": "V" + } } ] }`); @@ -1742,25 +1801,25 @@ module ts { "typeParameters": [ { "kind": "TypeParameter", + "pos": 18, + "end": 19, "name": { - "kind": 65, - "text": "K", + "kind": "Identifier", "pos": 18, - "end": 19 - }, - "pos": 18, - "end": 19 + "end": 19, + "text": "K" + } }, { "kind": "TypeParameter", + "pos": 22, + "end": 23, "name": { - "kind": 65, - "text": "V", + "kind": "Identifier", "pos": 22, - "end": 23 - }, - "pos": 22, - "end": 23 + "end": 23, + "text": "V" + } } ] }`); From 5544639d57e816ef089f66f84458c67524b31c7a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 15 Apr 2015 22:00:49 -0700 Subject: [PATCH 54/96] Add test for javascript syntactic diagnostics. --- src/harness/fourslash.ts | 7 +++++++ tests/cases/fourslash/fourslash.ts | 4 ++++ .../getJavaScriptSyntacticDiagnostics1.ts | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/cases/fourslash/getJavaScriptSyntacticDiagnostics1.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7269b2db75dc4..b2eab6576fef0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -798,6 +798,13 @@ module FourSlash { return "\nActual " + name + ":\n\t" + actualValue + "\nExpected value:\n\t" + expectedValue; } + public getSyntacticDiagnostics(expected: string) { + var diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); + var realized = ts.realizeDiagnostics(diagnostics, "\r\n"); + var actual = JSON.stringify(realized, null, " "); + assert.equal(actual, expected); + } + public getSemanticDiagnostics(expected: string) { var diagnostics = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); var realized = ts.realizeDiagnostics(diagnostics, "\r\n"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8ade18fc2009e..ef9ab51d61ffa 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -440,6 +440,10 @@ module FourSlashInterface { FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); } + public getSyntacticDiagnostics(expected: string) { + FourSlash.currentTestState.getSyntacticDiagnostics(expected); + } + public getSemanticDiagnostics(expected: string) { FourSlash.currentTestState.getSemanticDiagnostics(expected); } diff --git a/tests/cases/fourslash/getJavaScriptSyntacticDiagnostics1.ts b/tests/cases/fourslash/getJavaScriptSyntacticDiagnostics1.ts new file mode 100644 index 0000000000000..42631c8b0addc --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptSyntacticDiagnostics1.ts @@ -0,0 +1,19 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: a.js +//// /** +//// * @type {number} +//// * @type {string} +//// */ +//// var v; + +verify.getSyntacticDiagnostics(`[ + { + "message": "\'type\' tag already specified.", + "start": 26, + "length": 4, + "category": "error", + "code": 1218 + } +]`); \ No newline at end of file From 4840d69869bf64bb4750ff96902bfa9f35f6669f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 00:07:05 -0700 Subject: [PATCH 55/96] Move binding code back into the binder. --- src/compiler/binder.ts | 124 ++++++++++++++++++++++++++++++-------- src/compiler/checker.ts | 28 +-------- src/compiler/utilities.ts | 6 ++ 3 files changed, 108 insertions(+), 50 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ee52fbedd402a..37f89f186fa0d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -52,17 +52,6 @@ module ts { } } - /* @internal */ - export function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolKind: SymbolFlags) { - symbol.flags |= symbolKind; - if (!symbol.declarations) symbol.declarations = []; - symbol.declarations.push(node); - if (symbolKind & SymbolFlags.HasExports && !symbol.exports) symbol.exports = {}; - if (symbolKind & SymbolFlags.HasMembers && !symbol.members) symbol.members = {}; - node.symbol = symbol; - if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node; - } - export function bindSourceFile(file: SourceFile): void { let start = new Date().getTime(); bindSourceFileWorker(file); @@ -76,6 +65,7 @@ module ts { let lastContainer: Node; let symbolCount = 0; let Symbol = objectAllocator.getSymbolConstructor(); + let isJavaScriptFile = isJavaScript(file.fileName); if (!file.locals) { file.locals = {}; @@ -97,6 +87,16 @@ module ts { } } + function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolKind: SymbolFlags) { + symbol.flags |= symbolKind; + if (!symbol.declarations) symbol.declarations = []; + symbol.declarations.push(node); + if (symbolKind & SymbolFlags.HasExports && !symbol.exports) symbol.exports = {}; + if (symbolKind & SymbolFlags.HasMembers && !symbol.members) symbol.members = {}; + node.symbol = symbol; + if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node; + } + // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. function getDeclarationName(node: Declaration): string { @@ -257,10 +257,8 @@ module ts { setBlockScopeContainer(node, /*cleanLocals*/ (symbolKind & SymbolFlags.HasLocals) === 0 && node.kind !== SyntaxKind.SourceFile); } - if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { - if (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.FunctionDeclaration) { - bindJSDocTypeParameters(node); - } + if (isJavaScriptFile && node.jsDocComment) { + bindJSDocComment(node); } forEachChild(node, bind); @@ -269,11 +267,55 @@ module ts { blockScopeContainer = savedBlockScopeContainer; } - function bindJSDocTypeParameters(node: FunctionLikeDeclaration) { + + + function bindJSDocComment(node: Node) { let jsDocComment = node.jsDocComment; - if (jsDocComment) { + + if (jsDocComment.type) { + bind(jsDocComment.type); + } + + if (jsDocComment.returnType) { + bind(jsDocComment.returnType); + } + + forEach(jsDocComment.parameters, bindJSDocParameter); + + if (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.FunctionDeclaration) { forEach(jsDocComment.typeParameters, bind); - } + } + } + + function bindJSDocParameter(parameter: JSDocParameter) { + if (parameter.type) { + bind(parameter.type); + } + } + + function bindJSDocFunctionType(node: JSDocFunctionType) { + let isConstructSignature = isJSDocConstructSignature(node); + let name = isConstructSignature ? "__new" : "__call"; + + let symbol = createSymbol(SymbolFlags.Signature, name); + addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); + node.locals = {}; + + let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); + typeLiteralSymbol.members = {}; + typeLiteralSymbol.members[name] = symbol + + node.symbol = typeLiteralSymbol; + + saveParentAndBindChildren(node); + } + + function saveParentAndBindChildren(node: Node) { + let saveParent = parent; + parent = node; + forEachChild(node, bind); + parent = saveParent; } function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { @@ -431,9 +473,9 @@ module ts { return "__" + indexOf((node.parent).parameters, node); } - function bind(node: Node) { + function bind(node: Node): void { node.parent = parent; - + switch (node.kind) { case SyntaxKind.TypeParameter: bindDeclaration(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes, /*isBlockScopeContainer*/ false); @@ -441,6 +483,9 @@ module ts { case SyntaxKind.Parameter: bindParameter(node); break; + case SyntaxKind.VariableStatement: + bindVariableStatement(node); + break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: if (isBindingPattern((node).name)) { @@ -588,18 +633,33 @@ module ts { case SyntaxKind.CaseBlock: bindChildren(node, 0, /*isBlockScopeContainer*/ true); break; + case SyntaxKind.JSDocFunctionType: + bindJSDocFunctionType(node); + break; default: - let saveParent = parent; - parent = node; - forEachChild(node, bind); - parent = saveParent; + saveParentAndBindChildren(node); + } + } + + function bindVariableStatement(node: VariableStatement) { + let saveParent = parent; + parent = node; + + if (isJavaScriptFile && node.jsDocComment) { + bindJSDocComment(node); } + + forEachChild(node, bind); + parent = saveParent; } function bindParameter(node: ParameterDeclaration) { if (isBindingPattern(node.name)) { bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node), /*isBlockScopeContainer*/ false); } + else if (isJavaScriptFile && node.parent.kind === SyntaxKind.JSDocFunctionType) { + bindJSDocFunctionTypeParameter(node); + } else { bindDeclaration(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false); } @@ -615,6 +675,22 @@ module ts { } } + function bindJSDocFunctionTypeParameter(node: ParameterDeclaration) { + let functionType = node.parent; + let isConstructSignature = isJSDocConstructSignature(functionType); + + if (!isConstructSignature || functionType.parameters[0] !== node) { + let index = indexOf(functionType.parameters, node); + let paramName = "p" + index; + let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, paramName); + addDeclarationToSymbol(paramSymbol, node, SymbolFlags.FunctionScopedVariable); + + functionType.locals[paramName] = paramSymbol; + } + + bindChildren(node, SymbolFlags.FunctionScopedVariable, /*isBlockScopeContainer:*/ false); + } + function bindPropertyOrMethodOrAccessor(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { if (hasDynamicName(node)) { bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f8d7c110e2eda..5db2741f5011f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3748,33 +3748,9 @@ module ts { return links.resolvedType; } - function isJSDocConstructSignature(node: SignatureDeclaration) { - return node.kind === SyntaxKind.JSDocFunctionType && - node.parameters.length > 0 && - node.parameters[0].type.kind === SyntaxKind.JSDocConstructorType; - } - function getTypeFromJSDocFunctionType(node: JSDocFunctionType): Type { - let isConstructSignature = isJSDocConstructSignature(node); - let name = isConstructSignature ? "__new" : "__call"; - - let symbol = createSymbol(SymbolFlags.Signature, name); - addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - node.locals = {}; - for (let i = isConstructSignature ? 1 : 0; i < node.parameters.length; i++) { - let paramName = "p" + i; - let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, paramName); - addDeclarationToSymbol(paramSymbol, node.parameters[i], SymbolFlags.FunctionScopedVariable); - - node.locals[paramName] = paramSymbol; - } - - let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = {}; - typeLiteralSymbol.members[name] = symbol - - return createObjectType(TypeFlags.Anonymous, typeLiteralSymbol); + Debug.assert(!!node.symbol); + return createObjectType(TypeFlags.Anonymous, node.symbol); } function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fc5df690bdadf..cd4ac113db01e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -849,6 +849,12 @@ module ts { return false; } + export function isJSDocConstructSignature(node: SignatureDeclaration) { + return node.kind === SyntaxKind.JSDocFunctionType && + node.parameters.length > 0 && + node.parameters[0].type.kind === SyntaxKind.JSDocConstructorType; + } + export function getJSDocParameter(parameter: ParameterDeclaration, sourceFile: SourceFile): JSDocParameter { if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) { // If it's a parameter, see if the parent has a jsdoc comment with an @param From a9cd5689e164523fcf47ef36c042937befab8fcb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 00:08:27 -0700 Subject: [PATCH 56/96] Fix spacing. --- src/compiler/binder.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 37f89f186fa0d..8c40000d1f352 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -267,8 +267,6 @@ module ts { blockScopeContainer = savedBlockScopeContainer; } - - function bindJSDocComment(node: Node) { let jsDocComment = node.jsDocComment; From ab072923cec47c0c525e026e53ca4d02a3da457d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 00:25:18 -0700 Subject: [PATCH 57/96] Simplify checker. --- src/compiler/checker.ts | 138 ++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5db2741f5011f..6578d344c1d8b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2112,7 +2112,9 @@ module ts { function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) { let jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); - return getTypeFromTypeNode(jsDocType); + if (jsDocType) { + return getTypeFromTypeNode(jsDocType); + } } function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { @@ -3807,74 +3809,72 @@ module ts { } function getTypeFromTypeNodeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type { - if (node) { - switch (node.kind) { - case SyntaxKind.AnyKeyword: - return anyType; - case SyntaxKind.StringKeyword: - return stringType; - case SyntaxKind.NumberKeyword: - return numberType; - case SyntaxKind.BooleanKeyword: - return booleanType; - case SyntaxKind.SymbolKeyword: - return esSymbolType; - case SyntaxKind.VoidKeyword: - return voidType; - case SyntaxKind.StringLiteral: - return getTypeFromStringLiteral(node); - case SyntaxKind.TypeReference: - return getTypeFromTypeReference(node); - case SyntaxKind.HeritageClauseElement: - return getTypeFromHeritageClauseElement(node); - case SyntaxKind.TypeQuery: - return getTypeFromTypeQueryNode(node); - case SyntaxKind.ArrayType: - return getTypeFromArrayTypeNode(node); - case SyntaxKind.TupleType: - return getTypeFromTupleTypeNode(node); - case SyntaxKind.UnionType: - return getTypeFromUnionTypeNode(node); - case SyntaxKind.ParenthesizedType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - case SyntaxKind.TypeLiteral: - return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - // This function assumes that an identifier or qualified name is a type expression - // Callers should first ensure this by calling isTypeNode - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: - let symbol = getSymbolInfo(node); - return symbol && getDeclaredTypeOfSymbol(symbol); - case SyntaxKind.JSDocAllType: - return anyType; - case SyntaxKind.JSDocUnknownType: - return unknownType; - case SyntaxKind.JSDocArrayType: - return getTypeFromJSDocArrayType(node); - case SyntaxKind.JSDocTupleType: - return getTypeFromJSDocTupleType(node); - case SyntaxKind.JSDocUnionType: - return getTypeFromJSDocUnionType(node); - case SyntaxKind.JSDocNullableType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocNonNullableType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocTypeReference: - return getTypeForJSDocTypeReference(node); - case SyntaxKind.JSDocOptionalType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocFunctionType: - return getTypeFromJSDocFunctionType(node); - case SyntaxKind.JSDocVariadicType: - return getTypeFromJSDocVariadicType(node); - case SyntaxKind.JSDocConstructorType: - return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocThisType: - case SyntaxKind.JSDocRecordType: - // NYI: - } + switch (node.kind) { + case SyntaxKind.AnyKeyword: + return anyType; + case SyntaxKind.StringKeyword: + return stringType; + case SyntaxKind.NumberKeyword: + return numberType; + case SyntaxKind.BooleanKeyword: + return booleanType; + case SyntaxKind.SymbolKeyword: + return esSymbolType; + case SyntaxKind.VoidKeyword: + return voidType; + case SyntaxKind.StringLiteral: + return getTypeFromStringLiteral(node); + case SyntaxKind.TypeReference: + return getTypeFromTypeReference(node); + case SyntaxKind.HeritageClauseElement: + return getTypeFromHeritageClauseElement(node); + case SyntaxKind.TypeQuery: + return getTypeFromTypeQueryNode(node); + case SyntaxKind.ArrayType: + return getTypeFromArrayTypeNode(node); + case SyntaxKind.TupleType: + return getTypeFromTupleTypeNode(node); + case SyntaxKind.UnionType: + return getTypeFromUnionTypeNode(node); + case SyntaxKind.ParenthesizedType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeLiteral: + return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); + // This function assumes that an identifier or qualified name is a type expression + // Callers should first ensure this by calling isTypeNode + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + let symbol = getSymbolInfo(node); + return symbol && getDeclaredTypeOfSymbol(symbol); + case SyntaxKind.JSDocAllType: + return anyType; + case SyntaxKind.JSDocUnknownType: + return unknownType; + case SyntaxKind.JSDocArrayType: + return getTypeFromJSDocArrayType(node); + case SyntaxKind.JSDocTupleType: + return getTypeFromJSDocTupleType(node); + case SyntaxKind.JSDocUnionType: + return getTypeFromJSDocUnionType(node); + case SyntaxKind.JSDocNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocNonNullableType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocTypeReference: + return getTypeForJSDocTypeReference(node); + case SyntaxKind.JSDocOptionalType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocFunctionType: + return getTypeFromJSDocFunctionType(node); + case SyntaxKind.JSDocVariadicType: + return getTypeFromJSDocVariadicType(node); + case SyntaxKind.JSDocConstructorType: + return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocThisType: + case SyntaxKind.JSDocRecordType: + // NYI: } return unknownType; From 37101018a989ea65f969728173b7d7721d946c59 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 00:33:25 -0700 Subject: [PATCH 58/96] Remove unnecessary file. --- .../reference/APISample_compile.types | 168 ------- .../reference/APISample_linter.types | 312 ------------ .../reference/APISample_transform.types | 44 -- .../reference/APISample_watcher.types | 443 ------------------ 4 files changed, 967 deletions(-) delete mode 100644 tests/baselines/reference/APISample_compile.types delete mode 100644 tests/baselines/reference/APISample_linter.types delete mode 100644 tests/baselines/reference/APISample_transform.types delete mode 100644 tests/baselines/reference/APISample_watcher.types diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types deleted file mode 100644 index 676394cfedc27..0000000000000 --- a/tests/baselines/reference/APISample_compile.types +++ /dev/null @@ -1,168 +0,0 @@ -=== tests/cases/compiler/APISample_compile.ts === - -/* - * Note: This test is a public API sample. The sample sources can be found - at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler - * Please log a "breaking change" issue for any API breaking change affecting this issue - */ - -declare var process: any; ->process : any, Symbol(process, Decl(APISample_compile.ts, 7, 11)) - -declare var console: any; ->console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) - -declare var os: any; ->os : any, Symbol(os, Decl(APISample_compile.ts, 9, 11)) - -import ts = require("typescript"); ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) - -export function compile(fileNames: string[], options: ts.CompilerOptions): void { ->compile : (fileNames: string[], options: ts.CompilerOptions) => void, Symbol(compile, Decl(APISample_compile.ts, 11, 34)) ->fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) ->ts : any, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1155, 5)) - - var program = ts.createProgram(fileNames, options); ->program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->ts.createProgram(fileNames, options) : ts.Program ->ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1307, 113)) ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1307, 113)) ->fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24)) ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44)) - - var emitResult = program.emit(); ->emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->program.emit() : ts.EmitResult ->program.emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 848, 39)) ->program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->emit : (targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback) => ts.EmitResult, Symbol(ts.Program.emit, Decl(typescript.d.ts, 848, 39)) - - var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); ->allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) ->ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics(program).concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->ts.getPreEmitDiagnostics(program) : ts.Diagnostic[] ->ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1305, 98)) ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1305, 98)) ->program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7)) ->concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 901, 29)) ->emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 901, 29)) - - allDiagnostics.forEach(diagnostic => { ->allDiagnostics.forEach(diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); }) : void ->allDiagnostics.forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_compile.ts, 17, 7)) ->forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->diagnostic => { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } : (diagnostic: ts.Diagnostic) => void ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) - - var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); ->line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) ->character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) ->diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) - - var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); ->message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) ->ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) ->'\n' : string - - console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); ->console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) ->log : any ->`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->line + 1 : number ->line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13)) ->1 : number ->character + 1 : number ->character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19)) ->1 : number ->message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11)) - - }); - - var exitCode = emitResult.emitSkipped ? 1 : 0; ->exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) ->emitResult.emitSkipped ? 1 : 0 : number ->emitResult.emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 900, 26)) ->emitResult : ts.EmitResult, Symbol(emitResult, Decl(APISample_compile.ts, 15, 7)) ->emitSkipped : boolean, Symbol(ts.EmitResult.emitSkipped, Decl(typescript.d.ts, 900, 26)) ->1 : number ->0 : number - - console.log(`Process exiting with code '${exitCode}'.`); ->console.log(`Process exiting with code '${exitCode}'.`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_compile.ts, 8, 11)) ->log : any ->`Process exiting with code '${exitCode}'.` : string ->exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) - - process.exit(exitCode); ->process.exit(exitCode) : any ->process.exit : any ->process : any, Symbol(process, Decl(APISample_compile.ts, 7, 11)) ->exit : any ->exitCode : number, Symbol(exitCode, Decl(APISample_compile.ts, 25, 7)) -} - -compile(process.argv.slice(2), { ->compile(process.argv.slice(2), { noEmitOnError: true, noImplicitAny: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS}) : void ->compile : (fileNames: string[], options: ts.CompilerOptions) => void, Symbol(compile, Decl(APISample_compile.ts, 11, 34)) ->process.argv.slice(2) : any ->process.argv.slice : any ->process.argv : any ->process : any, Symbol(process, Decl(APISample_compile.ts, 7, 11)) ->argv : any ->slice : any ->2 : number ->{ noEmitOnError: true, noImplicitAny: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS} : { [x: string]: boolean | ts.ScriptTarget | ts.ModuleKind; noEmitOnError: boolean; noImplicitAny: boolean; target: ts.ScriptTarget; module: ts.ModuleKind; } - - noEmitOnError: true, noImplicitAny: true, ->noEmitOnError : boolean, Symbol(noEmitOnError, Decl(APISample_compile.ts, 30, 32)) ->true : boolean ->noImplicitAny : boolean, Symbol(noImplicitAny, Decl(APISample_compile.ts, 31, 24)) ->true : boolean - - target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS ->target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45)) ->ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1198, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) ->ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1198, 16)) ->module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) - -}); diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types deleted file mode 100644 index f2a7c475ae5f7..0000000000000 --- a/tests/baselines/reference/APISample_linter.types +++ /dev/null @@ -1,312 +0,0 @@ -=== tests/cases/compiler/APISample_linter.ts === - -/* - * Note: This test is a public API sample. The sample sources can be found - at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#traversing-the-ast-with-a-little-linter - * Please log a "breaking change" issue for any API breaking change affecting this issue - */ - -declare var process: any; ->process : any, Symbol(process, Decl(APISample_linter.ts, 7, 11)) - -declare var console: any; ->console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) - -declare var readFileSync: any; ->readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) - -import * as ts from "typescript"; ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) - -export function delint(sourceFile: ts.SourceFile) { ->delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SourceFile : ts.SourceFile, Symbol(ts.SourceFile, Decl(typescript.d.ts, 821, 5), Decl(typescript.d.ts, 1367, 5)) - - delintNode(sourceFile); ->delintNode(sourceFile) : void ->delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) - - function delintNode(node: ts.Node) { ->delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1327, 32)) - - switch (node.kind) { ->node.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) - - case ts.SyntaxKind.ForStatement: ->ts.SyntaxKind.ForStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForStatement, Decl(typescript.d.ts, 209, 29)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ForStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForStatement, Decl(typescript.d.ts, 209, 29)) - - case ts.SyntaxKind.ForInStatement: ->ts.SyntaxKind.ForInStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForInStatement, Decl(typescript.d.ts, 210, 27)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ForInStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.ForInStatement, Decl(typescript.d.ts, 210, 27)) - - case ts.SyntaxKind.WhileStatement: ->ts.SyntaxKind.WhileStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.WhileStatement, Decl(typescript.d.ts, 208, 26)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->WhileStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.WhileStatement, Decl(typescript.d.ts, 208, 26)) - - case ts.SyntaxKind.DoStatement: ->ts.SyntaxKind.DoStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.DoStatement, Decl(typescript.d.ts, 207, 26)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->DoStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.DoStatement, Decl(typescript.d.ts, 207, 26)) - - if ((node).statement.kind !== ts.SyntaxKind.Block) { ->(node).statement.kind !== ts.SyntaxKind.Block : boolean ->(node).statement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->(node).statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 605, 52)) ->(node) : ts.IterationStatement ->node : ts.IterationStatement ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IterationStatement : ts.IterationStatement, Symbol(ts.IterationStatement, Decl(typescript.d.ts, 604, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->statement : ts.Statement, Symbol(ts.IterationStatement.statement, Decl(typescript.d.ts, 605, 52)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) - - report(node, "A looping statement's contents should be wrapped in a block body."); ->report(node, "A looping statement's contents should be wrapped in a block body.") : void ->report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->"A looping statement's contents should be wrapped in a block body." : string - } - break; - - case ts.SyntaxKind.IfStatement: ->ts.SyntaxKind.IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) - - let ifStatement = (node); ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->(node) : ts.IfStatement ->node : ts.IfStatement ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->IfStatement : ts.IfStatement, Symbol(ts.IfStatement, Decl(typescript.d.ts, 599, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) - - if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) { ->ifStatement.thenStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.thenStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) - - report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); ->report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.") : void ->report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->thenStatement : ts.Statement, Symbol(ts.IfStatement.thenStatement, Decl(typescript.d.ts, 601, 31)) ->"An if statement's contents should be wrapped in a block body." : string - } - if (ifStatement.elseStatement && ->ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean ->ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) - - ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ->ifStatement.elseStatement.kind !== ts.SyntaxKind.Block : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ts.SyntaxKind.Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->Block : ts.SyntaxKind, Symbol(ts.SyntaxKind.Block, Decl(typescript.d.ts, 202, 36)) - - ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) { ->ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement : boolean ->ifStatement.elseStatement.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->ts.SyntaxKind.IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->IfStatement : ts.SyntaxKind, Symbol(ts.SyntaxKind.IfStatement, Decl(typescript.d.ts, 206, 34)) - - report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); ->report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.") : void ->report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->ifStatement.elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->ifStatement : ts.IfStatement, Symbol(ifStatement, Decl(APISample_linter.ts, 28, 19)) ->elseStatement : ts.Statement, Symbol(ts.IfStatement.elseStatement, Decl(typescript.d.ts, 602, 33)) ->"An else statement's contents should be wrapped in a block body." : string - } - break; - - case ts.SyntaxKind.BinaryExpression: ->ts.SyntaxKind.BinaryExpression : ts.SyntaxKind, Symbol(ts.SyntaxKind.BinaryExpression, Decl(typescript.d.ts, 192, 37)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->BinaryExpression : ts.SyntaxKind, Symbol(ts.SyntaxKind.BinaryExpression, Decl(typescript.d.ts, 192, 37)) - - let op = (node).operatorToken.kind; ->op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->(node).operatorToken.kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) ->(node).operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 513, 25)) ->(node) : ts.BinaryExpression ->node : ts.BinaryExpression ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->BinaryExpression : ts.BinaryExpression, Symbol(ts.BinaryExpression, Decl(typescript.d.ts, 511, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->operatorToken : ts.Node, Symbol(ts.BinaryExpression.operatorToken, Decl(typescript.d.ts, 513, 25)) ->kind : ts.SyntaxKind, Symbol(ts.Node.kind, Decl(typescript.d.ts, 313, 38)) - - if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) { ->op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken : boolean ->op === ts.SyntaxKind.EqualsEqualsToken : boolean ->op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->ts.SyntaxKind.EqualsEqualsToken : ts.SyntaxKind, Symbol(ts.SyntaxKind.EqualsEqualsToken, Decl(typescript.d.ts, 51, 36)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->EqualsEqualsToken : ts.SyntaxKind, Symbol(ts.SyntaxKind.EqualsEqualsToken, Decl(typescript.d.ts, 51, 36)) ->op == ts.SyntaxKind.ExclamationEqualsToken : boolean ->op : ts.SyntaxKind, Symbol(op, Decl(APISample_linter.ts, 40, 19)) ->ts.SyntaxKind.ExclamationEqualsToken : ts.SyntaxKind, Symbol(ts.SyntaxKind.ExclamationEqualsToken, Decl(typescript.d.ts, 52, 31)) ->ts.SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->SyntaxKind : typeof ts.SyntaxKind, Symbol(ts.SyntaxKind, Decl(typescript.d.ts, 22, 5)) ->ExclamationEqualsToken : ts.SyntaxKind, Symbol(ts.SyntaxKind.ExclamationEqualsToken, Decl(typescript.d.ts, 52, 31)) - - report(node, "Use '===' and '!=='.") ->report(node, "Use '===' and '!=='.") : void ->report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->"Use '===' and '!=='." : string - } - break; - } - - ts.forEachChild(node, delintNode); ->ts.forEachChild(node, delintNode) : void ->ts.forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1296, 48)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->forEachChild : (node: ts.Node, cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T) => T, Symbol(ts.forEachChild, Decl(typescript.d.ts, 1296, 48)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 16, 24)) ->delintNode : (node: ts.Node) => void, Symbol(delintNode, Decl(APISample_linter.ts, 14, 27)) - } - - function report(node: ts.Node, message: string) { ->report : (node: ts.Node, message: string) => void, Symbol(report, Decl(APISample_linter.ts, 48, 5)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->ts : any, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->Node : ts.Node, Symbol(ts.Node, Decl(typescript.d.ts, 312, 5), Decl(typescript.d.ts, 1327, 32)) ->message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) - - let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); ->line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) ->character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) ->sourceFile.getLineAndCharacterOfPosition(node.getStart()) : ts.LineAndCharacter ->sourceFile.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->node.getStart() : number ->node.getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1332, 53)) ->node : ts.Node, Symbol(node, Decl(APISample_linter.ts, 50, 20)) ->getStart : (sourceFile?: ts.SourceFile) => number, Symbol(ts.Node.getStart, Decl(typescript.d.ts, 1332, 53)) - - console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); ->console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_linter.ts, 8, 11)) ->log : any ->`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}` : string ->sourceFile.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 13, 23)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->line + 1 : number ->line : number, Symbol(line, Decl(APISample_linter.ts, 51, 13)) ->1 : number ->character + 1 : number ->character : number, Symbol(character, Decl(APISample_linter.ts, 51, 19)) ->1 : number ->message : string, Symbol(message, Decl(APISample_linter.ts, 50, 34)) - } -} - -const fileNames = process.argv.slice(2); ->fileNames : any, Symbol(fileNames, Decl(APISample_linter.ts, 56, 5)) ->process.argv.slice(2) : any ->process.argv.slice : any ->process.argv : any ->process : any, Symbol(process, Decl(APISample_linter.ts, 7, 11)) ->argv : any ->slice : any ->2 : number - -fileNames.forEach(fileName => { ->fileNames.forEach(fileName => { // Parse a file let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); // delint it delint(sourceFile);}) : any ->fileNames.forEach : any ->fileNames : any, Symbol(fileNames, Decl(APISample_linter.ts, 56, 5)) ->forEach : any ->fileName => { // Parse a file let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); // delint it delint(sourceFile);} : (fileName: any) => void ->fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) - - // Parse a file - let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true); ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) ->ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true) : ts.SourceFile ->ts.createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1297, 107)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->createSourceFile : (fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, setParentNodes?: boolean) => ts.SourceFile, Symbol(ts.createSourceFile, Decl(typescript.d.ts, 1297, 107)) ->fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) ->readFileSync(fileName).toString() : any ->readFileSync(fileName).toString : any ->readFileSync(fileName) : any ->readFileSync : any, Symbol(readFileSync, Decl(APISample_linter.ts, 9, 11)) ->fileName : any, Symbol(fileName, Decl(APISample_linter.ts, 57, 18)) ->toString : any ->ts.ScriptTarget.ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1199, 16)) ->ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_linter.ts, 11, 6)) ->ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1196, 5)) ->ES6 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES6, Decl(typescript.d.ts, 1199, 16)) ->true : boolean - - // delint it - delint(sourceFile); ->delint(sourceFile) : void ->delint : (sourceFile: ts.SourceFile) => void, Symbol(delint, Decl(APISample_linter.ts, 11, 33)) ->sourceFile : ts.SourceFile, Symbol(sourceFile, Decl(APISample_linter.ts, 59, 7)) - -}); diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types deleted file mode 100644 index 76622027caa23..0000000000000 --- a/tests/baselines/reference/APISample_transform.types +++ /dev/null @@ -1,44 +0,0 @@ -=== tests/cases/compiler/APISample_transform.ts === - -/* - * Note: This test is a public API sample. The sample sources can be found - at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-simple-transform-function - * Please log a "breaking change" issue for any API breaking change affecting this issue - */ - -declare var console: any; ->console : any, Symbol(console, Decl(APISample_transform.ts, 7, 11)) - -import * as ts from "typescript"; ->ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) - -const source = "let x: string = 'string'"; ->source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) ->"let x: string = 'string'" : string - -let result = ts.transpile(source, { module: ts.ModuleKind.CommonJS }); ->result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) ->ts.transpile(source, { module: ts.ModuleKind.CommonJS }) : string ->ts.transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1834, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->transpile : (input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[]) => string, Symbol(ts.transpile, Decl(typescript.d.ts, 1834, 5)) ->source : string, Symbol(source, Decl(APISample_transform.ts, 11, 5)) ->{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } ->module : ts.ModuleKind, Symbol(module, Decl(APISample_transform.ts, 13, 35)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_transform.ts, 9, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) - -console.log(JSON.stringify(result)); ->console.log(JSON.stringify(result)) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_transform.ts, 7, 11)) ->log : any ->JSON.stringify(result) : string ->JSON.stringify : { (value: any): string; (value: any, replacer: (key: string, value: any) => any): string; (value: any, replacer: any[]): string; (value: any, replacer: (key: string, value: any) => any, space: any): string; (value: any, replacer: any[], space: any): string; }, Symbol(JSON.stringify, Decl(lib.d.ts, 964, 70), Decl(lib.d.ts, 969, 34), Decl(lib.d.ts, 975, 78), Decl(lib.d.ts, 981, 51), Decl(lib.d.ts, 988, 90)) ->JSON : JSON, Symbol(JSON, Decl(lib.d.ts, 955, 42), Decl(lib.d.ts, 1000, 11)) ->stringify : { (value: any): string; (value: any, replacer: (key: string, value: any) => any): string; (value: any, replacer: any[]): string; (value: any, replacer: (key: string, value: any) => any, space: any): string; (value: any, replacer: any[], space: any): string; }, Symbol(JSON.stringify, Decl(lib.d.ts, 964, 70), Decl(lib.d.ts, 969, 34), Decl(lib.d.ts, 975, 78), Decl(lib.d.ts, 981, 51), Decl(lib.d.ts, 988, 90)) ->result : string, Symbol(result, Decl(APISample_transform.ts, 13, 3)) - diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types deleted file mode 100644 index 0930a1ebbff59..0000000000000 --- a/tests/baselines/reference/APISample_watcher.types +++ /dev/null @@ -1,443 +0,0 @@ -=== tests/cases/compiler/APISample_watcher.ts === - -/* - * Note: This test is a public API sample. The sample sources can be found - at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services - * Please log a "breaking change" issue for any API breaking change affecting this issue - */ - -declare var process: any; ->process : any, Symbol(process, Decl(APISample_watcher.ts, 7, 11)) - -declare var console: any; ->console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) - -declare var fs: any; ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) - -declare var path: any; ->path : any, Symbol(path, Decl(APISample_watcher.ts, 10, 11)) - -import * as ts from "typescript"; ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) - -function watch(rootFileNames: string[], options: ts.CompilerOptions) { ->watch : (rootFileNames: string[], options: ts.CompilerOptions) => void, Symbol(watch, Decl(APISample_watcher.ts, 12, 33)) ->rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) ->ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->CompilerOptions : ts.CompilerOptions, Symbol(ts.CompilerOptions, Decl(typescript.d.ts, 1155, 5)) - - const files: ts.Map<{ version: number }> = {}; ->files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) ->ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->Map : ts.Map, Symbol(ts.Map, Decl(typescript.d.ts, 15, 29)) ->version : number, Symbol(version, Decl(APISample_watcher.ts, 15, 25)) ->{} : { [x: string]: undefined; } - - // initialize the list of files - rootFileNames.forEach(fileName => { ->rootFileNames.forEach(fileName => { files[fileName] = { version: 0 }; }) : void ->rootFileNames.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) ->forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->fileName => { files[fileName] = { version: 0 }; } : (fileName: string) => void ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 18, 26)) - - files[fileName] = { version: 0 }; ->files[fileName] = { version: 0 } : { version: number; } ->files[fileName] : { version: number; } ->files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 18, 26)) ->{ version: 0 } : { version: number; } ->version : number, Symbol(version, Decl(APISample_watcher.ts, 19, 27)) ->0 : number - - }); - - // Create the language service host to allow the LS to communicate with the host - const servicesHost: ts.LanguageServiceHost = { ->servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) ->ts : any, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->LanguageServiceHost : ts.LanguageServiceHost, Symbol(ts.LanguageServiceHost, Decl(typescript.d.ts, 1400, 5)) ->{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; } - - getScriptFileNames: () => rootFileNames, ->getScriptFileNames : () => string[], Symbol(getScriptFileNames, Decl(APISample_watcher.ts, 23, 50)) ->() => rootFileNames : () => string[] ->rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) - - getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), ->getScriptVersion : (fileName: string) => string, Symbol(getScriptVersion, Decl(APISample_watcher.ts, 24, 48)) ->(fileName) => files[fileName] && files[fileName].version.toString() : (fileName: string) => string ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 25, 27)) ->files[fileName] && files[fileName].version.toString() : string ->files[fileName] : { version: number; } ->files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 25, 27)) ->files[fileName].version.toString() : string ->files[fileName].version.toString : (radix?: number) => string, Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) ->files[fileName].version : number, Symbol(version, Decl(APISample_watcher.ts, 15, 25)) ->files[fileName] : { version: number; } ->files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 25, 27)) ->version : number, Symbol(version, Decl(APISample_watcher.ts, 15, 25)) ->toString : (radix?: number) => string, Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) - - getScriptSnapshot: (fileName) => { ->getScriptSnapshot : (fileName: string) => ts.IScriptSnapshot, Symbol(getScriptSnapshot, Decl(APISample_watcher.ts, 25, 94)) ->(fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); } : (fileName: string) => ts.IScriptSnapshot ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 26, 28)) - - if (!fs.existsSync(fileName)) { ->!fs.existsSync(fileName) : boolean ->fs.existsSync(fileName) : any ->fs.existsSync : any ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) ->existsSync : any ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 26, 28)) - - return undefined; ->undefined : undefined, Symbol(undefined) - } - - return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); ->ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot ->ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1393, 27)) ->ts.ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1392, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ScriptSnapshot : typeof ts.ScriptSnapshot, Symbol(ts.ScriptSnapshot, Decl(typescript.d.ts, 1392, 5)) ->fromString : (text: string) => ts.IScriptSnapshot, Symbol(ts.ScriptSnapshot.fromString, Decl(typescript.d.ts, 1393, 27)) ->fs.readFileSync(fileName).toString() : any ->fs.readFileSync(fileName).toString : any ->fs.readFileSync(fileName) : any ->fs.readFileSync : any ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) ->readFileSync : any ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 26, 28)) ->toString : any - - }, - getCurrentDirectory: () => process.cwd(), ->getCurrentDirectory : () => any, Symbol(getCurrentDirectory, Decl(APISample_watcher.ts, 32, 10)) ->() => process.cwd() : () => any ->process.cwd() : any ->process.cwd : any ->process : any, Symbol(process, Decl(APISample_watcher.ts, 7, 11)) ->cwd : any - - getCompilationSettings: () => options, ->getCompilationSettings : () => ts.CompilerOptions, Symbol(getCompilationSettings, Decl(APISample_watcher.ts, 33, 49)) ->() => options : () => ts.CompilerOptions ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 14, 39)) - - getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), ->getDefaultLibFileName : (options: ts.CompilerOptions) => string, Symbol(getDefaultLibFileName, Decl(APISample_watcher.ts, 34, 46)) ->(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) ->ts.getDefaultLibFilePath(options) : string ->ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1842, 44)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->getDefaultLibFilePath : (options: ts.CompilerOptions) => string, Symbol(ts.getDefaultLibFilePath, Decl(typescript.d.ts, 1842, 44)) ->options : ts.CompilerOptions, Symbol(options, Decl(APISample_watcher.ts, 35, 32)) - - }; - - // Create the language service files - const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) ->services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService ->ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1840, 97)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService, Symbol(ts.createLanguageService, Decl(typescript.d.ts, 1840, 97)) ->servicesHost : ts.LanguageServiceHost, Symbol(servicesHost, Decl(APISample_watcher.ts, 23, 9)) ->ts.createDocumentRegistry() : ts.DocumentRegistry ->ts.createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1838, 193)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->createDocumentRegistry : () => ts.DocumentRegistry, Symbol(ts.createDocumentRegistry, Decl(typescript.d.ts, 1838, 193)) - - // Now let's watch the files - rootFileNames.forEach(fileName => { ->rootFileNames.forEach(fileName => { // First time around, emit all files emitFile(fileName); // Add a watch on the file to handle next change fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }); }) : void ->rootFileNames.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->rootFileNames : string[], Symbol(rootFileNames, Decl(APISample_watcher.ts, 14, 15)) ->forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->fileName => { // First time around, emit all files emitFile(fileName); // Add a watch on the file to handle next change fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }); } : (fileName: string) => void ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 42, 26)) - - // First time around, emit all files - emitFile(fileName); ->emitFile(fileName) : void ->emitFile : (fileName: string) => void, Symbol(emitFile, Decl(APISample_watcher.ts, 61, 7)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 42, 26)) - - // Add a watch on the file to handle next change - fs.watchFile(fileName, ->fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }) : any ->fs.watchFile : any ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) ->watchFile : any ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 42, 26)) - - { persistent: true, interval: 250 }, ->{ persistent: true, interval: 250 } : { persistent: boolean; interval: number; } ->persistent : boolean, Symbol(persistent, Decl(APISample_watcher.ts, 48, 13)) ->true : boolean ->interval : number, Symbol(interval, Decl(APISample_watcher.ts, 48, 31)) ->250 : number - - (curr, prev) => { ->(curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); } : (curr: any, prev: any) => void ->curr : any, Symbol(curr, Decl(APISample_watcher.ts, 49, 13)) ->prev : any, Symbol(prev, Decl(APISample_watcher.ts, 49, 18)) - - // Check timestamp - if (+curr.mtime <= +prev.mtime) { ->+curr.mtime <= +prev.mtime : boolean ->+curr.mtime : number ->curr.mtime : any ->curr : any, Symbol(curr, Decl(APISample_watcher.ts, 49, 13)) ->mtime : any ->+prev.mtime : number ->prev.mtime : any ->prev : any, Symbol(prev, Decl(APISample_watcher.ts, 49, 18)) ->mtime : any - - return; - } - - // Update the version to signal a change in the file - files[fileName].version++; ->files[fileName].version++ : number ->files[fileName].version : number, Symbol(version, Decl(APISample_watcher.ts, 15, 25)) ->files[fileName] : { version: number; } ->files : ts.Map<{ version: number; }>, Symbol(files, Decl(APISample_watcher.ts, 15, 9)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 42, 26)) ->version : number, Symbol(version, Decl(APISample_watcher.ts, 15, 25)) - - // write the changes to disk - emitFile(fileName); ->emitFile(fileName) : void ->emitFile : (fileName: string) => void, Symbol(emitFile, Decl(APISample_watcher.ts, 61, 7)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 42, 26)) - - }); - }); - - function emitFile(fileName: string) { ->emitFile : (fileName: string) => void, Symbol(emitFile, Decl(APISample_watcher.ts, 61, 7)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) - - let output = services.getEmitOutput(fileName); ->output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->services.getEmitOutput(fileName) : ts.EmitOutput ->services.getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1444, 132)) ->services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getEmitOutput : (fileName: string) => ts.EmitOutput, Symbol(ts.LanguageService.getEmitOutput, Decl(typescript.d.ts, 1444, 132)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) - - if (!output.emitSkipped) { ->!output.emitSkipped : boolean ->output.emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1647, 34)) ->output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->emitSkipped : boolean, Symbol(ts.EmitOutput.emitSkipped, Decl(typescript.d.ts, 1647, 34)) - - console.log(`Emitting ${fileName}`); ->console.log(`Emitting ${fileName}`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) ->log : any ->`Emitting ${fileName}` : string ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) - } - else { - console.log(`Emitting ${fileName} failed`); ->console.log(`Emitting ${fileName} failed`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) ->log : any ->`Emitting ${fileName} failed` : string ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) - - logErrors(fileName); ->logErrors(fileName) : void ->logErrors : (fileName: string) => void, Symbol(logErrors, Decl(APISample_watcher.ts, 77, 5)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 63, 22)) - } - - output.outputFiles.forEach(o => { ->output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void ->output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->output.outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1646, 26)) ->output : ts.EmitOutput, Symbol(output, Decl(APISample_watcher.ts, 64, 11)) ->outputFiles : ts.OutputFile[], Symbol(ts.EmitOutput.outputFiles, Decl(typescript.d.ts, 1646, 26)) ->forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void ->o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) - - fs.writeFileSync(o.name, o.text, "utf8"); ->fs.writeFileSync(o.name, o.text, "utf8") : any ->fs.writeFileSync : any ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) ->writeFileSync : any ->o.name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1655, 26)) ->o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->name : string, Symbol(ts.OutputFile.name, Decl(typescript.d.ts, 1655, 26)) ->o.text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1657, 36)) ->o : ts.OutputFile, Symbol(o, Decl(APISample_watcher.ts, 74, 35)) ->text : string, Symbol(ts.OutputFile.text, Decl(typescript.d.ts, 1657, 36)) ->"utf8" : string - - }); - } - - function logErrors(fileName: string) { ->logErrors : (fileName: string) => void, Symbol(logErrors, Decl(APISample_watcher.ts, 77, 5)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) - - let allDiagnostics = services.getCompilerOptionsDiagnostics() ->allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_watcher.ts, 80, 11)) ->services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) .concat(services.getSemanticDiagnostics(fileName)) : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics() .concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->services.getCompilerOptionsDiagnostics() : ts.Diagnostic[] ->services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1418, 63)) ->services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getCompilerOptionsDiagnostics : () => ts.Diagnostic[], Symbol(ts.LanguageService.getCompilerOptionsDiagnostics, Decl(typescript.d.ts, 1418, 63)) - - .concat(services.getSyntacticDiagnostics(fileName)) ->concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1416, 37)) ->services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSyntacticDiagnostics, Decl(typescript.d.ts, 1416, 37)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) - - .concat(services.getSemanticDiagnostics(fileName)); ->concat : { (...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46)) ->services.getSemanticDiagnostics(fileName) : ts.Diagnostic[] ->services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1417, 64)) ->services : ts.LanguageService, Symbol(services, Decl(APISample_watcher.ts, 39, 9)) ->getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[], Symbol(ts.LanguageService.getSemanticDiagnostics, Decl(typescript.d.ts, 1417, 64)) ->fileName : string, Symbol(fileName, Decl(APISample_watcher.ts, 79, 23)) - - allDiagnostics.forEach(diagnostic => { ->allDiagnostics.forEach(diagnostic => { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); if (diagnostic.file) { let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.log(` Error: ${message}`); } }) : void ->allDiagnostics.forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->allDiagnostics : ts.Diagnostic[], Symbol(allDiagnostics, Decl(APISample_watcher.ts, 80, 11)) ->forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void, Symbol(Array.forEach, Decl(lib.d.ts, 1108, 95)) ->diagnostic => { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); if (diagnostic.file) { let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.log(` Error: ${message}`); } } : (diagnostic: ts.Diagnostic) => void ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) - - let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); ->message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) ->ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string ->ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1306, 67)) ->diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1146, 23)) ->"\n" : string - - if (diagnostic.file) { ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) - - let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); ->line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) ->character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) ->diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter ->diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1368, 26)) ->diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1144, 25)) - - console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); ->console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) ->log : any ->` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string ->diagnostic.file.fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_watcher.ts, 84, 31)) ->file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1143, 26)) ->fileName : string, Symbol(ts.SourceFile.fileName, Decl(typescript.d.ts, 824, 29)) ->line + 1 : number ->line : number, Symbol(line, Decl(APISample_watcher.ts, 87, 21)) ->1 : number ->character + 1 : number ->character : number, Symbol(character, Decl(APISample_watcher.ts, 87, 27)) ->1 : number ->message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) - } - else { - console.log(` Error: ${message}`); ->console.log(` Error: ${message}`) : any ->console.log : any ->console : any, Symbol(console, Decl(APISample_watcher.ts, 8, 11)) ->log : any ->` Error: ${message}` : string ->message : string, Symbol(message, Decl(APISample_watcher.ts, 85, 15)) - } - }); - } -} - -// Initialize files constituting the program as all .ts files in the current directory -const currentDirectoryFiles = fs.readdirSync(process.cwd()). ->currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) ->fs.readdirSync(process.cwd()). filter(fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts") : any ->fs.readdirSync(process.cwd()). filter : any ->fs.readdirSync(process.cwd()) : any ->fs.readdirSync : any ->fs : any, Symbol(fs, Decl(APISample_watcher.ts, 9, 11)) ->readdirSync : any ->process.cwd() : any ->process.cwd : any ->process : any, Symbol(process, Decl(APISample_watcher.ts, 7, 11)) ->cwd : any - - filter(fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts"); ->filter : any ->fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts" : (fileName: any) => boolean ->fileName : any, Symbol(fileName, Decl(APISample_watcher.ts, 99, 11)) ->fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts" : boolean ->fileName.length >= 3 : boolean ->fileName.length : any ->fileName : any, Symbol(fileName, Decl(APISample_watcher.ts, 99, 11)) ->length : any ->3 : number ->fileName.substr(fileName.length - 3, 3) === ".ts" : boolean ->fileName.substr(fileName.length - 3, 3) : any ->fileName.substr : any ->fileName : any, Symbol(fileName, Decl(APISample_watcher.ts, 99, 11)) ->substr : any ->fileName.length - 3 : number ->fileName.length : any ->fileName : any, Symbol(fileName, Decl(APISample_watcher.ts, 99, 11)) ->length : any ->3 : number ->3 : number ->".ts" : string - -// Start the watcher -watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }); ->watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }) : void ->watch : (rootFileNames: string[], options: ts.CompilerOptions) => void, Symbol(watch, Decl(APISample_watcher.ts, 12, 33)) ->currentDirectoryFiles : any, Symbol(currentDirectoryFiles, Decl(APISample_watcher.ts, 98, 5)) ->{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; } ->module : ts.ModuleKind, Symbol(module, Decl(APISample_watcher.ts, 102, 30)) ->ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) ->ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->ts : typeof ts, Symbol(ts, Decl(APISample_watcher.ts, 12, 6)) ->ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1187, 5)) ->CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1189, 17)) - From 5e2e77e35745b1032d053be82cee8fb73dc1a735 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 21:30:24 -0700 Subject: [PATCH 59/96] Handle binding of JSDocFunctionTypes in a uniform manner with Consructor/FunctionTypes. --- src/compiler/binder.ts | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8c40000d1f352..16560e4cd2467 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -112,12 +112,12 @@ module ts { return (node.name).text; } switch (node.kind) { - case SyntaxKind.ConstructorType: case SyntaxKind.Constructor: return "__constructor"; case SyntaxKind.FunctionType: case SyntaxKind.CallSignature: return "__call"; + case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: return "__new"; case SyntaxKind.IndexSignature: @@ -129,6 +129,8 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: return node.flags & NodeFlags.Default ? "default" : undefined; + case SyntaxKind.JSDocFunctionType: + return isJSDocConstructSignature(node) ? "__new" : "__call"; } } @@ -291,24 +293,6 @@ module ts { } } - function bindJSDocFunctionType(node: JSDocFunctionType) { - let isConstructSignature = isJSDocConstructSignature(node); - let name = isConstructSignature ? "__new" : "__call"; - - let symbol = createSymbol(SymbolFlags.Signature, name); - addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - node.locals = {}; - - let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = {}; - typeLiteralSymbol.members[name] = symbol - - node.symbol = typeLiteralSymbol; - - saveParentAndBindChildren(node); - } - function saveParentAndBindChildren(node: Node) { let saveParent = parent; parent = node; @@ -415,7 +399,7 @@ module ts { } } - function bindFunctionOrConstructorType(node: SignatureDeclaration) { + function bindFunctionOrConstructorTypeORJSDocFunctionType(node: SignatureDeclaration): void { // For a given function symbol "<...>(...) => T" we want to generate a symbol identical // to the one we would get for: { <...>(...): T } // @@ -423,14 +407,16 @@ module ts { // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable // from an actual type literal symbol you would have gotten had you used the long form. - let symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); + let name = getDeclarationName(node); + + let symbol = createSymbol(SymbolFlags.Signature, name); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); bindChildren(node, SymbolFlags.Signature, /*isBlockScopeContainer:*/ false); let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); typeLiteralSymbol.members = {}; - typeLiteralSymbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = symbol + typeLiteralSymbol.members[name] = symbol } function bindAnonymousDeclaration(node: Declaration, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) { @@ -536,7 +522,8 @@ module ts { case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: - bindFunctionOrConstructorType(node); + case SyntaxKind.JSDocFunctionType: + bindFunctionOrConstructorTypeORJSDocFunctionType(node); break; case SyntaxKind.TypeLiteral: @@ -631,9 +618,6 @@ module ts { case SyntaxKind.CaseBlock: bindChildren(node, 0, /*isBlockScopeContainer*/ true); break; - case SyntaxKind.JSDocFunctionType: - bindJSDocFunctionType(node); - break; default: saveParentAndBindChildren(node); } From 9b7cf504e829f562ca93f3710b103f58ef4ed038 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 21:40:46 -0700 Subject: [PATCH 60/96] Simplify binding of JSDocFunctionTypes. --- src/compiler/binder.ts | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 16560e4cd2467..b97dbcff828be 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -131,6 +131,13 @@ module ts { return node.flags & NodeFlags.Default ? "default" : undefined; case SyntaxKind.JSDocFunctionType: return isJSDocConstructSignature(node) ? "__new" : "__call"; + case SyntaxKind.Parameter: + // Parameters with names are handled at the top of this function. Parameters + // without names can only come from JSDocFunctionTypes. + Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); + let functionType = node.parent; + let index = indexOf(functionType.parameters, node); + return "p" + index; } } @@ -323,6 +330,7 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: + case SyntaxKind.JSDocFunctionType: declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes); break; case SyntaxKind.ClassExpression: @@ -639,9 +647,6 @@ module ts { if (isBindingPattern(node.name)) { bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node), /*isBlockScopeContainer*/ false); } - else if (isJavaScriptFile && node.parent.kind === SyntaxKind.JSDocFunctionType) { - bindJSDocFunctionTypeParameter(node); - } else { bindDeclaration(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false); } @@ -657,22 +662,6 @@ module ts { } } - function bindJSDocFunctionTypeParameter(node: ParameterDeclaration) { - let functionType = node.parent; - let isConstructSignature = isJSDocConstructSignature(functionType); - - if (!isConstructSignature || functionType.parameters[0] !== node) { - let index = indexOf(functionType.parameters, node); - let paramName = "p" + index; - let paramSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, paramName); - addDeclarationToSymbol(paramSymbol, node, SymbolFlags.FunctionScopedVariable); - - functionType.locals[paramName] = paramSymbol; - } - - bindChildren(node, SymbolFlags.FunctionScopedVariable, /*isBlockScopeContainer:*/ false); - } - function bindPropertyOrMethodOrAccessor(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { if (hasDynamicName(node)) { bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer); From f261ea941e6da782ab60c681384c30994d46c884 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 21:49:08 -0700 Subject: [PATCH 61/96] Simplify recursion in the binder. Always go through bindChildren. --- src/compiler/binder.ts | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index b97dbcff828be..8463e65f19c3c 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -300,13 +300,6 @@ module ts { } } - function saveParentAndBindChildren(node: Node) { - let saveParent = parent; - parent = node; - forEachChild(node, bind); - parent = saveParent; - } - function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { switch (container.kind) { case SyntaxKind.ModuleDeclaration: @@ -475,9 +468,6 @@ module ts { case SyntaxKind.Parameter: bindParameter(node); break; - case SyntaxKind.VariableStatement: - bindVariableStatement(node); - break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: if (isBindingPattern((node).name)) { @@ -627,20 +617,9 @@ module ts { bindChildren(node, 0, /*isBlockScopeContainer*/ true); break; default: - saveParentAndBindChildren(node); - } - } - - function bindVariableStatement(node: VariableStatement) { - let saveParent = parent; - parent = node; - - if (isJavaScriptFile && node.jsDocComment) { - bindJSDocComment(node); + bindChildren(node, 0, /*isBlockScopeContainer:*/ false); + break; } - - forEachChild(node, bind); - parent = saveParent; } function bindParameter(node: ParameterDeclaration) { From b406d5a2be49dbe17a5367bf6af4df50282a5fec Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 21:56:30 -0700 Subject: [PATCH 62/96] CR feedback. --- src/compiler/parser.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bfbd14cd3e185..b1738b0628e1a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -930,7 +930,14 @@ module ts { function createNode(kind: SyntaxKind, pos?: number): Node { nodeCount++; - return createNodeAtPosition(scanner, kind, pos); + let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); + if (!(pos >= 0)) { + pos = scanner.getStartPos(); + } + + node.pos = pos; + node.end = pos; + return node; } function finishNode(node: T): T { @@ -4943,17 +4950,6 @@ module ts { : undefined); } - function createNodeAtPosition(scanner: Scanner, kind: SyntaxKind, pos?: number): Node { - let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); - if (!(pos >= 0)) { - pos = scanner.getStartPos(); - } - - node.pos = pos; - node.end = pos; - return node; - } - const enum ParsingContext { SourceElements, // Elements in source file ModuleElements, // Elements in module declaration From ad4a172e83ed4898002ce7ee8eb912b76d4b6a37 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 21:59:23 -0700 Subject: [PATCH 63/96] CR feedback. --- src/compiler/scanner.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e01f3390bbd0f..87fe42af06158 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -601,12 +601,23 @@ module ts { /* @internal */ // Creates a scanner over a (possibly unspecified) range of a piece of text. - export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner { - let pos: number; // Current position (end position of text of current token) - let end: number; // end of text - - let startPos: number; // Start position of whitespace before current token - let tokenPos: number; // Start position of text of current token + export function createScanner(languageVersion: ScriptTarget, + skipTrivia: boolean, + text?: string, + onError?: ErrorCallback, + start?: number, + length?: number): Scanner { + // Current position (end position of text of current token) + let pos: number; + + // end of text + let end: number; + + // Start position of whitespace before current token + let startPos: number; + + // Start position of text of current token + let tokenPos: number; let token: SyntaxKind; let tokenValue: string; let precedingLineBreak: boolean; From d4911b7a90de59336cfffda26cc39699cf557fd8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:03:14 -0700 Subject: [PATCH 64/96] CR feedback. --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b1738b0628e1a..c5729bf386864 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5370,7 +5370,7 @@ module ts { let canParseTag = true; let seenAsterisk = true; - for (pos = start + 3; pos < end;) { + for (pos = start + "/**".length; pos < end;) { let ch = content.charCodeAt(pos); pos++; From 72495f8a91bcce280d2b256e7eee0b0031429cb7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:06:12 -0700 Subject: [PATCH 65/96] CR feedback. --- src/compiler/checker.ts | 8 +++----- src/compiler/utilities.ts | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 15d01f22342dd..fb8fced76cab6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2119,9 +2119,7 @@ module ts { function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { // First, see if this node has an @type annotation on it directly. - let sourceFile = getSourceFileOfNode(declaration); let docComment = declaration.jsDocComment; - if (docComment && docComment.type) { return docComment.type; } @@ -2139,7 +2137,7 @@ module ts { else if (declaration.kind === SyntaxKind.Parameter) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. - let parameter = getJSDocParameter(declaration, sourceFile); + let parameter = getJSDocParameter(declaration); if (parameter) { return parameter.type; } @@ -3127,7 +3125,7 @@ module ts { return true; } - let docParam = getJSDocParameter(node, getSourceFile(node)); + let docParam = getJSDocParameter(node); if (docParam) { return docParam.type.kind === SyntaxKind.JSDocVariadicType; } @@ -3143,7 +3141,7 @@ module ts { return true; } - let docParam = getJSDocParameter(node, getSourceFile(node)); + let docParam = getJSDocParameter(node); if (docParam) { return docParam.isBracketed || docParam.type.kind === SyntaxKind.JSDocOptionalType; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index dc6bb3559fcb9..7b8f0fb538e17 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -857,7 +857,7 @@ module ts { node.parameters[0].type.kind === SyntaxKind.JSDocConstructorType; } - export function getJSDocParameter(parameter: ParameterDeclaration, sourceFile: SourceFile): JSDocParameter { + export function getJSDocParameter(parameter: ParameterDeclaration): JSDocParameter { if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. @@ -885,7 +885,7 @@ module ts { return true; } - let parameter = getJSDocParameter(lastParameter, getSourceFileOfNode(lastParameter)); + let parameter = getJSDocParameter(lastParameter); if (parameter) { return parameter.type.kind === SyntaxKind.JSDocVariadicType; } From 0c83e46a16aa4b1516477467badfe82abfc40a59 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:17:21 -0700 Subject: [PATCH 66/96] CR feedback. --- src/compiler/checker.ts | 56 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fb8fced76cab6..b8d3a10438334 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3487,23 +3487,9 @@ module ts { type = unknownType; } else { - type = getDeclaredTypeOfSymbol(symbol); - if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { - let typeParameters = (type).typeParameters; - if (node.typeArguments && node.typeArguments.length === typeParameters.length) { - type = createTypeReference(type, map(node.typeArguments, getTypeFromTypeNodeOrHeritageClauseElement)); - } - else { - error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length); - type = undefined; - } - } - else { - if (node.typeArguments) { - error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); - type = undefined; - } - } + type = createTypeReferenceIfGeneric( + getDeclaredTypeOfSymbol(symbol), + node, node.typeArguments); } } } @@ -3513,6 +3499,27 @@ module ts { return links.resolvedType; } + function createTypeReferenceIfGeneric(type: Type, node: Node, typeArguments: NodeArray): Type { + if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { + let typeParameters = (type).typeParameters; + if (typeArguments && typeArguments.length === typeParameters.length) { + return createTypeReference(type, map(typeArguments, getTypeFromTypeNodeOrHeritageClauseElement)); + } + else { + error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length); + return undefined; + } + } + else { + if (typeArguments) { + error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); + return undefined; + } + } + + return type; + } + function getTypeFromTypeQueryNode(node: TypeQueryNode): Type { let links = getNodeLinks(node); if (!links.resolvedType) { @@ -3773,16 +3780,13 @@ module ts { let symbol = resolveEntityName(node.name, SymbolFlags.Type); if (symbol) { - let type = getDeclaredTypeOfSymbol(symbol); - if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { - let typeParameters = (type).typeParameters; - if (node.typeArguments && node.typeArguments.length === typeParameters.length) { - let typeArguments = map(node.typeArguments, getTypeFromTypeNode); - type = createTypeReference(type, typeArguments); - } - } + let type = createTypeReferenceIfGeneric( + getDeclaredTypeOfSymbol(symbol), + node, node.typeArguments); - return type; + if (type) { + return type; + } } return unknownType; From 05ffaaf288115b9ab192e8be80e8163d8a810faa Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:18:40 -0700 Subject: [PATCH 67/96] CR feedback. --- tests/cases/fourslash/getJavaScriptCompletions5.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/getJavaScriptCompletions5.ts b/tests/cases/fourslash/getJavaScriptCompletions5.ts index 0cd0af6aab75c..d3be06b815fa4 100644 --- a/tests/cases/fourslash/getJavaScriptCompletions5.ts +++ b/tests/cases/fourslash/getJavaScriptCompletions5.ts @@ -9,6 +9,5 @@ ////function foo(a) { } ////foo(1)./**/ -debugger; goTo.marker(); verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From 28c80c320fe04ce4cea550cc9898f0062db34a87 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:24:24 -0700 Subject: [PATCH 68/96] CR feedback. --- src/compiler/checker.ts | 1 - src/compiler/utilities.ts | 27 +++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b8d3a10438334..61bb49faf2905 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3134,7 +3134,6 @@ module ts { return node.dotDotDotToken !== undefined; } - function isOptional(node: ParameterDeclaration) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { if (node.type && node.type.kind === SyntaxKind.JSDocOptionalType) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7b8f0fb538e17..09b65f565f359 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -875,23 +875,26 @@ module ts { } export function hasRestParameters(s: SignatureDeclaration): boolean { - let lastParameter = lastOrUndefined(s.parameters); - if (!lastParameter) { - return false; - } + return isVariadic(lastOrUndefined(s.parameters)); + } - if (s.parserContextFlags & ParserContextFlags.JavaScriptFile) { - if (lastParameter.type && lastParameter.type.kind === SyntaxKind.JSDocVariadicType) { - return true; - } + function isVariadic(node: ParameterDeclaration) { + if (node) { + if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { + return true; + } - let parameter = getJSDocParameter(lastParameter); - if (parameter) { - return parameter.type.kind === SyntaxKind.JSDocVariadicType; + let docParam = getJSDocParameter(node); + if (docParam) { + return docParam.type.kind === SyntaxKind.JSDocVariadicType; + } } + + return node.dotDotDotToken !== undefined; } - return lastParameter.dotDotDotToken !== undefined; + return false; } export function isLiteralKind(kind: SyntaxKind): boolean { From c92c63b273caf33bb1779a63a529bcfa685a9a05 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:29:57 -0700 Subject: [PATCH 69/96] CR feedback. --- src/compiler/checker.ts | 33 +++++++++------------------------ src/compiler/emitter.ts | 4 ++-- src/compiler/utilities.ts | 6 +++--- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 61bb49faf2905..d013e98068feb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1739,11 +1739,11 @@ module ts { function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { let parameterNode = p.valueDeclaration; - if (isVariadic(parameterNode)) { + if (isRestParameter(parameterNode)) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); - if (isOptional(parameterNode)) { + if (isOptionalParameter(parameterNode)) { writePunctuation(writer, SyntaxKind.QuestionToken); } writePunctuation(writer, SyntaxKind.ColonToken); @@ -3115,26 +3115,11 @@ module ts { return result; } - function isVariadicOrOptional(node: ParameterDeclaration) { - return isVariadic(node) || isOptional(node); + function isRestOrOptionalParameter(node: ParameterDeclaration) { + return isRestParameter(node) || isOptionalParameter(node); } - function isVariadic(node: ParameterDeclaration) { - if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { - if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { - return true; - } - - let docParam = getJSDocParameter(node); - if (docParam) { - return docParam.type.kind === SyntaxKind.JSDocVariadicType; - } - } - - return node.dotDotDotToken !== undefined; - } - - function isOptional(node: ParameterDeclaration) { + function isOptionalParameter(node: ParameterDeclaration) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { if (node.type && node.type.kind === SyntaxKind.JSDocOptionalType) { return true; @@ -3168,7 +3153,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (isVariadicOrOptional(param)) { + if (isRestOrOptionalParameter(param)) { minArgumentCount = i; } } @@ -3205,7 +3190,7 @@ module ts { } links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, - minArgumentCount, hasRestParameters(declaration), hasStringLiterals); + minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; } @@ -5849,7 +5834,7 @@ module ts { let contextualSignature = getContextualSignature(func); if (contextualSignature) { - let funcHasRestParameters = hasRestParameters(func); + let funcHasRestParameters = hasRestParameter(func); let len = func.parameters.length - (funcHasRestParameters ? 1 : 0); let indexOfParameter = indexOf(func.parameters, parameter); if (indexOfParameter < len) { @@ -9177,7 +9162,7 @@ module ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (!hasRestParameters(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { + if (!hasRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { return; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ac8c2f828f2d0..a48f6792ee9f1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2887,7 +2887,7 @@ var __param = this.__param || function(index, decorator) { return function (targ } function emitRestParameter(node: FunctionLikeDeclaration) { - if (languageVersion < ScriptTarget.ES6 && hasRestParameters(node)) { + if (languageVersion < ScriptTarget.ES6 && hasRestParameter(node)) { let restIndex = node.parameters.length - 1; let restParam = node.parameters[restIndex]; @@ -3015,7 +3015,7 @@ var __param = this.__param || function(index, decorator) { return function (targ write("("); if (node) { let parameters = node.parameters; - let omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameters(node) ? 1 : 0; + let omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameter(node) ? 1 : 0; emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false); } write(")"); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 09b65f565f359..f008797a11823 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -874,11 +874,11 @@ module ts { } } - export function hasRestParameters(s: SignatureDeclaration): boolean { - return isVariadic(lastOrUndefined(s.parameters)); + export function hasRestParameter(s: SignatureDeclaration): boolean { + return isRestParameter(lastOrUndefined(s.parameters)); } - function isVariadic(node: ParameterDeclaration) { + export function isRestParameter(node: ParameterDeclaration) { if (node) { if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { From 6f2d1b7cb552b3aa476b464037c4c60c892b83f0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:30:38 -0700 Subject: [PATCH 70/96] CR feedback. --- tests/cases/fourslash/getJavaScriptCompletions6.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/getJavaScriptCompletions6.ts b/tests/cases/fourslash/getJavaScriptCompletions6.ts index efbc208838338..9f9a42b5762c2 100644 --- a/tests/cases/fourslash/getJavaScriptCompletions6.ts +++ b/tests/cases/fourslash/getJavaScriptCompletions6.ts @@ -9,6 +9,5 @@ //// a./**/ ////} -debugger; goTo.marker(); verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From 7f28fd27a0af0738cc70844f3966a40571ddb3f1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 22:35:18 -0700 Subject: [PATCH 71/96] CR feedback. --- src/services/services.ts | 4 ---- .../fourslash/getJavaScriptSemanticDiagnostics22.ts | 10 +--------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 3b5db53553891..0f27bdc4f003d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2610,10 +2610,6 @@ module ts { diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); return true; } - if (parameter.dotDotDotToken) { - diagnostics.push(createDiagnosticForNode(parameter.dotDotDotToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "...")); - return true; - } if (parameter.type) { diagnostics.push(createDiagnosticForNode(parameter.type, Diagnostics.types_can_only_be_used_in_a_ts_file)); return true; diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts index 8ad0d57922b3e..c3ab5af2c2046 100644 --- a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts +++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics22.ts @@ -4,12 +4,4 @@ // @Filename: a.js //// function foo(...a) {} -verify.getSemanticDiagnostics(`[ - { - "message": "'...' can only be used in a .ts file.", - "start": 13, - "length": 3, - "category": "error", - "code": 8009 - } -]`); \ No newline at end of file +verify.getSemanticDiagnostics(`[]`); \ No newline at end of file From a33f703fce0f2f267dd1b11244e46e3c3b5c5b21 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:06:01 -0700 Subject: [PATCH 72/96] CR feedback. --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 10 +++++----- src/compiler/utilities.ts | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8463e65f19c3c..817cd4f4fb4ce 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -130,7 +130,7 @@ module ts { case SyntaxKind.ClassDeclaration: return node.flags & NodeFlags.Default ? "default" : undefined; case SyntaxKind.JSDocFunctionType: - return isJSDocConstructSignature(node) ? "__new" : "__call"; + return isJSDocConstructSignature(node) ? "__new" : "__call"; case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1731ef815caea..c3773fc5b8268 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3146,6 +3146,9 @@ module ts { let typeParameters = classType ? classType.typeParameters : getTypeParametersFromSignatureDeclaration(declaration); let isJSConstructSignature = isJSDocConstructSignature(declaration); + // If this is a JSDoc construct signature, then skip the first parameter in the + // parameter list. The first parameter represents the return type of the construct + // signature. for (let i = isJSConstructSignature ? 1 : 0, n = declaration.parameters.length; i < n; i++) { let param = declaration.parameters[i]; parameters.push(param.symbol); @@ -3165,14 +3168,11 @@ module ts { if (isJSConstructSignature) { minArgumentCount--; + returnType = getTypeFromTypeNode(declaration.parameters[0].type); } - - if (classType) { + else if (classType) { returnType = classType; } - else if (isJSConstructSignature) { - returnType = getTypeFromTypeNode(declaration.parameters[0].type); - } else if (declaration.type) { returnType = getTypeFromTypeNode(declaration.type); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f008797a11823..58548829cdb26 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -851,10 +851,10 @@ module ts { return false; } - export function isJSDocConstructSignature(node: SignatureDeclaration) { + export function isJSDocConstructSignature(node: Node) { return node.kind === SyntaxKind.JSDocFunctionType && - node.parameters.length > 0 && - node.parameters[0].type.kind === SyntaxKind.JSDocConstructorType; + (node).parameters.length > 0 && + (node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType; } export function getJSDocParameter(parameter: ParameterDeclaration): JSDocParameter { From 48a703b379d1d320d9b3085e0981b00477773b49 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:09:04 -0700 Subject: [PATCH 73/96] CR feedback. --- src/compiler/parser.ts | 5 ++--- src/compiler/types.ts | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c5729bf386864..1f070d1028c58 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5355,7 +5355,6 @@ module ts { let parameters: JSDocParameter[]; let returnType: JSDocType; let typeParameters: TypeParameterDeclaration[]; - // let tagCounts: Map; let pos: number; @@ -5417,11 +5416,11 @@ module ts { return createJSDocComment(); function createJSDocComment(): JSDocComment { - if (!returnType && !type && !parameters && !typeParameters/* && !tagCounts*/) { + if (!returnType && !type && !parameters && !typeParameters) { return undefined; } - return { returnType, type, parameters, typeParameters/*, tagCounts */ }; + return { returnType, type, parameters, typeParameters }; } function skipWhitespace(): void { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index df9454fd89e71..342fa0bbcc934 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1100,7 +1100,6 @@ module ts { parameters?: JSDocParameter[]; returnType?: JSDocType; typeParameters?: TypeParameterDeclaration[]; - // tagCounts?: Map } // Source files are declarations when they are external modules. From 6157ac728e10281492bbcb7292ae2f775a508286 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:12:17 -0700 Subject: [PATCH 74/96] CR feedback. --- src/compiler/parser.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1f070d1028c58..c0bd123808a56 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5685,8 +5685,14 @@ module ts { // Ditch any existing LS children we may have created. This way we can avoid // moving them forward. - node._children = undefined; - node.jsDocComment = undefined; + if (node._children) { + node._children = undefined; + } + + if (node.jsDocComment) { + node.jsDocComment = undefined; + } + node.pos += delta; node.end += delta; From 01143cf0b5b3bd30ba350fcb56a30d142719f3b7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:12:53 -0700 Subject: [PATCH 75/96] CR feedback. --- tests/cases/fourslash/getJavaScriptQuickInfo1.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo1.ts b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts index 9a9fa4f622244..71072f1699aa2 100644 --- a/tests/cases/fourslash/getJavaScriptQuickInfo1.ts +++ b/tests/cases/fourslash/getJavaScriptQuickInfo1.ts @@ -5,6 +5,5 @@ /////** @type {function(new:string,number)} */ ////var /**/v; -debugger; goTo.marker(); verify.quickInfoIs('var v: new (p1: number) => string'); \ No newline at end of file From de5e13c21a3d4c2346c80512a1d976dd3a2db611 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:18:57 -0700 Subject: [PATCH 76/96] CR feedback. --- src/compiler/checker.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c3773fc5b8268..e7a81c6edc886 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3077,16 +3077,6 @@ module ts { return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind); } - function symbolsToArray(symbols: SymbolTable): Symbol[] { - let result: Symbol[] = []; - for (let id in symbols) { - if (!isReservedMemberName(id)) { - result.push(symbols[id]); - } - } - return result; - } - function getTypeParametersFromSignatureDeclaration(declaration: SignatureDeclaration): TypeParameter[] { if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { let jsDocComment = declaration.jsDocComment; @@ -3115,6 +3105,16 @@ module ts { return result; } + function symbolsToArray(symbols: SymbolTable): Symbol[] { + let result: Symbol[] = []; + for (let id in symbols) { + if (!isReservedMemberName(id)) { + result.push(symbols[id]); + } + } + return result; + } + function isRestOrOptionalParameter(node: ParameterDeclaration) { return isRestParameter(node) || isOptionalParameter(node); } From 92f696d8b97423fa8fa9d80c8a30d5c0f3795e01 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 16 Apr 2015 23:54:50 -0700 Subject: [PATCH 77/96] CR feedback. --- src/compiler/utilities.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 58548829cdb26..a3589220296c3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -312,9 +312,9 @@ module ts { return getSpanOfTokenAtPosition(sourceFile, node.pos); } - let pos = !nodeIsMissing(errorNode) - ? skipTrivia(sourceFile.text, errorNode.pos) - : errorNode.pos; + let pos = nodeIsMissing(errorNode) + ? errorNode.pos + : skipTrivia(sourceFile.text, errorNode.pos); return createTextSpanFromBounds(pos, errorNode.end); } From 64b9792e7a3cae58db2ac25f19477b3a6388255f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 17 Apr 2015 14:24:51 -0700 Subject: [PATCH 78/96] Remove code. --- src/compiler/scanner.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index f51aead7e6cf9..9b39fcfe8db52 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -7,11 +7,6 @@ module ts { (message: DiagnosticMessage, length: number): void; } - export enum ScannerType { - TypeScript, - JSDocComment, - } - /* @internal */ export interface Scanner { getStartPos(): number; From d76f415ac95d7a738c43e356f9446cc7712e4a48 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 19 Apr 2015 17:51:42 -0700 Subject: [PATCH 79/96] Type JSDocRecordMembers to look like PropertyDeclarations. --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8f1d306973481..c876da902dfd5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1084,7 +1084,7 @@ module ts { type: JSDocType; } - export interface JSDocRecordMember extends Node { + export interface JSDocRecordMember extends PropertyDeclaration { name: Identifier | LiteralExpression, type?: JSDocType } From 316d25c1e6e6dbc6afcd21298ffd6e8592eb611a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 19 Apr 2015 18:22:07 -0700 Subject: [PATCH 80/96] Add support for object literals in JSDoc comments. --- src/compiler/binder.ts | 5 ++++- src/compiler/checker.ts | 7 ++++++- src/compiler/types.ts | 2 +- tests/cases/fourslash/getJavaScriptQuickInfo5.ts | 10 ++++++++++ tests/cases/fourslash/getQuickInfo5.ts | 7 +++++++ 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo5.ts create mode 100644 tests/cases/fourslash/getQuickInfo5.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 817cd4f4fb4ce..310813f0b486d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -335,6 +335,7 @@ module ts { case SyntaxKind.TypeLiteral: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.JSDocRecordType: declareSymbol(container.symbol.members, container.symbol, node, symbolKind, symbolExcludes); break; case SyntaxKind.EnumDeclaration: @@ -482,6 +483,7 @@ module ts { break; case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: + case SyntaxKind.JSDocRecordMember: bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property | ((node).questionToken ? SymbolFlags.Optional : 0), SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false); break; case SyntaxKind.PropertyAssignment: @@ -523,8 +525,9 @@ module ts { case SyntaxKind.JSDocFunctionType: bindFunctionOrConstructorTypeORJSDocFunctionType(node); break; - + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocRecordType: bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type", /*isBlockScopeContainer*/ false); break; case SyntaxKind.ObjectLiteralExpression: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da51cdac8e026..335da127aca4a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3773,6 +3773,10 @@ module ts { return createObjectType(TypeFlags.Anonymous, node.symbol); } + function getTypeFromJSDocRecordType(node: JSDocRecordType): Type { + return createObjectType(TypeFlags.Anonymous, node.symbol); + } + function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { let type = getTypeFromTypeNode(node.type); if (type) { @@ -3883,8 +3887,9 @@ module ts { return getTypeFromJSDocVariadicType(node); case SyntaxKind.JSDocConstructorType: return getTypeFromTypeNode((node).type); - case SyntaxKind.JSDocThisType: case SyntaxKind.JSDocRecordType: + return getTypeFromJSDocRecordType(node); + case SyntaxKind.JSDocThisType: // NYI: } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c876da902dfd5..ee6465fd6f2e9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1054,7 +1054,7 @@ module ts { type: JSDocType; } - export interface JSDocRecordType extends JSDocType { + export interface JSDocRecordType extends JSDocType, TypeLiteralNode { members: NodeArray; } diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo5.ts b/tests/cases/fourslash/getJavaScriptQuickInfo5.ts new file mode 100644 index 0000000000000..12dd37834bc64 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo5.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @param {{b:number}} [a] */ +////function /**/f(a) { } + +debugger; +goTo.marker(); +verify.quickInfoIs('function f(a?: {\n b: number;\n}): void'); \ No newline at end of file diff --git a/tests/cases/fourslash/getQuickInfo5.ts b/tests/cases/fourslash/getQuickInfo5.ts new file mode 100644 index 0000000000000..509e9fd139561 --- /dev/null +++ b/tests/cases/fourslash/getQuickInfo5.ts @@ -0,0 +1,7 @@ +/// + +////function /**/f(a: {b: number}) { } + +debugger; +goTo.marker(); +verify.quickInfoIs('function f(a: {\n b: number;\n}): void'); \ No newline at end of file From 548aa852af3199296d46be83b7315ae32ccdf72e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 19 Apr 2015 18:38:23 -0700 Subject: [PATCH 81/96] Add support for 'this-types' from JSDoc comments. --- src/compiler/checker.ts | 20 ++++++++++++++++++- .../fourslash/getJavaScriptCompletions10.ts | 11 ++++++++++ .../fourslash/getJavaScriptQuickInfo6.ts | 10 ++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions10.ts create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 335da127aca4a..0a6fbce09fa63 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3890,7 +3890,7 @@ module ts { case SyntaxKind.JSDocRecordType: return getTypeFromJSDocRecordType(node); case SyntaxKind.JSDocThisType: - // NYI: + return getTypeFromTypeNode((node).type); } return unknownType; @@ -5743,9 +5743,27 @@ module ts { let symbol = getSymbolOfNode(classNode); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol); } + + if (container.parserContextFlags & ParserContextFlags.JavaScriptFile) { + let type = getTypeForThisExpressionFromJSDoc(container); + if (type && type !== unknownType) { + return type; + } + } + return anyType; } + function getTypeForThisExpressionFromJSDoc(node: Node) { + var jsDocComment = node.jsDocComment; + if (jsDocComment && jsDocComment.type && jsDocComment.type.kind === SyntaxKind.JSDocFunctionType) { + let jsDocFunctionType = jsDocComment.type; + if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) { + return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type); + } + } + } + function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean { for (let n = node; n && n !== constructorDecl; n = n.parent) { if (n.kind === SyntaxKind.Parameter) { diff --git a/tests/cases/fourslash/getJavaScriptCompletions10.ts b/tests/cases/fourslash/getJavaScriptCompletions10.ts new file mode 100644 index 0000000000000..5fbd91e89881a --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions10.ts @@ -0,0 +1,11 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** +//// * @type {function(this:number)} +//// */ +////function f() { this./**/ } + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo6.ts b/tests/cases/fourslash/getJavaScriptQuickInfo6.ts new file mode 100644 index 0000000000000..2d23752fa636c --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo6.ts @@ -0,0 +1,10 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {function(this:number)} */ +////function f() { /**/this } + +debugger; +goTo.marker(); +verify.quickInfoIs('number'); \ No newline at end of file From 393eaa184374cfa385e1f8c7de5f82c523025f36 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 23 Apr 2015 16:12:41 -0700 Subject: [PATCH 82/96] Get all members of the types of a union type for javascript completions. --- src/services/services.ts | 21 +++++++++++++++++-- .../fourslash/getJavaScriptCompletions11.ts | 11 ++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/getJavaScriptCompletions11.ts diff --git a/src/services/services.ts b/src/services/services.ts index 0f27bdc4f003d..ad18283713b68 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2741,6 +2741,7 @@ module ts { let typeChecker = program.getTypeChecker(); let syntacticStart = new Date().getTime(); let sourceFile = getValidSourceFile(fileName); + let isJavaScriptFile = isJavaScript(fileName); let start = new Date().getTime(); let currentToken = getTokenAtPosition(sourceFile, position); @@ -2841,13 +2842,29 @@ module ts { } let type = typeChecker.getTypeAtLocation(node); + addTypeProperties(type); + } + + function addTypeProperties(type: Type) { if (type) { // Filter private properties - forEach(type.getApparentProperties(), symbol => { + for (let symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } - }); + } + + if (isJavaScriptFile && type.flags & TypeFlags.Union) { + // In javascript files, for union types, we don't just get the members that + // the individual types have in common, we also include all the members that + // each individual type has. This is because we're going to add all identifiers + // anyways. So we might as well elevate the members that were at least part + // of the individual types to a higher status than since we know what they are. + let unionType = type; + for (let elementType of unionType.types) { + addTypeProperties(elementType); + } + } } } diff --git a/tests/cases/fourslash/getJavaScriptCompletions11.ts b/tests/cases/fourslash/getJavaScriptCompletions11.ts new file mode 100644 index 0000000000000..f12f53fa960fe --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptCompletions11.ts @@ -0,0 +1,11 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +/////** @type {number|string} */ +////var v; +////v./**/ + +goTo.marker(); +verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); +verify.completionListContains("charCodeAt", /*displayText:*/ undefined, /*documentation*/ undefined, "method"); \ No newline at end of file From f1d1a6680a0ee075b3aefbf3c61c365e549dad0a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Apr 2015 16:06:37 -0700 Subject: [PATCH 83/96] PR feedback. --- src/compiler/parser.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a66692fbb8912..83ad93f3aeb48 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5038,7 +5038,6 @@ module ts { function setError(message: DiagnosticMessage) { parseErrorAtCurrentToken(message); - // error = true; if (throwOnJSDocErrors) { throw new Error(message.key); } @@ -5097,10 +5096,6 @@ module ts { return type; } - //return parseJSDocTypeReference(); - - //} - function parseBasicTypeExpression(): JSDocType { switch (token) { case SyntaxKind.AsteriskToken: From 43c17963638335bfa941146502f4e9a38289ccd7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Apr 2015 16:13:38 -0700 Subject: [PATCH 84/96] Rename type. --- src/compiler/parser.ts | 14 +++++++------- src/compiler/types.ts | 4 ++-- tests/cases/unittests/jsDocParsing.ts | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 83ad93f3aeb48..6c50251738938 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -374,8 +374,8 @@ module ts { /* @internal */ // Exposed only for testing. - export function parseJSDocComment(content: string, start?: number, length?: number) { - return Parser.JSDocParser.parseJSDocCommentForTests(content, start, length); + export function parseJSDocCommentInfo(content: string, start?: number, length?: number) { + return Parser.JSDocParser.parseJSDocCommentInfoForTests(content, start, length); } /* @internal */ @@ -578,7 +578,7 @@ module ts { let comments = getLeadingCommentRangesOfNode(node, sourceFile); if (comments) { for (let comment of comments) { - let jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); + let jsDocComment = JSDocParser.parseJSDocCommentInfo(node, comment.pos, comment.end - comment.pos); if (jsDocComment) { node.jsDocComment = jsDocComment; } @@ -5328,16 +5328,16 @@ module ts { } } - export function parseJSDocCommentForTests(content: string, start: number, length: number) { + export function parseJSDocCommentInfoForTests(content: string, start: number, length: number) { initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined); - let jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); + let jsDocComment = parseJSDocCommentInfo(/*parent:*/ undefined, start, length); let diagnostics = parseDiagnostics; clearState(); return jsDocComment ? { jsDocComment, diagnostics } : undefined; } - export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment { + export function parseJSDocCommentInfo(parent: Node, start: number, length: number): JSDocCommentInfo { let content = sourceText; start = start || 0; let end = length === undefined ? content.length : start + length; @@ -5411,7 +5411,7 @@ module ts { return createJSDocComment(); - function createJSDocComment(): JSDocComment { + function createJSDocComment(): JSDocCommentInfo { if (!returnType && !type && !parameters && !typeParameters) { return undefined; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0d8b2256ec166..74f043a312e5b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -399,7 +399,7 @@ module ts { modifiers?: ModifiersArray; // Array of modifiers /* @internal */ id?: number; // Unique id (used to look up NodeLinks) parent?: Node; // Parent node (initialized by binding - /* @internal */ jsDocComment?: JSDocComment; // JSDoc for the node, if it has any. Only for .js files. + /* @internal */ jsDocComment?: JSDocCommentInfo; // JSDoc for the node, if it has any. Only for .js files. /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) @@ -1095,7 +1095,7 @@ module ts { isBracketed: boolean; } - export interface JSDocComment { + export interface JSDocCommentInfo { type?: JSDocType; parameters?: JSDocParameter[]; returnType?: JSDocType; diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 0a08c106fc070..5cfa1dd968f35 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1190,7 +1190,7 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = ts.parseJSDocComment(content); + let comment = ts.parseJSDocCommentInfo(content); Debug.assert(comment && comment.diagnostics.length === 0); let result = JSON.stringify(comment.jsDocComment, (k, v) => { @@ -1202,7 +1202,7 @@ module ts { } function parsesIncorrectly(content: string) { - let type = ts.parseJSDocComment(content); + let type = ts.parseJSDocCommentInfo(content); assert.isTrue(!type || type.diagnostics.length > 0); } From b16be6c1f07e706c3272aeed2c39bff3485340d1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Apr 2015 17:22:47 -0700 Subject: [PATCH 85/96] Represent jsdoc comments in the tree as an actual node. --- src/compiler/parser.ts | 219 ++++++++++++++++++++++++++++++----------- src/compiler/types.ts | 33 +++++++ 2 files changed, 194 insertions(+), 58 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6c50251738938..5e05405aea1bb 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -940,8 +940,8 @@ module ts { return node; } - function finishNode(node: T): T { - node.end = scanner.getStartPos(); + function finishNode(node: T, end?: number): T { + node.end = end === undefined ? scanner.getStartPos() : end; if (contextFlags) { node.parserContextFlags = contextFlags; @@ -5338,6 +5338,55 @@ module ts { } export function parseJSDocCommentInfo(parent: Node, start: number, length: number): JSDocCommentInfo { + let docComment = parseJSDocComment(parent, start, length); + if (!docComment) { + return undefined; + } + + let result = {}; + + let typeTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTypeTag ? t : undefined); + let parameterTags = filter(docComment.tags, t => t.kind === SyntaxKind.JSDocParameterTag); + let returnTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocReturnTag ? t : undefined); + let templateTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTemplateTag ? t : undefined); + + if (!typeTag && parameterTags.length === 0 && !returnTag && !templateTag) { + return undefined; + } + + if (typeTag) { + result.type = typeTag.typeExpression.type; + } + + if (parameterTags.length > 0) { + result.parameters = map(parameterTags, t => { + let paramTag = t; + return { name: paramTag.parameterName.text, type: paramTag.parameterTypeExpression.type, isBracketed: paramTag.isBracketed } + }); + } + + if (returnTag) { + result.returnType = returnTag.typeExpression.type; + } + + if (templateTag) { + result.typeParameters = templateTag.typeParameters; + } + + return result; + } + + export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment { + let comment = parseJSDocCommentWorker(start, length); + if (comment) { + fixupParentReferences(comment); + comment.parent = parent; + } + + return comment; + } + + export function parseJSDocCommentWorker(start: number, length: number): JSDocComment { let content = sourceText; start = start || 0; let end = length === undefined ? content.length : start + length; @@ -5347,13 +5396,14 @@ module ts { Debug.assert(start <= end); Debug.assert(end <= content.length); - let type: JSDocType; - let parameters: JSDocParameter[]; - let returnType: JSDocType; - let typeParameters: TypeParameterDeclaration[]; - + let tags: NodeArray; let pos: number; - + + // NOTE(cyrusn): This is essentially a handwritten scanner for JSDocComments. I + // considered using an actual Scanner, but this would complicate things. The + // scanner would need to know it was in a Doc Comment. Otherwise, it would then + // produce comments *inside* the doc comment. In the end it was just easier to + // write a simple scanner rather than go that route. if (length >= "/** */".length) { if (content.charCodeAt(start) === CharacterCodes.slash && content.charCodeAt(start + 1) === CharacterCodes.asterisk && @@ -5411,12 +5461,14 @@ module ts { return createJSDocComment(); - function createJSDocComment(): JSDocCommentInfo { - if (!returnType && !type && !parameters && !typeParameters) { + function createJSDocComment(): JSDocComment { + if (!tags) { return undefined; } - return { returnType, type, parameters, typeParameters }; + let result = createNode(SyntaxKind.JSDocComment, start); + result.tags = tags; + return finishNode(result, end); } function skipWhitespace(): void { @@ -5427,25 +5479,57 @@ module ts { function parseTag(): void { Debug.assert(content.charCodeAt(pos - 1) === CharacterCodes.at); + let atToken = createNode(SyntaxKind.AtToken, pos - 1); + atToken.end = pos; let startPos = pos; let tagName = scanIdentifier(); + if (!tagName) { + return; + } + + let tag = handleTag(atToken, tagName) || handleUnknownTag(atToken, tagName); + addTag(tag); + } + + function handleTag(atToken: Node, tagName: Identifier): JSDocTag { if (tagName) { - switch (tagName) { + switch (tagName.text) { case "param": - return handleParamTag(); + return handleParamTag(atToken, tagName); case "return": case "returns": - return handleReturnTag(tagName, startPos); + return handleReturnTag(atToken, tagName); case "template": - return handleTemplateTag(tagName, startPos); + return handleTemplateTag(atToken, tagName); case "type": - return handleTypeTag(tagName, startPos); + return handleTypeTag(atToken, tagName); + } + } + + return undefined; + } + + function handleUnknownTag(atToken: Node, tagName: Identifier) { + let result = createNode(SyntaxKind.JSDocTag, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + return finishNode(result, pos); + } + + function addTag(tag: JSDocTag): void { + if (tag) { + if (!tags) { + tags = >[]; + tags.pos = tag.pos; } + + tags.push(tag); + tags.end = tag.end; } } - function parseType(): JSDocType { + function parseTypeExpression(): JSDocTypeExpression { skipWhitespace(); if (content.charCodeAt(pos) !== CharacterCodes.openBrace) { @@ -5457,24 +5541,23 @@ module ts { return undefined; } - typeExpression.parent = parent; pos = typeExpression.end; - return typeExpression.type; + return typeExpression; } - function handleParamTag() { + function handleParamTag(atToken: Node, tagName: Identifier) { skipWhitespace(); - let type: JSDocType; + let typeExpression: JSDocTypeExpression; if (content.charCodeAt(pos) === CharacterCodes.openBrace) { - type = parseType(); - if (!type) { + typeExpression = parseTypeExpression(); + if (!typeExpression) { return; } } skipWhitespace(); - let name: string; + let name: Identifier; let isBracketed: boolean; if (content.charCodeAt(pos) === CharacterCodes.openBracket) { pos++; @@ -5490,42 +5573,59 @@ module ts { return; } - if (!type) { - type = parseType(); - if (!type) { + if (!typeExpression) { + typeExpression = parseTypeExpression(); + if (!typeExpression) { return; } } - parameters = parameters || []; - parameters.push({ name, type, isBracketed }); + let result = createNode(SyntaxKind.JSDocParameterTag, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.parameterName = name; + result.parameterTypeExpression = typeExpression; + result.isBracketed = isBracketed; + return finishNode(result, pos); } - function handleReturnTag(tag: string, startPos: number): void { - if (returnType) { - parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); - return; + function handleReturnTag(atToken: Node, tagName: Identifier): JSDocReturnTag { + if (forEach(tags, t => t.kind === SyntaxKind.JSDocReturnTag)) { + parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text); + } + + let typeExpression = parseTypeExpression(); + if (!typeExpression) { + return undefined; } - returnType = parseType(); + let result = createNode(SyntaxKind.JSDocReturnTag, atToken.pos); + result.typeExpression = typeExpression; + return finishNode(result, pos); } - function handleTypeTag(tag: string, startPos: number): void { - if (type) { - parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); - return; + function handleTypeTag(atToken: Node, tagName: Identifier): JSDocTypeTag { + if (forEach(tags, t => t.kind === SyntaxKind.JSDocTypeTag)) { + parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text); + } + + let typeExpression = parseTypeExpression(); + if (!typeExpression) { + return undefined; } - type = parseType(); + let result = createNode(SyntaxKind.JSDocTypeTag, atToken.pos); + result.typeExpression = typeExpression; + return finishNode(result, pos); } - function handleTemplateTag(tag: string, startPos: number): void { - if (typeParameters) { - parseErrorAtPosition(startPos, pos - startPos, Diagnostics._0_tag_already_specified, tag); - return; + function handleTemplateTag(atToken: Node, tagName: Identifier): JSDocTemplateTag { + if (forEach(tags, t => t.kind === SyntaxKind.JSDocTemplateTag)) { + parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text); } - typeParameters = []; + let typeParameters = >[]; + //typeParameters.pos = pos; while (true) { skipWhitespace(); @@ -5534,32 +5634,33 @@ module ts { let name = scanIdentifier(); if (!name) { parseErrorAtPosition(startPos, 0, Diagnostics.Identifier_expected); - return; + return undefined; } - let identifier = createNode(SyntaxKind.Identifier); - let typeParameter = createNode(SyntaxKind.TypeParameter); - - identifier.text = name; - typeParameter.name = identifier; - - identifier.pos = typeParameter.pos = startPos; - identifier.end = typeParameter.end = pos; + let typeParameter = createNode(SyntaxKind.TypeParameter, name.pos); + typeParameter.name = name; + finishNode(typeParameter, pos); - Parser.fixupParentReferences(typeParameter); - typeParameter.parent = parent; typeParameters.push(typeParameter); skipWhitespace(); if (content.charCodeAt(pos) !== CharacterCodes.comma) { - return; + break; } pos++; } + + //typeParameters.end = pos; + + let result = createNode(SyntaxKind.JSDocTemplateTag, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.typeParameters = typeParameters; + return finishNode(result, pos); } - function scanIdentifier(): string { + function scanIdentifier(): Identifier { let startPos = pos; for (; pos < end; pos++) { let ch = content.charCodeAt(pos); @@ -5577,7 +5678,9 @@ module ts { return undefined; } - return content.substring(startPos, pos); + let result = createNode(SyntaxKind.Identifier, startPos); + result.text = content.substring(startPos, pos); + return finishNode(result, pos); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 74f043a312e5b..47aa1e403f61f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -288,6 +288,12 @@ module ts { JSDocVariadicType, JSDocConstructorType, JSDocThisType, + JSDocComment, + JSDocTag, + JSDocParameterTag, + JSDocReturnTag, + JSDocTypeTag, + JSDocTemplateTag, // Synthesized list SyntaxList, @@ -1095,6 +1101,33 @@ module ts { isBracketed: boolean; } + export interface JSDocComment extends Node { + tags: NodeArray; + } + + export interface JSDocTag extends Node { + atToken: Node; + tagName: Identifier; + } + + export interface JSDocTemplateTag extends JSDocTag { + typeParameters: NodeArray; + } + + export interface JSDocReturnTag extends JSDocTag { + typeExpression: JSDocTypeExpression; + } + + export interface JSDocTypeTag extends JSDocTag { + typeExpression: JSDocTypeExpression; + } + + export interface JSDocParameterTag extends JSDocTag { + parameterTypeExpression: JSDocTypeExpression; + parameterName: Identifier; + isBracketed: boolean; + } + export interface JSDocCommentInfo { type?: JSDocType; parameters?: JSDocParameter[]; From fea14857e2b00ae83ed20c750b24999fc549595f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Apr 2015 17:26:22 -0700 Subject: [PATCH 86/96] Properly set pos/end on template tags. --- src/compiler/parser.ts | 4 +- tests/cases/unittests/jsDocParsing.ts | 76 +++++++++++++++++---------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5e05405aea1bb..b5081c72ac8e7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5625,7 +5625,7 @@ module ts { } let typeParameters = >[]; - //typeParameters.pos = pos; + typeParameters.pos = pos; while (true) { skipWhitespace(); @@ -5651,7 +5651,7 @@ module ts { pos++; } - //typeParameters.end = pos; + typeParameters.end = pos; let result = createNode(SyntaxKind.JSDocTemplateTag, atToken.pos); result.atToken = atToken; diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 5cfa1dd968f35..8483521ebb793 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -1644,8 +1644,8 @@ module ts { * @template T */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1655,8 +1655,11 @@ module ts { "end": 19, "text": "T" } - } - ] + }, + "length": 1, + "pos": 17, + "end": 19 + } }`); }); @@ -1666,8 +1669,8 @@ module ts { * @template K,V */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1678,7 +1681,7 @@ module ts { "text": "K" } }, - { + "1": { "kind": "TypeParameter", "pos": 20, "end": 21, @@ -1688,8 +1691,11 @@ module ts { "end": 21, "text": "V" } - } - ] + }, + "length": 2, + "pos": 17, + "end": 21 + } }`); }); @@ -1699,8 +1705,8 @@ module ts { * @template K ,V */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1711,7 +1717,7 @@ module ts { "text": "K" } }, - { + "1": { "kind": "TypeParameter", "pos": 21, "end": 22, @@ -1721,8 +1727,11 @@ module ts { "end": 22, "text": "V" } - } - ] + }, + "length": 2, + "pos": 17, + "end": 22 + } }`); }); @@ -1732,8 +1741,8 @@ module ts { * @template K, V */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1744,7 +1753,7 @@ module ts { "text": "K" } }, - { + "1": { "kind": "TypeParameter", "pos": 21, "end": 22, @@ -1754,8 +1763,11 @@ module ts { "end": 22, "text": "V" } - } - ] + }, + "length": 2, + "pos": 17, + "end": 22 + } }`); }); @@ -1765,8 +1777,8 @@ module ts { * @template K , V */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1777,7 +1789,7 @@ module ts { "text": "K" } }, - { + "1": { "kind": "TypeParameter", "pos": 22, "end": 23, @@ -1787,8 +1799,11 @@ module ts { "end": 23, "text": "V" } - } - ] + }, + "length": 2, + "pos": 17, + "end": 23 + } }`); }); @@ -1798,8 +1813,8 @@ module ts { * @template K , V Description of type parameters. */`, `{ - "typeParameters": [ - { + "typeParameters": { + "0": { "kind": "TypeParameter", "pos": 18, "end": 19, @@ -1810,7 +1825,7 @@ module ts { "text": "K" } }, - { + "1": { "kind": "TypeParameter", "pos": 22, "end": 23, @@ -1820,8 +1835,11 @@ module ts { "end": 23, "text": "V" } - } - ] + }, + "length": 2, + "pos": 17, + "end": 24 + } }`); }); }); From 48a655435e5aee9642437c39ebaf427c9447e78d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Apr 2015 17:49:25 -0700 Subject: [PATCH 87/96] Remove the JSDocCommentInfo type. It's only used for testing now. --- src/compiler/binder.ts | 27 +---------- src/compiler/checker.ts | 38 +++++++-------- src/compiler/parser.ts | 64 +++++++------------------ src/compiler/types.ts | 17 +------ src/compiler/utilities.ts | 37 +++++++++++---- tests/cases/unittests/jsDocParsing.ts | 68 ++++++++++++++++++++++----- 6 files changed, 124 insertions(+), 127 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 01bfe8e9f2517..ff4cb6adb8fae 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -263,7 +263,7 @@ module ts { } if (isJavaScriptFile && node.jsDocComment) { - bindJSDocComment(node); + bind(node.jsDocComment); } forEachChild(node, bind); @@ -280,31 +280,6 @@ module ts { lastContainer = node; } - - function bindJSDocComment(node: Node) { - let jsDocComment = node.jsDocComment; - - if (jsDocComment.type) { - bind(jsDocComment.type); - } - - if (jsDocComment.returnType) { - bind(jsDocComment.returnType); - } - - forEach(jsDocComment.parameters, bindJSDocParameter); - - if (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.FunctionDeclaration) { - forEach(jsDocComment.typeParameters, bind); - } - } - - function bindJSDocParameter(parameter: JSDocParameter) { - if (parameter.type) { - bind(parameter.type); - } - } - function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) { switch (container.kind) { case SyntaxKind.ModuleDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8b6ea91905e1a..62b5d19579010 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2119,9 +2119,9 @@ module ts { function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { // First, see if this node has an @type annotation on it directly. - let docComment = declaration.jsDocComment; - if (docComment && docComment.type) { - return docComment.type; + let typeTag = getJSDocTypeTag(declaration); + if (typeTag) { + return typeTag.typeExpression.type; } if (declaration.kind === SyntaxKind.VariableDeclaration && @@ -2129,17 +2129,17 @@ module ts { declaration.parent.parent.kind === SyntaxKind.VariableStatement) { // @type annotation might have been on the variable statement, try that instead. - docComment = declaration.parent.parent.jsDocComment; - if (docComment && docComment.type) { - return docComment.type; + let typeTag = getJSDocTypeTag(declaration.parent.parent); + if (typeTag) { + return typeTag.typeExpression.type; } } else if (declaration.kind === SyntaxKind.Parameter) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. - let parameter = getJSDocParameter(declaration); + let parameter = getCorrespondingJSDocParameterTag(declaration); if (parameter) { - return parameter.type; + return parameter.typeExpression.type; } } @@ -3089,9 +3089,9 @@ module ts { function getTypeParametersFromSignatureDeclaration(declaration: SignatureDeclaration): TypeParameter[] { if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) { - let jsDocComment = declaration.jsDocComment; - if (jsDocComment && jsDocComment.typeParameters) { - return getTypeParametersFromTypeParameterDeclarations(jsDocComment.typeParameters); + let templateTag = getJSDocTemplateTag(declaration); + if (templateTag) { + return getTypeParametersFromTypeParameterDeclarations(templateTag.typeParameters); } } @@ -3135,9 +3135,9 @@ module ts { return true; } - let docParam = getJSDocParameter(node); + let docParam = getCorrespondingJSDocParameterTag(node); if (docParam) { - return docParam.isBracketed || docParam.type.kind === SyntaxKind.JSDocOptionalType; + return docParam.isBracketed || docParam.typeExpression.type.kind === SyntaxKind.JSDocOptionalType; } } @@ -5736,9 +5736,9 @@ module ts { } function getTypeForThisExpressionFromJSDoc(node: Node) { - var jsDocComment = node.jsDocComment; - if (jsDocComment && jsDocComment.type && jsDocComment.type.kind === SyntaxKind.JSDocFunctionType) { - let jsDocFunctionType = jsDocComment.type; + let typeTag = getJSDocTypeTag(node); + if (typeTag && typeTag.typeExpression.type.kind === SyntaxKind.JSDocFunctionType) { + let jsDocFunctionType = typeTag.typeExpression.type; if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) { return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type); } @@ -7431,9 +7431,9 @@ module ts { } function getReturnTypeFromJSDocComment(func: FunctionLikeDeclaration): Type { - let jsDocComment = func.jsDocComment; - if (jsDocComment && jsDocComment.returnType) { - return getTypeFromTypeNode(jsDocComment.returnType); + let returnTag = getJSDocReturnTag(func); + if (returnTag) { + return getTypeFromTypeNode(returnTag.typeExpression.type); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b5081c72ac8e7..29a457c7a9ef6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -348,6 +348,17 @@ module ts { case SyntaxKind.JSDocRecordMember: return visitNode(cbNode, (node).name) || visitNode(cbNode, (node).type); + case SyntaxKind.JSDocComment: + return visitNodes(cbNodes, (node).tags); + case SyntaxKind.JSDocParameterTag: + return visitNode(cbNode, (node).typeExpression) || + visitNode(cbNode, (node).parameterName); + case SyntaxKind.JSDocReturnTag: + return visitNode(cbNode, (node).typeExpression); + case SyntaxKind.JSDocTypeTag: + return visitNode(cbNode, (node).typeExpression); + case SyntaxKind.JSDocTemplateTag: + return visitNodes(cbNodes, (node).typeParameters); } } @@ -374,13 +385,13 @@ module ts { /* @internal */ // Exposed only for testing. - export function parseJSDocCommentInfo(content: string, start?: number, length?: number) { - return Parser.JSDocParser.parseJSDocCommentInfoForTests(content, start, length); + export function parseJSDocCommentForTests(content: string, start?: number, length?: number) { + return Parser.JSDocParser.parseJSDocCommentForTests(content, start, length); } /* @internal */ // Exposed only for testing. - export function parseJSDocTypeExpression(content: string, start?: number, length?: number) { + export function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number) { return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); } @@ -578,7 +589,7 @@ module ts { let comments = getLeadingCommentRangesOfNode(node, sourceFile); if (comments) { for (let comment of comments) { - let jsDocComment = JSDocParser.parseJSDocCommentInfo(node, comment.pos, comment.end - comment.pos); + let jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); if (jsDocComment) { node.jsDocComment = jsDocComment; } @@ -5328,54 +5339,15 @@ module ts { } } - export function parseJSDocCommentInfoForTests(content: string, start: number, length: number) { + export function parseJSDocCommentForTests(content: string, start: number, length: number) { initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined); - let jsDocComment = parseJSDocCommentInfo(/*parent:*/ undefined, start, length); + let jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); let diagnostics = parseDiagnostics; clearState(); return jsDocComment ? { jsDocComment, diagnostics } : undefined; } - export function parseJSDocCommentInfo(parent: Node, start: number, length: number): JSDocCommentInfo { - let docComment = parseJSDocComment(parent, start, length); - if (!docComment) { - return undefined; - } - - let result = {}; - - let typeTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTypeTag ? t : undefined); - let parameterTags = filter(docComment.tags, t => t.kind === SyntaxKind.JSDocParameterTag); - let returnTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocReturnTag ? t : undefined); - let templateTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTemplateTag ? t : undefined); - - if (!typeTag && parameterTags.length === 0 && !returnTag && !templateTag) { - return undefined; - } - - if (typeTag) { - result.type = typeTag.typeExpression.type; - } - - if (parameterTags.length > 0) { - result.parameters = map(parameterTags, t => { - let paramTag = t; - return { name: paramTag.parameterName.text, type: paramTag.parameterTypeExpression.type, isBracketed: paramTag.isBracketed } - }); - } - - if (returnTag) { - result.returnType = returnTag.typeExpression.type; - } - - if (templateTag) { - result.typeParameters = templateTag.typeParameters; - } - - return result; - } - export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment { let comment = parseJSDocCommentWorker(start, length); if (comment) { @@ -5584,7 +5556,7 @@ module ts { result.atToken = atToken; result.tagName = tagName; result.parameterName = name; - result.parameterTypeExpression = typeExpression; + result.typeExpression = typeExpression; result.isBracketed = isBracketed; return finishNode(result, pos); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 47aa1e403f61f..f902590a00ef6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -405,7 +405,7 @@ module ts { modifiers?: ModifiersArray; // Array of modifiers /* @internal */ id?: number; // Unique id (used to look up NodeLinks) parent?: Node; // Parent node (initialized by binding - /* @internal */ jsDocComment?: JSDocCommentInfo; // JSDoc for the node, if it has any. Only for .js files. + /* @internal */ jsDocComment?: JSDocComment; // JSDoc for the node, if it has any. Only for .js files. /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) @@ -1095,12 +1095,6 @@ module ts { type?: JSDocType } - export interface JSDocParameter { - name: string; - type: JSDocType; - isBracketed: boolean; - } - export interface JSDocComment extends Node { tags: NodeArray; } @@ -1123,18 +1117,11 @@ module ts { } export interface JSDocParameterTag extends JSDocTag { - parameterTypeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression; parameterName: Identifier; isBracketed: boolean; } - export interface JSDocCommentInfo { - type?: JSDocType; - parameters?: JSDocParameter[]; - returnType?: JSDocType; - typeParameters?: TypeParameterDeclaration[]; - } - // Source files are declarations when they are external modules. export interface SourceFile extends Declaration { statements: NodeArray; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 14e2574681498..4a6c883c8f86a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -857,19 +857,38 @@ module ts { (node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType; } - export function getJSDocParameter(parameter: ParameterDeclaration): JSDocParameter { + function getJSDocTag(node: Node, kind: SyntaxKind): JSDocTag { + if (node && node.jsDocComment) { + for (let tag of node.jsDocComment.tags) { + if (tag.kind === kind) { + return tag; + } + } + } + } + + export function getJSDocTypeTag(node: Node): JSDocTypeTag { + return getJSDocTag(node, SyntaxKind.JSDocTypeTag); + } + + export function getJSDocReturnTag(node: Node): JSDocReturnTag { + return getJSDocTag(node, SyntaxKind.JSDocReturnTag); + } + + export function getJSDocTemplateTag(node: Node): JSDocTemplateTag { + return getJSDocTag(node, SyntaxKind.JSDocTemplateTag); + } + + export function getCorrespondingJSDocParameterTag(parameter: ParameterDeclaration): JSDocParameterTag { if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. let parameterName = (parameter.name).text; let docComment = parameter.parent.jsDocComment; - if (docComment && docComment.parameters) { - for (let parameter of docComment.parameters) { - if (parameter.name === parameterName) { - return parameter; - } - } + if (docComment) { + return forEach(docComment.tags, t => + t.kind === SyntaxKind.JSDocParameterTag && (t).parameterName.text === parameterName ? t : undefined); } } } @@ -885,9 +904,9 @@ module ts { return true; } - let docParam = getJSDocParameter(node); + let docParam = getCorrespondingJSDocParameterTag(node); if (docParam) { - return docParam.type.kind === SyntaxKind.JSDocVariadicType; + return docParam.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; } } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 8483521ebb793..fe4d234312d2a 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -3,20 +3,64 @@ /// module ts { + interface JSDocCommentInfo { + type?: JSDocType; + parameters?: JSDocParameter[]; + returnType?: JSDocType; + typeParameters?: TypeParameterDeclaration[]; + } + + interface JSDocParameter { + name: string; + type: JSDocType; + isBracketed: boolean; + } + describe("JSDocParsing", () => { - //function nodeToJSON(file: ts.Node): string { - // return JSON.stringify(Utils.serializeNode(file), (k, v) => { - // return isNodeOrArray(v) ? Utils.serializeNode(v) : v; - // }, " "); - //} + function parseJSDocCommentInfo(content: string): { jsDocComment: JSDocCommentInfo, diagnostics: Diagnostic[] } { + let docCommentAndDiags = ts.parseJSDocCommentForTests(content); + if (!docCommentAndDiags) { + return undefined; + } + + let docComment = docCommentAndDiags.jsDocComment; + let result = {}; + + let typeTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTypeTag ? t : undefined); + let parameterTags = filter(docComment.tags, t => t.kind === SyntaxKind.JSDocParameterTag); + let returnTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocReturnTag ? t : undefined); + let templateTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTemplateTag ? t : undefined); + + if (!typeTag && parameterTags.length === 0 && !returnTag && !templateTag) { + return undefined; + } + + if (typeTag) { + result.type = typeTag.typeExpression.type; + } + + if (parameterTags.length > 0) { + result.parameters = map(parameterTags, t => { + let paramTag = t; + return { name: paramTag.parameterName.text, type: paramTag.typeExpression.type, isBracketed: paramTag.isBracketed } + }); + } + + if (returnTag) { + result.returnType = returnTag.typeExpression.type; + } + + if (templateTag) { + result.typeParameters = templateTag.typeParameters; + } + + return { jsDocComment: result, diagnostics: docCommentAndDiags.diagnostics }; + } - //function isNodeOrArray(a: any): boolean { - // return a !== undefined && typeof a.pos === "number"; - //} describe("TypeExpressions", () => { function parsesCorrectly(content: string, expected: string) { - let typeAndDiagnostics = ts.parseJSDocTypeExpression(content); + let typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0); let result = Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type); @@ -24,7 +68,7 @@ module ts { } function parsesIncorrectly(content: string) { - let type = ts.parseJSDocTypeExpression(content); + let type = ts.parseJSDocTypeExpressionForTests(content); assert.isTrue(!type || type.diagnostics.length > 0); } @@ -1190,7 +1234,7 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = ts.parseJSDocCommentInfo(content); + let comment = parseJSDocCommentInfo(content); Debug.assert(comment && comment.diagnostics.length === 0); let result = JSON.stringify(comment.jsDocComment, (k, v) => { @@ -1202,7 +1246,7 @@ module ts { } function parsesIncorrectly(content: string) { - let type = ts.parseJSDocCommentInfo(content); + let type = parseJSDocCommentInfo(content); assert.isTrue(!type || type.diagnostics.length > 0); } From 507caf787810a0a87b1be01016f1aa7ce9946ecf Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Apr 2015 18:17:39 -0700 Subject: [PATCH 88/96] Remove the JSDocCommentInfo temporary type. --- src/compiler/checker.ts | 18 +- src/compiler/parser.ts | 36 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 6 +- tests/cases/unittests/jsDocParsing.ts | 1195 +++++++++++++++++-------- 5 files changed, 873 insertions(+), 384 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62b5d19579010..d41844b5a327b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2137,9 +2137,9 @@ module ts { else if (declaration.kind === SyntaxKind.Parameter) { // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. - let parameter = getCorrespondingJSDocParameterTag(declaration); - if (parameter) { - return parameter.typeExpression.type; + let paramTag = getCorrespondingJSDocParameterTag(declaration); + if (paramTag && paramTag.typeExpression) { + return paramTag.typeExpression.type; } } @@ -3135,9 +3135,15 @@ module ts { return true; } - let docParam = getCorrespondingJSDocParameterTag(node); - if (docParam) { - return docParam.isBracketed || docParam.typeExpression.type.kind === SyntaxKind.JSDocOptionalType; + let paramTag = getCorrespondingJSDocParameterTag(node); + if (paramTag) { + if (paramTag.isBracketed) { + return true; + } + + if (paramTag.typeExpression) { + return paramTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType; + } } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 29a457c7a9ef6..a59fb979b3de4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5033,9 +5033,6 @@ module ts { // Prime the first token for us to start processing. token = nextToken(); - if (token !== SyntaxKind.OpenBraceToken) { - return undefined; - } let result = createNode(SyntaxKind.JSDocTypeExpression); @@ -5501,13 +5498,19 @@ module ts { } } - function parseTypeExpression(): JSDocTypeExpression { + function tryParseTypeExpression(): JSDocTypeExpression { skipWhitespace(); if (content.charCodeAt(pos) !== CharacterCodes.openBrace) { return undefined; } + return parseTypeExpression(); + } + + function parseTypeExpression(): JSDocTypeExpression { + skipWhitespace(); + let typeExpression = parseJSDocTypeExpression(pos, end - pos); if (!typeExpression) { return undefined; @@ -5523,9 +5526,6 @@ module ts { let typeExpression: JSDocTypeExpression; if (content.charCodeAt(pos) === CharacterCodes.openBrace) { typeExpression = parseTypeExpression(); - if (!typeExpression) { - return; - } } skipWhitespace(); @@ -5542,14 +5542,12 @@ module ts { } if (!name) { - return; + parseErrorAtPosition(pos, 0, Diagnostics.Identifier_expected); + return undefined; } if (!typeExpression) { - typeExpression = parseTypeExpression(); - if (!typeExpression) { - return; - } + typeExpression = tryParseTypeExpression(); } let result = createNode(SyntaxKind.JSDocParameterTag, atToken.pos); @@ -5566,13 +5564,8 @@ module ts { parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text); } - let typeExpression = parseTypeExpression(); - if (!typeExpression) { - return undefined; - } - let result = createNode(SyntaxKind.JSDocReturnTag, atToken.pos); - result.typeExpression = typeExpression; + result.typeExpression = parseTypeExpression(); return finishNode(result, pos); } @@ -5581,13 +5574,8 @@ module ts { parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text); } - let typeExpression = parseTypeExpression(); - if (!typeExpression) { - return undefined; - } - let result = createNode(SyntaxKind.JSDocTypeTag, atToken.pos); - result.typeExpression = typeExpression; + result.typeExpression = parseTypeExpression(); return finishNode(result, pos); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f902590a00ef6..098ceb726dbf4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1117,7 +1117,7 @@ module ts { } export interface JSDocParameterTag extends JSDocTag { - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; parameterName: Identifier; isBracketed: boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4a6c883c8f86a..6d3ba1d02c815 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -904,9 +904,9 @@ module ts { return true; } - let docParam = getCorrespondingJSDocParameterTag(node); - if (docParam) { - return docParam.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; + let paramTag = getCorrespondingJSDocParameterTag(node); + if (paramTag && paramTag.typeExpression) { + return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; } } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index fe4d234312d2a..d2d243e7082d4 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -3,61 +3,7 @@ /// module ts { - interface JSDocCommentInfo { - type?: JSDocType; - parameters?: JSDocParameter[]; - returnType?: JSDocType; - typeParameters?: TypeParameterDeclaration[]; - } - - interface JSDocParameter { - name: string; - type: JSDocType; - isBracketed: boolean; - } - describe("JSDocParsing", () => { - function parseJSDocCommentInfo(content: string): { jsDocComment: JSDocCommentInfo, diagnostics: Diagnostic[] } { - let docCommentAndDiags = ts.parseJSDocCommentForTests(content); - if (!docCommentAndDiags) { - return undefined; - } - - let docComment = docCommentAndDiags.jsDocComment; - let result = {}; - - let typeTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTypeTag ? t : undefined); - let parameterTags = filter(docComment.tags, t => t.kind === SyntaxKind.JSDocParameterTag); - let returnTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocReturnTag ? t : undefined); - let templateTag = forEach(docComment.tags, t => t.kind === SyntaxKind.JSDocTemplateTag ? t : undefined); - - if (!typeTag && parameterTags.length === 0 && !returnTag && !templateTag) { - return undefined; - } - - if (typeTag) { - result.type = typeTag.typeExpression.type; - } - - if (parameterTags.length > 0) { - result.parameters = map(parameterTags, t => { - let paramTag = t; - return { name: paramTag.parameterName.text, type: paramTag.typeExpression.type, isBracketed: paramTag.isBracketed } - }); - } - - if (returnTag) { - result.returnType = returnTag.typeExpression.type; - } - - if (templateTag) { - result.typeParameters = templateTag.typeParameters; - } - - return { jsDocComment: result, diagnostics: docCommentAndDiags.diagnostics }; - } - - describe("TypeExpressions", () => { function parsesCorrectly(content: string, expected: string) { let typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); @@ -1234,7 +1180,7 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = parseJSDocCommentInfo(content); + let comment = parseJSDocCommentForTests(content); Debug.assert(comment && comment.diagnostics.length === 0); let result = JSON.stringify(comment.jsDocComment, (k, v) => { @@ -1242,11 +1188,12 @@ module ts { ? JSON.parse(Utils.sourceFileToJSON(v)) : v; }, " "); + assert.equal(result, expected); } function parsesIncorrectly(content: string) { - let type = parseJSDocCommentInfo(content); + let type = parseJSDocCommentForTests(content); assert.isTrue(!type || type.diagnostics.length > 0); } @@ -1314,13 +1261,6 @@ module ts { */`); }); - it("paramWithoutType", () => { - parsesIncorrectly( -`/** - * @param foo - */`); - }); - it("paramWithoutTypeOrName", () => { parsesIncorrectly( `/** @@ -1336,17 +1276,35 @@ module ts { @type {number} */`, `{ - "type": { - "kind": "JSDocTypeReference", - "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": "Identifier", + "pos": 15, + "end": 21, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 22 } }`); }); @@ -1357,17 +1315,35 @@ module ts { * @type {number} */`, `{ - "type": { - "kind": "JSDocTypeReference", - "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": "Identifier", + "pos": 15, + "end": 21, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 22 } }`); }); @@ -1378,17 +1354,35 @@ module ts { * @type {number} */`, `{ - "type": { - "kind": "JSDocTypeReference", - "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "JSDocTypeReference", + "pos": 15, + "end": 21, + "name": { + "kind": "Identifier", + "pos": 15, + "end": 21, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 22 } }`); }); @@ -1399,17 +1393,35 @@ module ts { * @return {number} */`, `{ - "returnType": { - "kind": "JSDocTypeReference", - "pos": 17, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 29, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 24, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 16, + "end": 24, + "type": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 17, + "end": 23, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 24 } }`); }); @@ -1420,17 +1432,35 @@ module ts { * @return {number} Description text follows */`, `{ - "returnType": { - "kind": "JSDocTypeReference", - "pos": 17, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 54, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 24, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 16, + "end": 24, + "type": { + "kind": "JSDocTypeReference", + "pos": 17, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 17, + "end": 23, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 24 } }`); }); @@ -1441,17 +1471,35 @@ module ts { * @returns {number} */`, `{ - "returnType": { - "kind": "JSDocTypeReference", - "pos": 18, - "end": 24, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 24, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "kind": "JSDocComment", + "pos": 0, + "end": 30, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 25, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 17, + "end": 25, + "type": { + "kind": "JSDocTypeReference", + "pos": 18, + "end": 24, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 24, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } + } + } + }, + "length": 1, + "pos": 8, + "end": 25 } }`); }); @@ -1462,23 +1510,53 @@ module ts { * @param {number} name1 */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 34, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 1, + "pos": 8, + "end": 29 + } }`); }); @@ -1489,38 +1567,92 @@ module ts { * @param {number} name2 */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 60, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } }, - { - "name": "name2", - "type": { - "kind": "JSDocTypeReference", - "pos": 42, - "end": 48, - "name": { - "kind": "Identifier", + "1": { + "kind": "JSDocParameterTag", + "pos": 34, + "end": 55, + "atToken": { + "kind": "AtToken", + "pos": 34, + "end": 35 + }, + "tagName": { + "kind": "Identifier", + "pos": 35, + "end": 40, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 50, + "end": 55, + "text": "name2" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 41, + "end": 49, + "type": { + "kind": "JSDocTypeReference", "pos": 42, "end": 48, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 42, + "end": 48, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 2, + "pos": 8, + "end": 55 + } }`); }); @@ -1530,23 +1662,53 @@ module ts { * @param {number} name1 Description text follows */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 59, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 1, + "pos": 8, + "end": 29 + } }`); }); @@ -1556,24 +1718,54 @@ module ts { * @param {number} [name1] Description text follows */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 61, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 30, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 25, + "end": 30, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } }, "isBracketed": true - } - ] + }, + "length": 1, + "pos": 8, + "end": 30 + } }`); }); @@ -1583,24 +1775,54 @@ module ts { * @param {number} [ name1 = 1] Description text follows */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 66, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 31, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 26, + "end": 31, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } }, "isBracketed": true - } - ] + }, + "length": 1, + "pos": 8, + "end": 31 + } }`); }); @@ -1610,23 +1832,53 @@ module ts { * @param {number} name1 @param {number} name2 */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 56, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "JSDocTypeReference", "pos": 16, "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 16, + "end": 22, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 1, + "pos": 8, + "end": 29 + } }`); }); @@ -1636,23 +1888,53 @@ module ts { * @param name1 {number} */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 22, - "end": 28, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 34, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 15, + "end": 20, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 21, + "end": 29, + "type": { + "kind": "JSDocTypeReference", "pos": 22, "end": 28, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 22, + "end": 28, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 1, + "pos": 8, + "end": 29 + } }`); }); @@ -1662,23 +1944,53 @@ module ts { * @param name1 {number} Description */`, `{ - "parameters": [ - { - "name": "name1", - "type": { - "kind": "JSDocTypeReference", - "pos": 22, - "end": 28, - "name": { - "kind": "Identifier", + "kind": "JSDocComment", + "pos": 0, + "end": 46, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 15, + "end": 20, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 21, + "end": 29, + "type": { + "kind": "JSDocTypeReference", "pos": 22, "end": 28, - "originalKeywordKind": "NumberKeyword", - "text": "number" + "name": { + "kind": "Identifier", + "pos": 22, + "end": 28, + "originalKeywordKind": "NumberKeyword", + "text": "number" + } } } - } - ] + }, + "length": 1, + "pos": 8, + "end": 29 + } }`); }); @@ -1688,20 +2000,44 @@ module ts { * @template T */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 24, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, + "kind": "JSDocTemplateTag", + "pos": 8, "end": 19, - "name": { + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "T" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "T" + } + }, + "length": 1, + "pos": 17, + "end": 19 } }, "length": 1, - "pos": 17, + "pos": 8, "end": 19 } }`); @@ -1713,31 +2049,55 @@ module ts { * @template K,V */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 26, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 20, + "kind": "JSDocTemplateTag", + "pos": 8, "end": 21, - "name": { + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 20, - "end": 21, - "text": "V" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 20, + "end": 21, + "name": { + "kind": "Identifier", + "pos": 20, + "end": 21, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 21 } }, - "length": 2, - "pos": 17, + "length": 1, + "pos": 8, "end": 21 } }`); @@ -1749,31 +2109,55 @@ module ts { * @template K ,V */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 21, + "kind": "JSDocTemplateTag", + "pos": 8, "end": 22, - "name": { + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 21, - "end": 22, - "text": "V" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 21, + "end": 22, + "name": { + "kind": "Identifier", + "pos": 21, + "end": 22, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 22 } }, - "length": 2, - "pos": 17, + "length": 1, + "pos": 8, "end": 22 } }`); @@ -1785,31 +2169,55 @@ module ts { * @template K, V */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 21, + "kind": "JSDocTemplateTag", + "pos": 8, "end": 22, - "name": { + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 21, - "end": 22, - "text": "V" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 21, + "end": 22, + "name": { + "kind": "Identifier", + "pos": 21, + "end": 22, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 22 } }, - "length": 2, - "pos": 17, + "length": 1, + "pos": 8, "end": 22 } }`); @@ -1821,31 +2229,55 @@ module ts { * @template K , V */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 28, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 22, + "kind": "JSDocTemplateTag", + "pos": 8, "end": 23, - "name": { + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 22, - "end": 23, - "text": "V" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 22, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 22, + "end": 23, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 23 } }, - "length": 2, - "pos": 17, + "length": 1, + "pos": 8, "end": 23 } }`); @@ -1857,32 +2289,95 @@ module ts { * @template K , V Description of type parameters. */`, `{ - "typeParameters": { + "kind": "JSDocComment", + "pos": 0, + "end": 60, + "tags": { "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 24, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 22, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 22, + "end": 23, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 24 } }, - "1": { - "kind": "TypeParameter", - "pos": 22, - "end": 23, - "name": { + "length": 1, + "pos": 8, + "end": 24 + } +}`); + }); + + it("paramWithoutType", () => { + parsesCorrectly( + `/** + * @param foo + */`, + `{ + "kind": "JSDocComment", + "pos": 0, + "end": 23, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 18, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { "kind": "Identifier", - "pos": 22, - "end": 23, - "text": "V" + "pos": 9, + "end": 14, + "text": "param" + }, + "parameterName": { + "kind": "Identifier", + "pos": 15, + "end": 18, + "text": "foo" } }, - "length": 2, - "pos": 17, - "end": 24 + "length": 1, + "pos": 8, + "end": 18 } }`); }); From 5d6a1e8312068fe3a851b0bf419ce0c27095aee0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 27 Apr 2015 12:39:19 -0700 Subject: [PATCH 89/96] Use real type nodes for primitive types. --- src/compiler/checker.ts | 10 - src/compiler/parser.ts | 7 + tests/cases/unittests/jsDocParsing.ts | 473 +++++--------------------- 3 files changed, 93 insertions(+), 397 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b4e016be35e32..e83886e5fdb2e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3772,16 +3772,6 @@ module ts { } function getTypeForJSDocTypeReference(node: JSDocTypeReference): Type { - if (node.name.kind === SyntaxKind.Identifier) { - switch ((node.name).text) { - case "any": return anyType; - case "boolean": return booleanType; - case "number": return numberType; - case "string": return stringType; - case "symbol": return esSymbolType; - } - } - let symbol = resolveEntityName(node.name, SymbolFlags.Type); if (symbol) { let type = createTypeReferenceIfGeneric( diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a59fb979b3de4..610917308b709 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5126,6 +5126,13 @@ module ts { 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: + return parseTokenNode(); } return parseJSDocTypeReference(); diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index d2d243e7082d4..f7855055dde10 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -44,16 +44,9 @@ module ts { "pos": 1, "end": 8, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 } }`) }); @@ -65,16 +58,9 @@ module ts { "pos": 1, "end": 8, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 1, - "end": 7, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 7, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 7 } }`) }); @@ -86,16 +72,9 @@ module ts { "pos": 1, "end": 8, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 } }`) }); @@ -107,16 +86,9 @@ module ts { "pos": 1, "end": 8, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 1, - "end": 7, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 7, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 7 } }`) }); @@ -178,16 +150,9 @@ module ts { "text": "foo" }, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 6, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 13, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 13 } }, "length": 1, @@ -251,16 +216,9 @@ module ts { "text": "foo" }, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 6, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 13, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 13 } }, "1": { @@ -310,16 +268,9 @@ module ts { "text": "bar" }, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 11, - "end": 18, - "name": { - "kind": "Identifier", - "pos": 11, - "end": 18, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 18 } }, "length": 2, @@ -347,16 +298,9 @@ module ts { "text": "foo" }, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 6, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 13, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 13 } }, "1": { @@ -370,16 +314,9 @@ module ts { "text": "bar" }, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 19, - "end": 26, - "name": { - "kind": "Identifier", - "pos": 19, - "end": 26, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 26 } }, "length": 2, @@ -423,28 +360,14 @@ module ts { "end": 16, "types": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 }, "1": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 9, - "end": 15, - "name": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 15 }, "length": 2, "pos": 2, @@ -461,28 +384,14 @@ module ts { "end": 14, "types": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 1, - "end": 7, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 7, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 7 }, "1": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 8, - "end": 14, - "name": { - "kind": "Identifier", - "pos": 8, - "end": 14, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 14 }, "length": 2, "pos": 1, @@ -517,16 +426,9 @@ module ts { "pos": 10, "end": 16, "type": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 10, - "end": 16, - "name": { - "kind": "Identifier", - "pos": 10, - "end": 16, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 16 } }, "1": { @@ -534,16 +436,9 @@ module ts { "pos": 17, "end": 25, "type": { - "kind": "JSDocTypeReference", + "kind": "BooleanKeyword", "pos": 17, - "end": 25, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 25, - "originalKeywordKind": "BooleanKeyword", - "text": "boolean" - } + "end": 25 } }, "length": 2, @@ -565,16 +460,9 @@ module ts { "pos": 10, "end": 16, "type": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 10, - "end": 16, - "name": { - "kind": "Identifier", - "pos": 10, - "end": 16, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 16 } }, "1": { @@ -582,16 +470,9 @@ module ts { "pos": 17, "end": 25, "type": { - "kind": "JSDocTypeReference", + "kind": "BooleanKeyword", "pos": 17, - "end": 25, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 25, - "originalKeywordKind": "BooleanKeyword", - "text": "boolean" - } + "end": 25 } }, "length": 2, @@ -670,16 +551,9 @@ module ts { "pos": 1, "end": 10, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 4, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 4, - "end": 10, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 10 } }`); }); @@ -691,16 +565,9 @@ module ts { "pos": 1, "end": 8, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 1, - "end": 7, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 7, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 7 } }`); }); @@ -733,16 +600,9 @@ module ts { }, "typeArguments": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 4, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 4, - "end": 10, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 10 }, "length": 1, "pos": 4, @@ -765,28 +625,14 @@ module ts { }, "typeArguments": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 4, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 4, - "end": 10, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 10 }, "1": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 11, - "end": 17, - "name": { - "kind": "Identifier", - "pos": 11, - "end": 17, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 17 }, "length": 2, "pos": 4, @@ -974,16 +820,9 @@ module ts { "end": 9, "types": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 }, "length": 1, "pos": 2, @@ -1001,28 +840,14 @@ module ts { "end": 16, "types": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 }, "1": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 9, - "end": 15, - "name": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 15 }, "length": 2, "pos": 2, @@ -1040,40 +865,19 @@ module ts { "end": 24, "types": { "0": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 2, - "end": 8, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 8, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 8 }, "1": { - "kind": "JSDocTypeReference", + "kind": "StringKeyword", "pos": 9, - "end": 15, - "name": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "originalKeywordKind": "StringKeyword", - "text": "string" - } + "end": 15 }, "2": { - "kind": "JSDocTypeReference", + "kind": "BooleanKeyword", "pos": 16, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 23, - "originalKeywordKind": "BooleanKeyword", - "text": "boolean" - } + "end": 23 }, "length": 3, "pos": 2, @@ -1289,16 +1093,9 @@ module ts { "pos": 14, "end": 22, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 21 } } }, @@ -1328,16 +1125,9 @@ module ts { "pos": 14, "end": 22, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 21 } } }, @@ -1367,16 +1157,9 @@ module ts { "pos": 14, "end": 22, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 15, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 15, - "end": 21, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 21 } } }, @@ -1406,16 +1189,9 @@ module ts { "pos": 16, "end": 24, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 17, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 23 } } }, @@ -1445,16 +1221,9 @@ module ts { "pos": 16, "end": 24, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 17, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 23 } } }, @@ -1484,16 +1253,9 @@ module ts { "pos": 17, "end": 25, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 18, - "end": 24, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 24, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 24 } } }, @@ -1540,16 +1302,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } } }, @@ -1597,16 +1352,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } } }, @@ -1636,16 +1384,9 @@ module ts { "pos": 41, "end": 49, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 42, - "end": 48, - "name": { - "kind": "Identifier", - "pos": 42, - "end": 48, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 48 } } }, @@ -1692,16 +1433,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } } }, @@ -1748,16 +1482,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } }, "isBracketed": true @@ -1805,16 +1532,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } }, "isBracketed": true @@ -1862,16 +1582,9 @@ module ts { "pos": 15, "end": 23, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 16, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 16, - "end": 22, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 22 } } }, @@ -1918,16 +1631,9 @@ module ts { "pos": 21, "end": 29, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 22, - "end": 28, - "name": { - "kind": "Identifier", - "pos": 22, - "end": 28, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 28 } } }, @@ -1974,16 +1680,9 @@ module ts { "pos": 21, "end": 29, "type": { - "kind": "JSDocTypeReference", + "kind": "NumberKeyword", "pos": 22, - "end": 28, - "name": { - "kind": "Identifier", - "pos": 22, - "end": 28, - "originalKeywordKind": "NumberKeyword", - "text": "number" - } + "end": 28 } } }, From 47ad2f57fb1b684310bf2fd9f0d27e2b5067287b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 27 Apr 2015 16:12:00 -0700 Subject: [PATCH 90/96] Add support for classifying jsdoc comments --- src/compiler/parser.ts | 48 ++-- src/compiler/types.ts | 3 +- src/compiler/utilities.ts | 11 +- src/services/services.ts | 120 ++++++++- tests/cases/fourslash/fourslash.ts | 4 + ...cticClassificationsFunctionWithComments.ts | 2 +- tests/cases/unittests/jsDocParsing.ts | 240 +++++++++++++----- 7 files changed, 332 insertions(+), 96 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 610917308b709..1ea4e0789f81e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -351,8 +351,9 @@ module ts { case SyntaxKind.JSDocComment: return visitNodes(cbNodes, (node).tags); case SyntaxKind.JSDocParameterTag: - return visitNode(cbNode, (node).typeExpression) || - visitNode(cbNode, (node).parameterName); + return visitNode(cbNode, (node).preParameterName) || + visitNode(cbNode, (node).typeExpression) || + visitNode(cbNode, (node).postParameterName); case SyntaxKind.JSDocReturnTag: return visitNode(cbNode, (node).typeExpression); case SyntaxKind.JSDocTypeTag: @@ -384,9 +385,8 @@ module ts { } /* @internal */ - // Exposed only for testing. - export function parseJSDocCommentForTests(content: string, start?: number, length?: number) { - return Parser.JSDocParser.parseJSDocCommentForTests(content, start, length); + export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) { + return Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); } /* @internal */ @@ -5343,7 +5343,7 @@ module ts { } } - export function parseJSDocCommentForTests(content: string, start: number, length: number) { + export function parseIsolatedJSDocComment(content: string, start: number, length: number) { initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined); let jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); let diagnostics = parseDiagnostics; @@ -5512,28 +5512,13 @@ module ts { return undefined; } - return parseTypeExpression(); - } - - function parseTypeExpression(): JSDocTypeExpression { - skipWhitespace(); - let typeExpression = parseJSDocTypeExpression(pos, end - pos); - if (!typeExpression) { - return undefined; - } - pos = typeExpression.end; return typeExpression; } function handleParamTag(atToken: Node, tagName: Identifier) { - skipWhitespace(); - - let typeExpression: JSDocTypeExpression; - if (content.charCodeAt(pos) === CharacterCodes.openBrace) { - typeExpression = parseTypeExpression(); - } + let typeExpression = tryParseTypeExpression(); skipWhitespace(); let name: Identifier; @@ -5553,6 +5538,14 @@ module ts { return undefined; } + let preName: Identifier, postName: Identifier; + if (typeExpression) { + postName = name; + } + else { + preName = name; + } + if (!typeExpression) { typeExpression = tryParseTypeExpression(); } @@ -5560,8 +5553,9 @@ module ts { let result = createNode(SyntaxKind.JSDocParameterTag, atToken.pos); result.atToken = atToken; result.tagName = tagName; - result.parameterName = name; + result.preParameterName = preName; result.typeExpression = typeExpression; + result.postParameterName = postName; result.isBracketed = isBracketed; return finishNode(result, pos); } @@ -5572,7 +5566,9 @@ module ts { } let result = createNode(SyntaxKind.JSDocReturnTag, atToken.pos); - result.typeExpression = parseTypeExpression(); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result, pos); } @@ -5582,7 +5578,9 @@ module ts { } let result = createNode(SyntaxKind.JSDocTypeTag, atToken.pos); - result.typeExpression = parseTypeExpression(); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result, pos); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5c4c5d727591f..d70fece9c468d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1117,8 +1117,9 @@ module ts { } export interface JSDocParameterTag extends JSDocTag { + preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; - parameterName: Identifier; + postParameterName?: Identifier; isBracketed: boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fa4873346e92e..834a472b96534 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -887,8 +887,15 @@ module ts { let docComment = parameter.parent.jsDocComment; if (docComment) { - return forEach(docComment.tags, t => - t.kind === SyntaxKind.JSDocParameterTag && (t).parameterName.text === parameterName ? t : undefined); + return forEach(docComment.tags, t => { + if (t.kind === SyntaxKind.JSDocParameterTag) { + let parameterTag = t; + let name = parameterTag.preParameterName || parameterTag.postParameterName; + if (name.text === parameterName) { + return t; + } + } + }); } } } diff --git a/src/services/services.ts b/src/services/services.ts index ad18283713b68..5b0af0a6b902a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1485,6 +1485,9 @@ module ts { public static moduleName = "module name"; public static typeParameterName = "type parameter name"; public static typeAlias = "type alias name"; + public static parameterName = "parameter name"; + + public static docCommentTagName = "doc comment tag name"; } /// Language Service @@ -5925,11 +5928,7 @@ module ts { } if (isComment(kind)) { - // Simple comment. Just add as is. - result.push({ - textSpan: createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }) + classifyComment(token, kind, start, width); continue; } @@ -5956,6 +5955,106 @@ module ts { } } + function classifyComment(token: Node, kind: SyntaxKind, start: number, width: number) { + if (kind === SyntaxKind.MultiLineCommentTrivia) { + // See if this is a doc comment. If so, we'll classify certain portions of it + // specially. + let jsDocComment = parseIsolatedJSDocComment(sourceFile.text, start, width); + if (jsDocComment && jsDocComment.jsDocComment) { + jsDocComment.jsDocComment.parent = token; + classifyJSDocComment(jsDocComment.jsDocComment); + return; + } + } + + // Simple comment. Just add as is. + pushCommentRange(start, width); + } + + function pushCommentRange(start: number, width: number) { + result.push({ + textSpan: createTextSpan(start, width), + classificationType: ClassificationTypeNames.comment + }) + } + + function classifyJSDocComment(docComment: JSDocComment) { + let pos = docComment.pos; + + for (let tag of docComment.tags) { + if (tag.pos !== pos) { + pushCommentRange(pos, tag.pos - pos); + } + + result.push({ + textSpan: createTextSpanFromBounds(tag.atToken.pos, tag.atToken.end), + classificationType: ClassificationTypeNames.punctuation + }); + + result.push({ + textSpan: createTextSpanFromBounds(tag.tagName.pos, tag.tagName.end), + classificationType: ClassificationTypeNames.docCommentTagName + }); + + pos = tag.tagName.end; + + switch (tag.kind) { + case SyntaxKind.JSDocParameterTag: + processJSDocParameterTag(tag); + break; + case SyntaxKind.JSDocTemplateTag: + processJSDocTemplateTag(tag); + break; + case SyntaxKind.JSDocTypeTag: + processElement((tag).typeExpression); + break; + case SyntaxKind.JSDocReturnTag: + processElement((tag).typeExpression); + break; + } + + pos = tag.end; + } + + if (pos !== docComment.end) { + pushCommentRange(pos, docComment.end - pos); + } + + return; + + function processJSDocParameterTag(tag: JSDocParameterTag) { + if (tag.preParameterName) { + pushCommentRange(pos, tag.preParameterName.pos - pos); + result.push({ + textSpan: createTextSpanFromBounds(tag.preParameterName.pos, tag.preParameterName.end), + classificationType: ClassificationTypeNames.parameterName + }); + pos = tag.preParameterName.end; + } + + if (tag.typeExpression) { + pushCommentRange(pos, tag.typeExpression.pos - pos); + processElement(tag.typeExpression); + pos = tag.typeExpression.end; + } + + if (tag.postParameterName) { + pushCommentRange(pos, tag.postParameterName.pos - pos); + result.push({ + textSpan: createTextSpanFromBounds(tag.postParameterName.pos, tag.postParameterName.end), + classificationType: ClassificationTypeNames.parameterName + }); + pos = tag.postParameterName.end; + } + } + } + + function processJSDocTemplateTag(tag: JSDocTemplateTag) { + for (let child of tag.getChildren()) { + processElement(child); + } + } + function classifyDisabledMergeCode(text: string, start: number, end: number) { // Classify the line that the ======= marker is on as a comment. Then just lex // all further tokens and add them to the result. @@ -6085,6 +6184,11 @@ module ts { return ClassificationTypeNames.moduleName; } return; + case SyntaxKind.Parameter: + if ((token.parent).name === token) { + return ClassificationTypeNames.parameterName; + } + return; } } @@ -6093,9 +6197,13 @@ module ts { } function processElement(element: Node) { + if (!element) { + return; + } + // Ignore nodes that don't intersect the original span to classify. if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) { - let children = element.getChildren(); + let children = element.getChildren(sourceFile); for (let child of children) { if (isToken(child)) { classifyToken(child); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index ef9ab51d61ffa..a83f5f03a409e 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -655,6 +655,10 @@ module FourSlashInterface { return getClassification("typeParameterName", text, position); } + export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { + return getClassification("parameterName", text, position); + } + export function typeAlias(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { return getClassification("typeAlias", text, position); } diff --git a/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts b/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts index eeaf4a7033f3f..f7e5b7355a7c2 100644 --- a/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts +++ b/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts @@ -19,7 +19,7 @@ var firstCommentText = var c = classification; verify.syntacticClassificationsAre( c.comment(firstCommentText), - c.keyword("function"), c.text("myFunction"), c.punctuation("("), c.comment("/* x */"), c.text("x"), c.punctuation(":"), c.keyword("any"), c.punctuation(")"), c.punctuation("{"), + c.keyword("function"), c.text("myFunction"), c.punctuation("("), c.comment("/* x */"), c.parameterName("x"), c.punctuation(":"), c.keyword("any"), c.punctuation(")"), c.punctuation("{"), c.keyword("var"), c.text("y"), c.operator("="), c.text("x"), c.operator("?"), c.text("x"), c.operator("++"), c.operator(":"), c.operator("++"), c.text("x"), c.punctuation(";"), c.punctuation("}"), c.comment("// end of file")); \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index f7855055dde10..ebba6e8a1a648 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -984,7 +984,7 @@ module ts { describe("DocComments", () => { function parsesCorrectly(content: string, expected: string) { - let comment = parseJSDocCommentForTests(content); + let comment = parseIsolatedJSDocComment(content); Debug.assert(comment && comment.diagnostics.length === 0); let result = JSON.stringify(comment.jsDocComment, (k, v) => { @@ -997,7 +997,7 @@ module ts { } function parsesIncorrectly(content: string) { - let type = parseJSDocCommentForTests(content); + let type = parseIsolatedJSDocComment(content); assert.isTrue(!type || type.diagnostics.length > 0); } @@ -1014,13 +1014,6 @@ module ts { parsesIncorrectly("/** * @type {number} */"); }); - it("noType", () => { - parsesIncorrectly( -`/** - * @type - */`); - }); - it("multipleTypes", () => { parsesIncorrectly( `/** @@ -1037,13 +1030,6 @@ module ts { */`); }); - it("noReturnType", () => { - parsesIncorrectly( -`/** - * @return - */`); - }); - it("noTypeParameters", () => { parsesIncorrectly( `/** @@ -1088,6 +1074,17 @@ module ts { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, @@ -1106,6 +1103,72 @@ module ts { }`); }); + it("noType", () => { + parsesCorrectly( + `/** + * @type + */`, + `{ + "kind": "JSDocComment", + "pos": 0, + "end": 18, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 13, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + } + }, + "length": 1, + "pos": 8, + "end": 13 + } +}`); + }); + + it("noReturnType", () => { + parsesCorrectly( + `/** + * @return + */`, + `{ + "kind": "JSDocComment", + "pos": 0, + "end": 20, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 15, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + } + }, + "length": 1, + "pos": 8, + "end": 15 + } +}`); + }); + it("leadingAsterisk", () => { parsesCorrectly( `/** @@ -1120,6 +1183,17 @@ module ts { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, @@ -1152,6 +1226,17 @@ module ts { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, @@ -1184,6 +1269,17 @@ module ts { "kind": "JSDocReturnTag", "pos": 8, "end": 24, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 16, @@ -1216,6 +1312,17 @@ module ts { "kind": "JSDocReturnTag", "pos": 8, "end": 24, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 16, @@ -1248,6 +1355,17 @@ module ts { "kind": "JSDocReturnTag", "pos": 8, "end": 25, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 16, + "text": "returns" + }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 17, @@ -1291,12 +1409,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1306,6 +1418,12 @@ module ts { "pos": 16, "end": 22 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" } }, "length": 1, @@ -1341,12 +1459,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1356,6 +1468,12 @@ module ts { "pos": 16, "end": 22 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" } }, "1": { @@ -1373,12 +1491,6 @@ module ts { "end": 40, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 50, - "end": 55, - "text": "name2" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 41, @@ -1388,6 +1500,12 @@ module ts { "pos": 42, "end": 48 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 50, + "end": 55, + "text": "name2" } }, "length": 2, @@ -1422,12 +1540,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1437,6 +1549,12 @@ module ts { "pos": 16, "end": 22 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" } }, "length": 1, @@ -1471,12 +1589,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 25, - "end": 30, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1487,6 +1599,12 @@ module ts { "end": 22 } }, + "postParameterName": { + "kind": "Identifier", + "pos": 25, + "end": 30, + "text": "name1" + }, "isBracketed": true }, "length": 1, @@ -1521,12 +1639,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 26, - "end": 31, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1537,6 +1649,12 @@ module ts { "end": 22 } }, + "postParameterName": { + "kind": "Identifier", + "pos": 26, + "end": 31, + "text": "name1" + }, "isBracketed": true }, "length": 1, @@ -1571,12 +1689,6 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -1586,6 +1698,12 @@ module ts { "pos": 16, "end": 22 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" } }, "length": 1, @@ -1620,7 +1738,7 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { + "preParameterName": { "kind": "Identifier", "pos": 15, "end": 20, @@ -1669,7 +1787,7 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { + "preParameterName": { "kind": "Identifier", "pos": 15, "end": 20, @@ -2067,7 +2185,7 @@ module ts { "end": 14, "text": "param" }, - "parameterName": { + "preParameterName": { "kind": "Identifier", "pos": 15, "end": 18, From fdc9ba1b78e3600a88f4eff3b61464096e836267 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 4 May 2015 12:53:49 -0700 Subject: [PATCH 91/96] use pos/end instead of width() --- src/services/services.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index f7a2ef3e22c79..f70f00af590cb 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6077,8 +6077,8 @@ module ts { pushCommentRange(pos, tag.pos - pos); } - pushClassification(tag.atToken.pos, tag.atToken.getWidth(), ClassificationType.punctuation); - pushClassification(tag.tagName.pos, tag.tagName.getWidth(), ClassificationType.docCommentTagName); + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation); + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); pos = tag.tagName.end; @@ -6109,7 +6109,7 @@ module ts { function processJSDocParameterTag(tag: JSDocParameterTag) { if (tag.preParameterName) { pushCommentRange(pos, tag.preParameterName.pos - pos); - pushClassification(tag.preParameterName.pos, tag.preParameterName.getWidth(), ClassificationType.parameterName); + pushClassification(tag.preParameterName.pos, tag.preParameterName.end - tag.preParameterName.pos, ClassificationType.parameterName); pos = tag.preParameterName.end; } @@ -6121,7 +6121,7 @@ module ts { if (tag.postParameterName) { pushCommentRange(pos, tag.postParameterName.pos - pos); - pushClassification(tag.postParameterName.pos, tag.postParameterName.getWidth(), ClassificationType.parameterName); + pushClassification(tag.postParameterName.pos, tag.postParameterName.end - tag.postParameterName.pos, ClassificationType.parameterName); pos = tag.postParameterName.end; } } From 3b656e86a14ac7eca8adf092111e2e48f5c0705d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 4 May 2015 23:20:08 -0700 Subject: [PATCH 92/96] Deal properly with type parameters not parented by signatures/classes/interfaces (i.e. in doc comments). --- src/compiler/checker.ts | 2 +- src/compiler/utilities.ts | 16 ++++++++++++++++ src/services/services.ts | 20 +++++++++++--------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ff1d56ac394a..b2ca96ff0bb1d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3417,7 +3417,7 @@ module ts { // bubble up to the declaration let currentNode: Node = typeReferenceNode; // forEach === exists - while (!forEach(typeParameterSymbol.declarations, d => d.parent === currentNode.parent)) { + while (!forEach(typeParameterSymbol.declarations, d => getTypeParameterOwner(d) === currentNode.parent)) { currentNode = currentNode.parent; } // if last step was made from the type parameter this means that path has started somewhere in constraint which is illegal diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f5597829d03bd..990dbd6568fe7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -468,6 +468,12 @@ module ts { return false; } + export function isClassLike(node: Node): boolean { + if (node) { + return node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression; + } + } + export function isFunctionLike(node: Node): boolean { if (node) { switch (node.kind) { @@ -2057,4 +2063,14 @@ module ts { return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength:*/ newEndN - oldStartN); } + + export function getTypeParameterOwner(d: Declaration): Declaration { + if (d && d.kind === SyntaxKind.TypeParameter) { + for (let current: Node = d; current; current = current.parent) { + if (isFunctionLike(current) || isClassLike(current) || current.kind === SyntaxKind.InterfaceDeclaration) { + return current; + } + } + } + } } diff --git a/src/services/services.ts b/src/services/services.ts index f70f00af590cb..98a407e632fc0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3729,16 +3729,18 @@ module ts { } else { // Method/function type parameter - let signatureDeclaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent; - let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration); - if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) { - displayParts.push(keywordPart(SyntaxKind.NewKeyword)); - displayParts.push(spacePart()); - } - else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) { - addFullSymbolName(signatureDeclaration.symbol); + let signatureDeclaration = getTypeParameterOwner(getDeclarationOfKind(symbol, SyntaxKind.TypeParameter)); + if (signatureDeclaration) { + let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration); + if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) { + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); + } + else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) { + addFullSymbolName(signatureDeclaration.symbol); + } + displayParts.push.apply(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } - displayParts.push.apply(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } } if (symbolFlags & SymbolFlags.EnumMember) { From ab44f953f3b2db20bfc7bd0a8e5a1a3f1afa199a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 8 May 2015 09:51:23 -0700 Subject: [PATCH 93/96] Support @type tags referencing JS values. --- src/compiler/checker.ts | 7 +++++++ tests/cases/fourslash/getJavaScriptQuickInfo7.ts | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/cases/fourslash/getJavaScriptQuickInfo7.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 869bde021e4bd..68565ca6be5de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3801,6 +3801,13 @@ module ts { function getTypeForJSDocTypeReference(node: JSDocTypeReference): Type { let symbol = resolveEntityName(node.name, SymbolFlags.Type); + if (!symbol) { + // If the reference didn't resolve to a type, try seeing if results to a + // value. If it does, get the type of that value. + symbol = resolveEntityName(node.name, SymbolFlags.Value); + return symbol && getTypeOfSymbol(symbol); + } + if (symbol) { let type = createTypeReferenceIfGeneric( getDeclaredTypeOfSymbol(symbol), diff --git a/tests/cases/fourslash/getJavaScriptQuickInfo7.ts b/tests/cases/fourslash/getJavaScriptQuickInfo7.ts new file mode 100644 index 0000000000000..d8ecb1ec138d9 --- /dev/null +++ b/tests/cases/fourslash/getJavaScriptQuickInfo7.ts @@ -0,0 +1,11 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: Foo.js +//// function f(a,b) { } +//// /** @type {f} */ +//// var v/**/ + +debugger; +goTo.marker(); +verify.quickInfoIs('var v: (a: any, b: any) => void'); \ No newline at end of file From 729c96cbce28444a7219ccb7e8ef32a7838c110e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 28 May 2015 11:40:49 -0700 Subject: [PATCH 94/96] Move code. --- src/compiler/utilities.ts | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 918c144f138d7..709cb4dbe9890 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -854,29 +854,6 @@ module ts { return false; } - export function hasRestParameter(s: SignatureDeclaration): boolean { - return isRestParameter(lastOrUndefined(s.parameters)); - } - - export function isRestParameter(node: ParameterDeclaration) { - if (node) { - if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { - if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { - return true; - } - - let paramTag = getCorrespondingJSDocParameterTag(node); - if (paramTag && paramTag.typeExpression) { - return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; - } - } - - return node.dotDotDotToken !== undefined; - } - - return false; - } - export function isJSDocConstructSignature(node: Node) { return node.kind === SyntaxKind.JSDocFunctionType && (node).parameters.length > 0 && @@ -926,6 +903,29 @@ module ts { } } + export function hasRestParameter(s: SignatureDeclaration): boolean { + return isRestParameter(lastOrUndefined(s.parameters)); + } + + export function isRestParameter(node: ParameterDeclaration) { + if (node) { + if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) { + if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { + return true; + } + + let paramTag = getCorrespondingJSDocParameterTag(node); + if (paramTag && paramTag.typeExpression) { + return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; + } + } + + return node.dotDotDotToken !== undefined; + } + + return false; + } + export function isLiteralKind(kind: SyntaxKind): boolean { return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken; } From d8ef02a7f521b2845ac77da0c2b36f5a44df4685 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Fri, 5 Jun 2015 16:59:04 -0700 Subject: [PATCH 95/96] Added non-ts file support to the server --- src/server/editorServices.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index bc9e685825c08..7fcecbc65e1d8 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -966,7 +966,9 @@ module ts.server { this.setCompilerOptions(opt); } else { - this.setCompilerOptions(ts.getDefaultCompilerOptions()); + var defaultOpts = ts.getDefaultCompilerOptions(); + defaultOpts.allowNonTsExtensions = true; + this.setCompilerOptions(defaultOpts); } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); this.classifier = ts.createClassifier(); From 34c128ea438e32d11918a62453ea69b4357c6d0c Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Tue, 30 Jun 2015 10:31:06 -0700 Subject: [PATCH 96/96] Added JSX support --- src/compiler/utilities.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 750482bc8b09f..6aa1a42324a0a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1958,11 +1958,11 @@ namespace ts { } export function isJavaScript(fileName: string) { - return fileExtensionIs(fileName, ".js"); + return fileExtensionIs(fileName, ".js") || fileExtensionIs(fileName, ".jsx"); } export function isTsx(fileName: string) { - return fileExtensionIs(fileName, ".tsx"); + return fileExtensionIs(fileName, ".tsx") || fileExtensionIs(fileName, ".jsx"); } /**