From 743046bf45567d13cd67ba465733227ae72309fa Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 29 Sep 2014 09:45:03 -0700 Subject: [PATCH] Use SymbolDisplayParts api --- src/compiler/checker.ts | 22 +- src/compiler/types.ts | 22 +- src/harness/fourslash.ts | 99 +- src/services/compiler/references.ts | 1 - src/services/compiler/types.ts | 102 -- src/services/services.ts | 1002 +++++++---------- src/services/shims.ts | 12 - src/services/signatureHelp.ts | 2 +- .../cases/fourslash/commentsCommentParsing.ts | 276 ++--- tests/cases/fourslash/fourslash.ts | 20 +- 10 files changed, 625 insertions(+), 933 deletions(-) delete mode 100644 src/services/compiler/types.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a6ac051558..932c144ffcf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45,6 +45,14 @@ module ts { string(): string; } + // TODO this should go back in services + export function getSymbolDisplayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart { + return { + text: text, + kind: kind + }; + } + /// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics. /// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors /// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors. @@ -931,7 +939,7 @@ module ts { var displayParts: SymbolDisplayPart[] = []; return { displayParts: () => displayParts, - writeKind: (text, kind) => displayParts.push(new SymbolDisplayPart(text, kind, undefined)), + writeKind: (text, kind) => displayParts.push(getSymbolDisplayPart(text, kind)), writeSymbol: (text, symbol) => displayParts.push(symbolPart(text, symbol)), // Completely ignore indentation for display part writers. And map newlines to @@ -7699,27 +7707,27 @@ module ts { } export function spacePart() { - return new SymbolDisplayPart(" ", SymbolDisplayPartKind.space, undefined); + return getSymbolDisplayPart(" ", SymbolDisplayPartKind.space, undefined); } export function keywordPart(kind: SyntaxKind) { - return new SymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.keyword, undefined); + return getSymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.keyword, undefined); } export function punctuationPart(kind: SyntaxKind) { - return new SymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation, undefined); + return getSymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation, undefined); } export function operatorPart(kind: SyntaxKind) { - return new SymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.operator, undefined); + return getSymbolDisplayPart(tokenToString(kind), SymbolDisplayPartKind.operator, undefined); } export function textPart(text: string) { - return new SymbolDisplayPart(text, SymbolDisplayPartKind.text, undefined); + return getSymbolDisplayPart(text, SymbolDisplayPartKind.text, undefined); } export function symbolPart(text: string, symbol: Symbol) { - return new SymbolDisplayPart(text, displayPartKind(symbol), symbol) + return getSymbolDisplayPart(text, displayPartKind(symbol), symbol) } function displayPartKind(symbol: Symbol): SymbolDisplayPartKind { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e024beb12ab..54ec0d23d15 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1190,22 +1190,9 @@ module ts { verticalTab = 0x0B, // \v } - export class SymbolDisplayPart { - constructor(public text: string, - public kind: SymbolDisplayPartKind, - public symbol: Symbol) { - } - - public toJSON() { - return { - text: this.text, - kind: SymbolDisplayPartKind[this.kind] - }; - } - - public static toString(parts: SymbolDisplayPart[]) { - return parts.map(p => p.text).join(""); - } + export interface SymbolDisplayPart { + text: string; + kind: SymbolDisplayPartKind; } export enum SymbolDisplayPartKind { @@ -1215,20 +1202,17 @@ module ts { fieldName, interfaceName, keyword, - labelName, lineBreak, numericLiteral, stringLiteral, localName, methodName, moduleName, - namespaceName, operator, parameterName, propertyName, punctuation, space, - anonymousTypeIndicator, text, typeParameterName, enumMemberName, diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 6a9fa4aa48f..865eace8739 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -523,17 +523,17 @@ module FourSlash { } } - public verifyMemberListContains(symbol: string, type?: string, docComment?: string, fullSymbolName?: string, kind?: string) { + public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) { this.scenarioActions.push(''); this.scenarioActions.push(''); - if (type || docComment || fullSymbolName || kind) { + if (text || documentation || kind) { this.taoInvalidReason = 'verifyMemberListContains only supports the "symbol" parameter'; } var members = this.getMemberListAtCaret(); if (members) { - this.assertItemInCompletionList(members.entries, symbol, type, docComment, fullSymbolName, kind); + this.assertItemInCompletionList(members.entries, symbol, text, documentation, kind); } else { this.raiseError("Expected a member list, but none was provided"); @@ -632,9 +632,9 @@ module FourSlash { } } - public verifyCompletionListContains(symbol: string, type?: string, docComment?: string, fullSymbolName?: string, kind?: string) { + public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { var completions = this.getCompletionListAtCaret(); - this.assertItemInCompletionList(completions.entries, symbol, type, docComment, fullSymbolName, kind); + this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind); } public verifyCompletionListDoesNotContain(symbol: string) { @@ -647,19 +647,15 @@ module FourSlash { } } - public verifyCompletionEntryDetails(entryName: string, type: string, docComment?: string, fullSymbolName?: string, kind?: string) { + public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) { this.taoInvalidReason = 'verifyCompletionEntryDetails NYI'; var details = this.getCompletionEntryDetails(entryName); - assert.equal(details.type, type); + assert.equal(ts.displayPartsToString(details.displayParts), expectedText); - if (docComment != undefined) { - assert.equal(details.docComment, docComment); - } - - if (fullSymbolName !== undefined) { - assert.equal(details.fullSymbolName, fullSymbolName); + if (expectedDocumentation != undefined) { + assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation); } if (kind !== undefined) { @@ -758,49 +754,35 @@ module FourSlash { return this.languageService.getImplementorsAtPosition(this.activeFile.fileName, this.currentCaretPosition); } - public verifyQuickInfo(negative: boolean, expectedTypeName?: string, docComment?: string, symbolName?: string, kind?: string) { - [expectedTypeName, docComment, symbolName, kind].forEach(str => { + public verifyQuickInfo(negative: boolean, expectedText?: string, expectedDocumentation?: string) { + [expectedText, expectedDocumentation].forEach(str => { if (str) { this.scenarioActions.push(''); this.scenarioActions.push(''); } }); - var actualQuickInfo = this.languageService.getTypeAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var actualQuickInfoMemberName = actualQuickInfo ? actualQuickInfo.memberName.toString() : ""; - var actualQuickInfoDocComment = actualQuickInfo ? actualQuickInfo.docComment : ""; - var actualQuickInfoSymbolName = actualQuickInfo ? actualQuickInfo.fullSymbolName : ""; - var actualQuickInfoKind = actualQuickInfo ? actualQuickInfo.kind : ""; + var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + var actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; + var actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; function assertionMessage(msg: string) { return "\nMarker: " + currentTestState.lastKnownMarker + "\nChecking: " + msg + "\n\n"; } if (negative) { - if (expectedTypeName !== undefined) { - assert.notEqual(actualQuickInfoMemberName, expectedTypeName, assertionMessage("quick info member name")); + if (expectedText !== undefined) { + assert.notEqual(actualQuickInfoText, expectedText, assertionMessage("quick info text")); } - if (docComment != undefined) { - assert.notEqual(actualQuickInfoDocComment, docComment, assertionMessage("quick info doc comment")); - } - if (symbolName !== undefined) { - assert.notEqual(actualQuickInfoSymbolName, symbolName, assertionMessage("quick info symbol name")); - } - if (kind !== undefined) { - assert.notEqual(actualQuickInfoKind, kind, assertionMessage("quick info kind")); + if (expectedDocumentation != undefined) { + assert.notEqual(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc comment")); } } else { - if (expectedTypeName !== undefined) { - assert.equal(actualQuickInfoMemberName, expectedTypeName, assertionMessage("quick info member")); + if (expectedText !== undefined) { + assert.equal(actualQuickInfoText, expectedText, assertionMessage("quick info text")); } - if (docComment != undefined) { - assert.equal(actualQuickInfoDocComment, docComment, assertionMessage("quick info doc")); - } - if (symbolName !== undefined) { - assert.equal(actualQuickInfoSymbolName, symbolName, assertionMessage("quick info symbol name")); - } - if (kind !== undefined) { - assert.equal(actualQuickInfoKind, kind, assertionMessage("quick info kind")); + if (expectedDocumentation != undefined) { + assert.equal(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc")); } } } @@ -808,7 +790,7 @@ module FourSlash { public verifyQuickInfoExists(negative: number) { this.taoInvalidReason = 'verifyQuickInfoExists NYI'; - var actualQuickInfo = this.languageService.getTypeAtPosition(this.activeFile.fileName, this.currentCaretPosition); + var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (negative) { if (actualQuickInfo) { this.raiseError('verifyQuickInfoExists failed. Expected quick info NOT to exist'); @@ -826,9 +808,9 @@ module FourSlash { var help = this.getActiveSignatureHelpItem(); assert.equal( - ts.SymbolDisplayPart.toString(help.prefixDisplayParts) + - help.parameters.map(p => ts.SymbolDisplayPart.toString(p.displayParts)).join(ts.SymbolDisplayPart.toString(help.separatorDisplayParts)) + - ts.SymbolDisplayPart.toString(help.suffixDisplayParts), expected); + ts.displayPartsToString(help.prefixDisplayParts) + + help.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(ts.displayPartsToString(help.separatorDisplayParts)) + + ts.displayPartsToString(help.suffixDisplayParts), expected); } public verifyCurrentParameterIsVariable(isVariable: boolean) { @@ -852,7 +834,7 @@ module FourSlash { var activeSignature = this.getActiveSignatureHelpItem(); var activeParameter = this.getActiveParameter(); - assert.equal(ts.SymbolDisplayPart.toString(activeParameter.displayParts), parameter); + assert.equal(ts.displayPartsToString(activeParameter.displayParts), parameter); } public verifyCurrentParameterHelpDocComment(docComment: string) { @@ -1054,7 +1036,7 @@ module FourSlash { } public printCurrentQuickInfo() { - var quickInfo = this.languageService.getTypeAtPosition(this.activeFile.fileName, this.currentCaretPosition); + var quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); Harness.IO.log(JSON.stringify(quickInfo)); } @@ -1710,7 +1692,7 @@ module FourSlash { } for (i = 0; i < positions.length; i++) { - var nameOf = (type: ts.TypeInfo) => type ? type.fullSymbolName : '(none)'; + var nameOf = (type: ts.QuickInfo) => type ? ts.displayPartsToString(type.displayParts) : '(none)'; var pullName: string, refName: string; var anyFailed = false; @@ -1718,7 +1700,7 @@ module FourSlash { var errMsg = ''; try { - var pullType = this.languageService.getTypeAtPosition(this.activeFile.fileName, positions[i]); + var pullType = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, positions[i]); pullName = nameOf(pullType); } catch (err1) { errMsg = 'Failed to get pull type check. Exception: ' + err1 + '\r\n'; @@ -1728,7 +1710,7 @@ module FourSlash { } try { - var referenceType = referenceLanguageService.getTypeAtPosition(this.activeFile.fileName, positions[i]); + var referenceType = referenceLanguageService.getQuickInfoAtPosition(this.activeFile.fileName, positions[i]); refName = nameOf(referenceType); } catch (err2) { errMsg = 'Failed to get full type check. Exception: ' + err2 + '\r\n'; @@ -1980,28 +1962,25 @@ module FourSlash { return result; } - private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, type?: string, docComment?: string, fullSymbolName?: string, kind?: string) { + private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string) { this.scenarioActions.push(''); this.scenarioActions.push(''); - if (type || docComment || fullSymbolName || kind) { + if (text || documentation || kind) { this.taoInvalidReason = 'assertItemInCompletionList only supports the "name" parameter'; } for (var i = 0; i < items.length; i++) { var item = items[i]; if (item.name == name) { - if (docComment != undefined || type !== undefined || fullSymbolName !== undefined) { + if (documentation != undefined || text !== undefined) { var details = this.getCompletionEntryDetails(item.name); - if (docComment != undefined) { - assert.equal(details.docComment, docComment); + if (documentation != undefined) { + assert.equal(ts.displayPartsToString(details.documentation), documentation); } - if (type !== undefined) { - assert.equal(details.type, type); - } - if (fullSymbolName !== undefined) { - assert.equal(details.fullSymbolName, fullSymbolName); + if (text !== undefined) { + assert.equal(ts.displayPartsToString(details.displayParts), text); } } @@ -2015,7 +1994,7 @@ module FourSlash { var itemsString = items.map((item) => JSON.stringify({ name: item.name, kind: item.kind })).join(",\n"); - this.raiseError('Expected "' + JSON.stringify({ name: name, type: type, docComment: docComment, fullSymbolName: fullSymbolName, kind: kind }) + '" to be in list [' + itemsString + ']'); + this.raiseError('Expected "' + JSON.stringify({ name: name, text: text, documentation: documentation, kind: kind }) + '" to be in list [' + itemsString + ']'); } private findFile(indexOrName: any) { diff --git a/src/services/compiler/references.ts b/src/services/compiler/references.ts index 07ec0fa6043..b2d605d595f 100644 --- a/src/services/compiler/references.ts +++ b/src/services/compiler/references.ts @@ -12,7 +12,6 @@ ///// ///// ///// -///// ///// ///// ///// diff --git a/src/services/compiler/types.ts b/src/services/compiler/types.ts deleted file mode 100644 index 28bef81629b..00000000000 --- a/src/services/compiler/types.ts +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -/// - -module TypeScript { - export class MemberName { - public prefix: string = ""; - public suffix: string = ""; - - public isString() { return false; } - public isArray() { return false; } - public isMarker() { return !this.isString() && !this.isArray(); } - - public toString(): string { - return MemberName.memberNameToString(this); - } - - static memberNameToString(memberName: MemberName, markerInfo?: number[], markerBaseLength: number = 0): string { - var result = memberName.prefix; - - if (memberName.isString()) { - result += (memberName).text; - } - else if (memberName.isArray()) { - var ar = memberName; - for (var index = 0; index < ar.entries.length; index++) { - if (ar.entries[index].isMarker()) { - if (markerInfo) { - markerInfo.push(markerBaseLength + result.length); - } - continue; - } - - result += MemberName.memberNameToString(ar.entries[index], markerInfo, markerBaseLength + result.length); - result += ar.delim; - } - } - - result += memberName.suffix; - return result; - } - - static create(text: string): MemberName; - static create(entry: MemberName, prefix: string, suffix: string): MemberName; - static create(arg1: any, arg2?: any, arg3?: any): MemberName { - if (typeof arg1 === "string") { - return new MemberNameString(arg1); - } - else { - var result = new MemberNameArray(); - if (arg2) - result.prefix = arg2; - if (arg3) - result.suffix = arg3; - result.entries.push(arg1); - return result; - } - } - } - - export class MemberNameString extends MemberName { - constructor(public text: string) { - super(); - } - - public isString() { return true; } - } - - export class MemberNameArray extends MemberName { - public delim: string = ""; - public entries: MemberName[] = []; - - public isArray() { return true; } - - public add(entry: MemberName) { - this.entries.push(entry); - } - - public addAll(entries: MemberName[]) { - for (var i = 0 ; i < entries.length; i++) { - this.entries.push(entries[i]); - } - } - - constructor() { - super(); - } - } -} \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index 4662f0c75c3..2ef809cb68f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -23,7 +23,6 @@ /// /// /// -/// /// module ts { @@ -47,7 +46,7 @@ module ts { getFlags(): SymbolFlags; getName(): string; getDeclarations(): Declaration[]; - getDocumentationComment(): string; + getDocumentationComment(): SymbolDisplayPart[]; } export interface Type { @@ -228,7 +227,7 @@ module ts { // Undefined is used to indicate the value has not been computed. If, after computing, the // symbol has no doc comment, then the empty string will be returned. - documentationComment: string; + documentationComment: SymbolDisplayPart[]; constructor(flags: SymbolFlags, name: string) { this.flags = flags; @@ -247,154 +246,294 @@ module ts { return this.declarations; } - getDocumentationComment(): string { + getDocumentationComment(): SymbolDisplayPart[] { if (this.documentationComment === undefined) { - var lines: string[] = []; - - // Get the doc comments from all the declarations of this symbol, and merge them - // into one single doc comment. - var declarations = this.getDeclarations(); - if (declarations) { - for (var i = 0, n = declarations.length; i < n; i++) { - this.processDocumentationCommentDeclaration(lines, declarations[i]); + this.documentationComment = []; + var docComments = getJsDocCommentsSeparatedByNewLines(this); + ts.forEach(docComments, docComment => { + if (this.documentationComment.length) { + this.documentationComment.push(getSymbolDisplayPart("\n", SymbolDisplayPartKind.lineBreak)); } - } - - // TODO: get the newline info from the host. - this.documentationComment = lines.join("\r\n"); + this.documentationComment.push(docComment); + }); } return this.documentationComment; - } - private processDocumentationCommentDeclaration(lines: string[], declaration: Node) { - var commentRanges = getLeadingCommentRangesOfNode(declaration); - if (commentRanges) { - var sourceFile = declaration.getSourceFile(); + function getJsDocCommentsSeparatedByNewLines(symbol: Symbol) { + var paramTag = "@param"; + var jsDocCommentParts: SymbolDisplayPart[] = []; - for (var i = 0, n = commentRanges.length; i < n; i++) { - this.processDocumentationCommentRange( - lines, sourceFile, commentRanges[i]); + ts.forEach(symbol.declarations, declaration => { + var sourceFileOfDeclaration = getSourceFileOfNode(declaration); + // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments + if (declaration.kind === SyntaxKind.Parameter) { + ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { + var cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + if (cleanedParamJsDocComment) { + jsDocCommentParts.push.apply(jsDocCommentParts, cleanedParamJsDocComment); + } + }); + } + + // Get the cleaned js doc comment text from the declaration + ts.forEach(getJsDocCommentTextRange( + declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { + var cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + if (cleanedJsDocComment) { + jsDocCommentParts.push.apply(jsDocCommentParts, cleanedJsDocComment); + } + }); + }); + + return jsDocCommentParts; + + function getJsDocCommentTextRange(node: Node, sourceFile: SourceFile): TextRange[] { + return ts.map(getJsDocComments(node, sourceFile), + jsDocComment => { + return { + pos: jsDocComment.pos + "/*".length, // Consume /* from the comment + end: jsDocComment.end - "*/".length // Trim off comment end indicator + }; + }); + } + + function consumeWhiteSpacesOnTheLine(pos: number, end: number, sourceFile: SourceFile, maxSpacesToRemove?: number) { + if (maxSpacesToRemove !== undefined) { + end = Math.min(end, pos + maxSpacesToRemove); + } + + for (; pos < end; pos++) { + var ch = sourceFile.text.charCodeAt(pos); + if (!isWhiteSpace(ch) || isLineBreak(ch)) { + // Either found lineBreak or non whiteSpace + return pos; + } + } + + return end; + } + + function consumeLineBreaks(pos: number, end: number, sourceFile: SourceFile) { + while (pos < end && isLineBreak(sourceFile.text.charCodeAt(pos))) { + pos++; + } + + return pos; + } + + function isName(pos: number, end: number, sourceFile: SourceFile, name: string) { + return pos + name.length < end && + sourceFile.text.substr(pos, name.length) === name && + isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)); + } + + function isParamTag(pos: number, end: number, sourceFile: SourceFile) { + // If it is @param tag + return isName(pos, end, sourceFile, paramTag); + } + + function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { + var spacesToRemoveAfterAsterisk: number; + var docComments: SymbolDisplayPart[] = []; + var isInParamTag = false; + + while (pos < end) { + var docCommentTextOfLine = ""; + // First consume leading white space + pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile); + + // If the comment starts with '*' consume the spaces on this line + if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { + var lineStartPos = pos + 1; + pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); + + // Set the spaces to remove after asterisk as margin if not already set + if (spacesToRemoveAfterAsterisk === undefined && pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { + spacesToRemoveAfterAsterisk = pos - lineStartPos; + } + } + else if (spacesToRemoveAfterAsterisk === undefined) { + spacesToRemoveAfterAsterisk = 0; + } + + // Analyse text on this line + while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { + var ch = sourceFile.text.charAt(pos); + if (ch === "@") { + // If it is @param tag + if (isParamTag(pos, end, sourceFile)) { + isInParamTag = true; + pos += paramTag.length; + continue; + } + else { + isInParamTag = false; + } + } + + // Add the ch to doc text if we arent in param tag + if (!isInParamTag) { + docCommentTextOfLine += ch; + } + + // Scan next character + pos++; + } + + // Continue with next line + pos = consumeLineBreaks(pos, end, sourceFile); + if (docCommentTextOfLine) { + docComments.push(textPart(docCommentTextOfLine)); + } + } + + return docComments; + } + + function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { + var paramHelpStringMargin: number; + var paramDocComments: SymbolDisplayPart[] = []; + while (pos < end) { + if (isParamTag(pos, end, sourceFile)) { + // Consume leading spaces + pos = consumeWhiteSpaces(pos + paramTag.length); + if (pos >= end) { + break; + } + + // Ignore type expression + if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { + pos++; + for (var curlies = 1; pos < end; pos++) { + var charCode = sourceFile.text.charCodeAt(pos); + + // { character means we need to find another } to match the found one + if (charCode === CharacterCodes.openBrace) { + curlies++; + continue; + } + + // } char + if (charCode === CharacterCodes.closeBrace) { + curlies--; + if (curlies === 0) { + // We do not have any more } to match the type expression is ignored completely + pos++; + break; + } + else { + // there are more { to be matched with } + continue; + } + } + + // Found start of another tag + if (charCode === CharacterCodes.at) { + break; + } + } + + // Consume white spaces + pos = consumeWhiteSpaces(pos); + if (pos >= end) { + break; + } + } + + // Parameter name + if (isName(pos, end, sourceFile, symbol.name)) { + // Found the parameter we are looking for consume white spaces + pos = consumeWhiteSpaces(pos + symbol.name.length); + if (pos >= end) { + break; + } + + var paramHelpString = ""; + var firstLineParamHelpStringPos = pos; + while (pos < end) { + var ch = sourceFile.text.charCodeAt(pos); + + // at line break, set this comment line text and go to next line + if (isLineBreak(ch)) { + if (paramHelpString) { + paramDocComments.push(textPart(paramHelpString)); + paramHelpString = ""; + } + + // Get the pos after cleaning start of the line + setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos); + continue; + } + + // Done scanning param help string - next tag found + if (ch === CharacterCodes.at) { + break; + } + + paramHelpString += sourceFile.text.charAt(pos); + + // Go to next character + pos++; + } + + // If there is param help text, add it top the doc comments + if (paramHelpString) { + paramDocComments.push(textPart(paramHelpString)); + } + paramHelpStringMargin = undefined; + } + + // If this is the start of another tag, continue with the loop in seach of param tag with symbol name + if (sourceFile.text.charCodeAt(pos) === CharacterCodes.at) { + continue; + } + } + + // Next character + pos++; + } + + return paramDocComments; + + function consumeWhiteSpaces(pos: number) { + while (pos < end && isWhiteSpace(sourceFile.text.charCodeAt(pos))) { + pos++; + } + + return pos; + } + + function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos: number) { + // Get the pos after consuming line breaks + pos = consumeLineBreaks(pos, end, sourceFile); + if (pos >= end) { + return; + } + + if (paramHelpStringMargin === undefined) { + paramHelpStringMargin = sourceFile.getLineAndCharacterFromPosition(firstLineParamHelpStringPos).character - 1; + } + + // Now consume white spaces max + var startOfLinePos = pos; + pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); + if (pos >= end) { + return; + } + + var consumedSpaces = pos - startOfLinePos; + if (consumedSpaces < paramHelpStringMargin) { + var ch = sourceFile.text.charCodeAt(pos); + if (ch === CharacterCodes.asterisk) { + // Consume more spaces after asterisk + pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); + } + } + } } } } - - private processDocumentationCommentRange(lines: string[], sourceFile: SourceFile, commentRange: CommentRange) { - // We only care about well-formed /** */ comments - if (commentRange.end - commentRange.pos > "/**/".length && - sourceFile.text.substr(commentRange.pos, "/**".length) === "/**" && - sourceFile.text.substr(commentRange.end - "*/".length, "*/".length) === "*/") { - - // Put a newline between each converted comment we join together. - if (lines.length) { - lines.push(""); - } - - var startLineAndChar = sourceFile.getLineAndCharacterFromPosition(commentRange.pos); - var endLineAndChar = sourceFile.getLineAndCharacterFromPosition(commentRange.end); - - if (startLineAndChar.line === endLineAndChar.line) { - // A single line doc comment. Just extract the text between the - // comment markers and add that to the doc comment we're building - // up. - lines.push(sourceFile.text.substring(commentRange.pos + "/**".length, commentRange.end - "*/".length).trim()); - } - else { - this.processMultiLineDocumentationCommentRange(sourceFile, commentRange, startLineAndChar, endLineAndChar, lines); - } - } - } - - private processMultiLineDocumentationCommentRange( - sourceFile: SourceFile, commentRange: CommentRange, - startLineAndChar: { line: number; character: number }, - endLineAndChar: { line: number; character: number }, - lines: string[]) { - - // Comment spanned multiple lines. Find the leftmost character - // position in each line, and use that to determine what we should - // trim off, and what part of the line to keep. - // i.e. if the comment looks like: - // - // /** Foo - // * Bar - // * Baz - // */ - // - // Then we'll want to add: - // Foo - // Bar - // Baz - var trimLength: number = undefined; - for (var iLine = startLineAndChar.line + 1; iLine <= endLineAndChar.line; iLine++) { - var lineStart = sourceFile.getPositionFromLineAndCharacter(iLine, /*character:*/ 1); - var lineEnd = iLine === endLineAndChar.line - ? commentRange.end - "*/".length - : sourceFile.getPositionFromLineAndCharacter(iLine + 1, 1); - var docCommentTriviaLength = this.skipDocumentationCommentTrivia(sourceFile.text, lineStart, lineEnd); - - if (trimLength === undefined || (docCommentTriviaLength && docCommentTriviaLength < trimLength)) { - trimLength = docCommentTriviaLength; - } - } - - // Add the first line in. - var firstLine = sourceFile.text.substring( - commentRange.pos + "/**".length, - sourceFile.getPositionFromLineAndCharacter(startLineAndChar.line + 1, /*character:*/ 1)).trim(); - if (firstLine !== "") { - lines.push(firstLine); - } - - // For all the lines up to the last (but not including the last), add the contents - // of the line (with the length up to the - for (var iLine = startLineAndChar.line + 1; iLine < endLineAndChar.line; iLine++) { - var line = this.trimRight(sourceFile.text.substring( - sourceFile.getPositionFromLineAndCharacter(iLine, /*character*/ 1), - sourceFile.getPositionFromLineAndCharacter(iLine + 1, /*character*/ 1))).substr(trimLength); - - lines.push(line); - } - - // Add the last line if there is any actual text before the */ - var lastLine = this.trimRight(sourceFile.text.substring( - sourceFile.getPositionFromLineAndCharacter(endLineAndChar.line, /*character:*/ 1), - commentRange.end - "*/".length)).substr(trimLength); - - if (lastLine !== "") { - lines.push(lastLine); - } - } - - private trimRight(val: string) { - return val.replace(/(\n|\r|\s)+$/, ''); - } - - private skipDocumentationCommentTrivia(text: string, lineStart: number, lineEnd: number): number { - var seenAsterisk = false; - var lineLength = lineEnd - lineStart; - for (var i = 0; i < lineLength; i++) { - var char = text.charCodeAt(i + lineStart); - if (char === CharacterCodes.asterisk && !seenAsterisk) { - // Ignore the first asterisk we see. We want to trim out the line of *'s - // commonly seen at the start of a doc comment. - seenAsterisk = true; - continue; - } - else if (isLineBreak(char)) { - // This was a blank line. Just ignore it wrt computing the leading whitespace to - // trim. - break; - } - else if (!isWhiteSpace(char)) { - // Found a real doc comment character. Keep track of it so we can determine how - // much of the doc comment leading trivia to trim off. - return i; - } - } - - return undefined; - } } class TypeObject implements Type { @@ -653,9 +792,6 @@ module ts { getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; - // Obsolete. Use getQuickInfoAtPosition instead. - getTypeAtPosition(fileName: string, position: number): TypeInfo; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TypeScript.TextSpan; getBreakpointStatementAtPosition(fileName: string, position: number): TypeScript.TextSpan; @@ -801,12 +937,6 @@ module ts { containerName: string; } - export interface MemberName { - prefix: string; - suffix: string; - text: string; - } - export interface QuickInfo { kind: string; kindModifiers: string; @@ -815,14 +945,6 @@ module ts { documentation: SymbolDisplayPart[]; } - export interface TypeInfo { - memberName: TypeScript.MemberName; - docComment: string; - fullSymbolName: string; - kind: string; - textSpan: TypeScript.TextSpan; - } - export interface RenameInfo { canRename: boolean; localizedErrorMessage: string; @@ -882,9 +1004,8 @@ module ts { name: string; kind: string; // see ScriptElementKind kindModifiers: string; // see ScriptElementKindModifier, comma separated - type: string; - fullSymbolName: string; - docComment: string; + displayParts: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[]; } export interface EmitOutput { @@ -1099,6 +1220,13 @@ module ts { owners: string[]; } + export function displayPartsToString(displayParts: SymbolDisplayPart[]) { + var result = ""; + ts.forEach(displayParts, displayPart => { + result += displayPart.text; + }); + return result; + } export function getDefaultCompilerOptions(): CompilerOptions { // Set "ES5" target by default for language service return { @@ -1622,11 +1750,6 @@ module ts { }); } - export function getSymbolDocumentationDisplayParts(symbol: Symbol): SymbolDisplayPart[] { - var documentation = symbol.getDocumentationComment(); - return documentation === "" ? [] : [new SymbolDisplayPart(documentation, SymbolDisplayPartKind.text, /*symbol:*/ null)]; - } - export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry): LanguageService { var syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); var formattingRulesProvider: TypeScript.Services.Formatting.RulesProvider; @@ -2213,298 +2336,7 @@ module ts { }; } - function getJsDocCommentOfSymbol(symbol: Symbol) { - var paramTag = "@param"; - var jsDocCommentText: string[] = []; - - ts.forEach(symbol.declarations, declaration => { - var sourceFileOfDeclaration = getSourceFileOfNode(declaration); - // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments - if (declaration.kind === SyntaxKind.Parameter) { - ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - var cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); - if (cleanedParamJsDocComment) { - jsDocCommentText.push(cleanedParamJsDocComment); - } - }); - } - - // Get the cleaned js doc comment text from the declaration - ts.forEach(getJsDocCommentTextRange( - declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - var cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); - if (cleanedJsDocComment) { - jsDocCommentText.push(cleanedJsDocComment); - } - }); - }); - - return jsDocCommentText.join("\n"); - - function getJsDocCommentTextRange(node: Node, sourceFile: SourceFile): TextRange[] { - return ts.map(getJsDocComments(node, sourceFile), - jsDocComment => { - return { - pos: jsDocComment.pos + "/*".length, // Consume /* from the comment - end: jsDocComment.end - "*/".length // Trim off comment end indicator - }; - }); - } - - function consumeWhiteSpacesOnTheLine(pos: number, end: number, sourceFile: SourceFile, maxSpacesToRemove?: number) { - if (maxSpacesToRemove !== undefined) { - end = Math.min(end, pos + maxSpacesToRemove); - } - - for (; pos < end; pos++) { - var ch = sourceFile.text.charCodeAt(pos); - if (!isWhiteSpace(ch) || isLineBreak(ch)) { - // Either found lineBreak or non whiteSpace - return pos; - } - } - - return end; - } - - function consumeLineBreaks(pos: number, end: number, sourceFile: SourceFile) { - while (pos < end && isLineBreak(sourceFile.text.charCodeAt(pos))) { - pos++; - } - - return pos; - } - - function isName(pos: number, end: number, sourceFile: SourceFile, name: string) { - return pos + name.length < end && - sourceFile.text.substr(pos, name.length) === name && - isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)); - } - - function isParamTag(pos: number, end: number, sourceFile: SourceFile) { - // If it is @param tag - return isName(pos, end, sourceFile, paramTag); - } - - function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { - var spacesToRemoveAfterAsterisk: number; - var docComments: string[] = []; - var isInParamTag = false; - - while (pos < end) { - var docCommentTextOfLine = ""; - // First consume leading white space - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile); - - // If the comment starts with '*' consume the spaces on this line - if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - var lineStartPos = pos + 1; - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); - - // Set the spaces to remove after asterisk as margin if not already set - if (spacesToRemoveAfterAsterisk === undefined && pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - spacesToRemoveAfterAsterisk = pos - lineStartPos; - } - } - else if (spacesToRemoveAfterAsterisk === undefined) { - spacesToRemoveAfterAsterisk = 0; - } - - // Analyse text on this line - while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - var ch = sourceFile.text.charAt(pos); - if (ch === "@") { - // If it is @param tag - if (isParamTag(pos, end, sourceFile)) { - isInParamTag = true; - pos += paramTag.length; - continue; - } - else { - isInParamTag = false; - } - } - - // Add the ch to doc text if we arent in param tag - if (!isInParamTag) { - docCommentTextOfLine += ch; - } - - // Scan next character - pos++; - } - - // Continue with next line - pos = consumeLineBreaks(pos, end, sourceFile); - if (docCommentTextOfLine) { - docComments.push(docCommentTextOfLine); - } - } - - return docComments.join("\n"); - } - - function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { - var paramHelpStringMargin: number; - var paramDocComments: string[] = []; - while (pos < end) { - if (isParamTag(pos, end, sourceFile)) { - // Consume leading spaces - pos = consumeWhiteSpaces(pos + paramTag.length); - if (pos >= end) { - break; - } - - // Ignore type expression - if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { - pos++; - for (var curlies = 1; pos < end; pos++) { - var charCode = sourceFile.text.charCodeAt(pos); - - // { character means we need to find another } to match the found one - if (charCode === CharacterCodes.openBrace) { - curlies++; - continue; - } - - // } char - if (charCode === CharacterCodes.closeBrace) { - curlies--; - if (curlies === 0) { - // We do not have any more } to match the type expression is ignored completely - pos++; - break; - } - else { - // there are more { to be matched with } - continue; - } - } - - // Found start of another tag - if (charCode === CharacterCodes.at) { - break; - } - } - - // Consume white spaces - pos = consumeWhiteSpaces(pos); - if (pos >= end) { - break; - } - } - - // Parameter name - if (isName(pos, end, sourceFile, symbol.name)) { - // Found the parameter we are looking for consume white spaces - pos = consumeWhiteSpaces(pos + symbol.name.length); - if (pos >= end) { - break; - } - - var paramHelpString = ""; - var firstLineParamHelpStringPos = pos; - while (pos < end) { - var ch = sourceFile.text.charCodeAt(pos); - - // at line break, set this comment line text and go to next line - if (isLineBreak(ch)) { - if (paramHelpString) { - paramDocComments.push(paramHelpString); - paramHelpString = ""; - } - - // Get the pos after cleaning start of the line - setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos); - continue; - } - - // Done scanning param help string - next tag found - if (ch === CharacterCodes.at) { - break; - } - - paramHelpString += sourceFile.text.charAt(pos); - - // Go to next character - pos++; - } - - // If there is param help text, add it top the doc comments - if (paramHelpString) { - paramDocComments.push(paramHelpString); - } - paramHelpStringMargin = undefined; - } - - // If this is the start of another tag, continue with the loop in seach of param tag with symbol name - if (sourceFile.text.charCodeAt(pos) === CharacterCodes.at) { - continue; - } - } - - // Next character - pos++; - } - - return paramDocComments.join("\n"); - - function consumeWhiteSpaces(pos: number) { - while (pos < end && isWhiteSpace(sourceFile.text.charCodeAt(pos))) { - pos++; - } - - return pos; - } - - function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos: number) { - // Get the pos after consuming line breaks - pos = consumeLineBreaks(pos, end, sourceFile); - if (pos >= end) { - return; - } - - if (paramHelpStringMargin === undefined) { - paramHelpStringMargin = sourceFile.getLineAndCharacterFromPosition(firstLineParamHelpStringPos).character - 1; - } - - // Now consume white spaces max - var startOfLinePos = pos; - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); - if (pos >= end) { - return; - } - - var consumedSpaces = pos - startOfLinePos; - if (consumedSpaces < paramHelpStringMargin) { - var ch = sourceFile.text.charCodeAt(pos); - if (ch === CharacterCodes.asterisk) { - // Consume more spaces after asterisk - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); - } - } - } - } - } - - function getTypeFormatFlags(symbolKind: ScriptElementKind) { - var typeFormatFlags = TypeFormatFlags.NoTruncation; - switch (symbolKind) { - case ScriptElementKind.functionElement: - case ScriptElementKind.memberGetAccessorElement: - case ScriptElementKind.memberSetAccessorElement: - case ScriptElementKind.memberFunctionElement: - case ScriptElementKind.constructSignatureElement: - case ScriptElementKind.callSignatureElement: - case ScriptElementKind.constructorImplementationElement: - case ScriptElementKind.constructSignatureElement: - typeFormatFlags = typeFormatFlags | TypeFormatFlags.NoArrowStyleTopLevelSignature; - } - - return typeFormatFlags; - } - - function getCompletionEntryDetails(filename: string, position: number, entryName: string) { + function getCompletionEntryDetails(filename: string, position: number, entryName: string): CompletionEntryDetails { // Note: No need to call synchronizeHostData, as we have captured all the data we need // in the getCompletionsAtPosition earlier filename = TypeScript.switchToForwardSlashes(filename); @@ -2525,9 +2357,8 @@ module ts { name: entryName, kind: completionEntry.kind, kindModifiers: completionEntry.kindModifiers, - type: session.typeChecker.typeToString(type, session.location, getTypeFormatFlags(completionEntry.kind)), - fullSymbolName: typeInfoResolver.symbolToString(symbol, session.location), - docComment: getJsDocCommentOfSymbol(symbol) + displayParts: getSymbolDisplayPartsofSymbol(symbol, getSourceFile(filename), session.location, session.typeChecker), + documentation: symbol.getDocumentationComment() }; } else { @@ -2536,9 +2367,8 @@ module ts { name: entryName, kind: ScriptElementKind.keyword, kindModifiers: ScriptElementKindModifier.none, - type: undefined, - fullSymbolName: entryName, - docComment: undefined + displayParts: [getSymbolDisplayPart(entryName, SymbolDisplayPartKind.keyword)], + documentation: undefined }; } } @@ -2649,6 +2479,123 @@ module ts { return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none; } + function getSymbolDisplayPartsofSymbol(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, typeResolver: TypeChecker): SymbolDisplayPart[] { + var displayParts: SymbolDisplayPart[] = []; + function addNewLineIfDisplayPartsExist() { + if (displayParts.length) { + displayParts.push(getSymbolDisplayPart("\n", SymbolDisplayPartKind.lineBreak)); + } + } + if (symbol.flags & SymbolFlags.Class) { + displayParts.push(keywordPart(SyntaxKind.ClassKeyword)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, sourceFile)); + } + if (symbol.flags & SymbolFlags.Interface) { + addNewLineIfDisplayPartsExist(); + displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, sourceFile)); + } + if (symbol.flags & SymbolFlags.Enum) { + addNewLineIfDisplayPartsExist(); + displayParts.push(keywordPart(SyntaxKind.EnumKeyword)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, sourceFile)); + } + if (symbol.flags & SymbolFlags.Module) { + addNewLineIfDisplayPartsExist(); + displayParts.push(keywordPart(SyntaxKind.ModuleKeyword)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, sourceFile)); + } + if (symbol.flags & SymbolFlags.TypeParameter) { + addNewLineIfDisplayPartsExist(); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(textPart("type parameter")); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, enclosingDeclaration)); + } + else { + //public static string FormatSymbolName(string name, string fullSymbolName, string kind, out bool useTypeName) + var text: string; + if (symbol.flags & SymbolFlags.Property) { + text = "property"; + } + else if (symbol.flags & SymbolFlags.EnumMember) { + text = "enum member"; + } + else if (symbol.flags & SymbolFlags.Function) { + text = "function"; + } + else if (symbol.flags & SymbolFlags.Variable) { + if (ts.forEach(symbol.declarations, declaration => declaration.kind === SyntaxKind.Parameter)) { + text = "parameter"; + } + else { + text = "var"; + } + } + else if (symbol.flags & SymbolFlags.Method) { + text = "method"; + } + else if (symbol.flags & SymbolFlags.Constructor) { + text = "constructor"; + } + else if (symbol.flags & SymbolFlags.GetAccessor) { + text = "getter"; + } + else if (symbol.flags & SymbolFlags.SetAccessor) { + text = "setter"; + } + + if (text || symbol.flags & SymbolFlags.Signature) { + addNewLineIfDisplayPartsExist(); + if (text) { + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(textPart(text)); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); + displayParts.push(spacePart()); + + displayParts.push.apply(displayParts, typeResolver.symbolToDisplayParts(symbol, enclosingDeclaration)); + } + + var type = typeResolver.getTypeOfSymbol(symbol); + if (symbol.flags & SymbolFlags.Property || + symbol.flags & SymbolFlags.Variable) { + if (type) { + displayParts.push(punctuationPart(SyntaxKind.ColonToken)); + displayParts.push(spacePart()); + displayParts.push.apply(displayParts, typeResolver.typeToDisplayParts(type, enclosingDeclaration, TypeFormatFlags.NoTruncation)); + } + } + else if (symbol.flags & SymbolFlags.Function || + symbol.flags & SymbolFlags.Method || + symbol.flags & SymbolFlags.Signature || + symbol.flags & SymbolFlags.Accessor) { + if (type) { + displayParts.push.apply(displayParts, typeResolver.typeToDisplayParts(type, enclosingDeclaration, TypeFormatFlags.NoTruncation | TypeFormatFlags.NoArrowStyleTopLevelSignature)); + } + } + else if (symbol.flags & SymbolFlags.EnumMember) { + var declaration = symbol.declarations[0]; + if (declaration.kind === SyntaxKind.EnumMember) { + var constantValue = typeResolver.getEnumMemberValue(declaration); + if (constantValue !== undefined) { + displayParts.push(spacePart()); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); + displayParts.push(spacePart()); + displayParts.push(getSymbolDisplayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral)); + } + } + } + } + } + + return displayParts; + } + function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); @@ -2664,125 +2611,15 @@ module ts { return undefined; } - var documentationParts = getSymbolDocumentationDisplayParts(symbol); - - // Having all this logic here is pretty unclean. Consider moving to the roslyn model - // where all symbol display logic is encapsulated into visitors and options. - var totalParts: SymbolDisplayPart[] = []; - - if (symbol.flags & SymbolFlags.Class) { - totalParts.push(keywordPart(SyntaxKind.ClassKeyword)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile)); - } - else if (symbol.flags & SymbolFlags.Interface) { - totalParts.push(keywordPart(SyntaxKind.InterfaceKeyword)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile)); - } - else if (symbol.flags & SymbolFlags.Enum) { - totalParts.push(keywordPart(SyntaxKind.EnumKeyword)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile)); - } - else if (symbol.flags & SymbolFlags.Module) { - totalParts.push(keywordPart(SyntaxKind.ModuleKeyword)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile)); - } - else if (symbol.flags & SymbolFlags.TypeParameter) { - totalParts.push(punctuationPart(SyntaxKind.OpenParenToken)); - totalParts.push(new SymbolDisplayPart("type parameter", SymbolDisplayPartKind.text, undefined)); - totalParts.push(punctuationPart(SyntaxKind.CloseParenToken)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol)); - } - else { - totalParts.push(punctuationPart(SyntaxKind.OpenParenToken)); - var text: string; - - if (symbol.flags & SymbolFlags.Property) { text = "property" } - else if (symbol.flags & SymbolFlags.EnumMember) { text = "enum member" } - else if (symbol.flags & SymbolFlags.Function) { text = "function" } - else if (symbol.flags & SymbolFlags.Variable) { text = "variable" } - else if (symbol.flags & SymbolFlags.Method) { text = "method" } - - if (!text) { - return undefined; - } - - totalParts.push(new SymbolDisplayPart(text, SymbolDisplayPartKind.text, undefined)); - totalParts.push(punctuationPart(SyntaxKind.CloseParenToken)); - totalParts.push(spacePart()); - - totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, getContainerNode(node))); - - var type = typeInfoResolver.getTypeOfSymbol(symbol); - - if (symbol.flags & SymbolFlags.Property || - symbol.flags & SymbolFlags.Variable) { - - if (type) { - totalParts.push(punctuationPart(SyntaxKind.ColonToken)); - totalParts.push(spacePart()); - totalParts.push.apply(totalParts, typeInfoResolver.typeToDisplayParts(type, getContainerNode(node))); - } - } - else if (symbol.flags & SymbolFlags.Function || - symbol.flags & SymbolFlags.Method) { - if (type) { - totalParts.push.apply(totalParts, typeInfoResolver.typeToDisplayParts(type, getContainerNode(node))); - } - } - else if (symbol.flags & SymbolFlags.EnumMember) { - var declaration = symbol.declarations[0]; - if (declaration.kind === SyntaxKind.EnumMember) { - var constantValue = typeInfoResolver.getEnumMemberValue(declaration); - if (constantValue !== undefined) { - totalParts.push(spacePart()); - totalParts.push(operatorPart(SyntaxKind.EqualsToken)); - totalParts.push(spacePart()); - totalParts.push(new SymbolDisplayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral, undefined)); - } - } - } - } - return { kind: getSymbolKind(symbol), kindModifiers: getSymbolModifiers(symbol), textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()), - displayParts: totalParts, - documentation: documentationParts + displayParts: getSymbolDisplayPartsofSymbol(symbol, sourceFile, getContainerNode(node), typeInfoResolver), + documentation: symbol.getDocumentationComment() }; } - function getTypeAtPosition(fileName: string, position: number): TypeInfo { - synchronizeHostData(); - - fileName = TypeScript.switchToForwardSlashes(fileName); - var sourceFile = getSourceFile(fileName); - var node = getNodeAtPosition(sourceFile, position); - if (!node) { - return undefined; - } - - var symbol = typeInfoResolver.getSymbolInfo(node); - var type = symbol && typeInfoResolver.getTypeOfSymbol(symbol); - if (type) { - var symbolKind = getSymbolKind(symbol); - return { - memberName: new TypeScript.MemberNameString(typeInfoResolver.typeToString(type, undefined, getTypeFormatFlags(symbolKind))), - docComment: getJsDocCommentOfSymbol(symbol), - fullSymbolName: typeInfoResolver.symbolToString(symbol, getContainerNode(node)), - kind: getSymbolKind(symbol), - textSpan: TypeScript.TextSpan.fromBounds(node.pos, node.end) - }; - } - - return undefined; - } - /// Goto definition function getDefinitionAtPosition(filename: string, position: number): DefinitionInfo[]{ function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo { @@ -4187,7 +4024,7 @@ module ts { var formalSignatures: FormalSignatureItemInfo[] = []; forEach(signatureHelpItems.items, signature => { - var signatureInfoString = ts.SymbolDisplayPart.toString(signature.prefixDisplayParts); + var signatureInfoString = displayPartsToString(signature.prefixDisplayParts); var parameters: FormalParameterInfo[] = []; if (signature.parameters) { @@ -4196,29 +4033,29 @@ module ts { // add the parameter to the string if (i) { - signatureInfoString += ts.SymbolDisplayPart.toString(signature.separatorDisplayParts); + signatureInfoString += displayPartsToString(signature.separatorDisplayParts); } var start = signatureInfoString.length; - signatureInfoString += ts.SymbolDisplayPart.toString(parameter.displayParts); + signatureInfoString += displayPartsToString(parameter.displayParts); var end = signatureInfoString.length - 1; // add the parameter to the list parameters.push({ name: parameter.name, isVariable: i == n - 1 && signature.isVariadic, - docComment: ts.SymbolDisplayPart.toString(parameter.documentation), + docComment: displayPartsToString(parameter.documentation), minChar: start, limChar: end }); } } - signatureInfoString += ts.SymbolDisplayPart.toString(signature.suffixDisplayParts); + signatureInfoString += displayPartsToString(signature.suffixDisplayParts); formalSignatures.push({ signatureInfo: signatureInfoString, - docComment: ts.SymbolDisplayPart.toString(signature.documentation), + docComment: displayPartsToString(signature.documentation), parameters: parameters, typeParameters: [], }); @@ -4864,7 +4701,6 @@ module ts { getSemanticClassifications: getSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, - getTypeAtPosition: getTypeAtPosition, getSignatureHelpItems: getSignatureHelpItems, getQuickInfoAtPosition: getQuickInfoAtPosition, getDefinitionAtPosition: getDefinitionAtPosition, diff --git a/src/services/shims.ts b/src/services/shims.ts index 45ac958935e..ac3e24054b4 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -85,9 +85,6 @@ module ts { getQuickInfoAtPosition(fileName: string, position: number): string; - // Obsolete. Use getQuickInfoAtPosition instead. - getTypeAtPosition(fileName: string, position: number): string; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string; getBreakpointStatementAtPosition(fileName: string, position: number): string; @@ -577,15 +574,6 @@ module ts { } - public getTypeAtPosition(fileName: string, position: number): string { - return this.forwardJSONCall( - "getTypeAtPosition('" + fileName + "', " + position + ")", - () => { - var typeInfo = this.languageService.getTypeAtPosition(fileName, position); - return typeInfo; - }); - } - /// NAMEORDOTTEDNAMESPAN /** diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 796472c030e..bef1efe4295 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -273,7 +273,7 @@ module ts.SignatureHelp { return { name: p.name, - documentation: getSymbolDocumentationDisplayParts(p), + documentation: p.getDocumentationComment(), displayParts: displayParts, isOptional: isOptional }; diff --git a/tests/cases/fourslash/commentsCommentParsing.ts b/tests/cases/fourslash/commentsCommentParsing.ts index f02b489a6ee..09579cf98f2 100644 --- a/tests/cases/fourslash/commentsCommentParsing.ts +++ b/tests/cases/fourslash/commentsCommentParsing.ts @@ -203,298 +203,298 @@ ////} goTo.marker('1'); -//verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); goTo.marker('1q'); -verify.quickInfoIs("(): void", "", "simple", "function"); +verify.quickInfoIs("(function) simple(): void", ""); goTo.marker('2'); -//verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); goTo.marker('2q'); -verify.quickInfoIs("(): void", "", "multiLine", "function"); +verify.quickInfoIs("(function) multiLine(): void", ""); goTo.marker('3'); -//verify.currentSignatureHelpDocCommentIs("this is eg of single line jsdoc style comment "); +verify.currentSignatureHelpDocCommentIs("this is eg of single line jsdoc style comment "); goTo.marker('3q'); -verify.quickInfoIs("(): void", "this is eg of single line jsdoc style comment ", "jsDocSingleLine", "function"); +verify.quickInfoIs("(function) jsDocSingleLine(): void", "this is eg of single line jsdoc style comment "); goTo.marker('4'); -//verify.currentSignatureHelpDocCommentIs("this is multiple line jsdoc stule comment\nNew line1\nNew Line2"); +verify.currentSignatureHelpDocCommentIs("this is multiple line jsdoc stule comment\nNew line1\nNew Line2"); goTo.marker('4q'); -verify.quickInfoIs("(): void", "this is multiple line jsdoc stule comment\nNew line1\nNew Line2", "jsDocMultiLine", "function"); +verify.quickInfoIs("(function) jsDocMultiLine(): void", "this is multiple line jsdoc stule comment\nNew line1\nNew Line2"); goTo.marker('5'); -//verify.currentSignatureHelpDocCommentIs("this is multiple line jsdoc stule comment\nNew line1\nNew Line2\nShoul mege this line as well\nand this too\nAnother this one too"); +verify.currentSignatureHelpDocCommentIs("this is multiple line jsdoc stule comment\nNew line1\nNew Line2\nShoul mege this line as well\nand this too\nAnother this one too"); goTo.marker('5q'); -verify.quickInfoIs("(): void", "this is multiple line jsdoc stule comment\nNew line1\nNew Line2\nShoul mege this line as well\nand this too\nAnother this one too", "jsDocMultiLineMerge", "function"); +verify.quickInfoIs("(function) jsDocMultiLineMerge(): void", "this is multiple line jsdoc stule comment\nNew line1\nNew Line2\nShoul mege this line as well\nand this too\nAnother this one too"); goTo.marker('6'); -//verify.currentSignatureHelpDocCommentIs("jsdoc comment "); +verify.currentSignatureHelpDocCommentIs("jsdoc comment "); goTo.marker('6q'); -verify.quickInfoIs("(): void", "jsdoc comment ", "jsDocMixedComments1", "function"); +verify.quickInfoIs("(function) jsDocMixedComments1(): void", "jsdoc comment "); goTo.marker('7'); -//verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); +verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); goTo.marker('7q'); -verify.quickInfoIs("(): void", "jsdoc comment \nanother jsDocComment", "jsDocMixedComments2", "function"); +verify.quickInfoIs("(function) jsDocMixedComments2(): void", "jsdoc comment \nanother jsDocComment"); goTo.marker('8'); -//verify.currentSignatureHelpDocCommentIs("jsdoc comment \n* another jsDocComment"); +verify.currentSignatureHelpDocCommentIs("jsdoc comment \n* another jsDocComment"); goTo.marker('8q'); -verify.quickInfoIs("(): void", "jsdoc comment \n* another jsDocComment", "jsDocMixedComments3", "function"); +verify.quickInfoIs("(function) jsDocMixedComments3(): void", "jsdoc comment \n* another jsDocComment"); goTo.marker('9'); -//verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); +verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); goTo.marker('9q'); -verify.quickInfoIs("(): void", "jsdoc comment \nanother jsDocComment", "jsDocMixedComments4", "function"); +verify.quickInfoIs("(function) jsDocMixedComments4(): void", "jsdoc comment \nanother jsDocComment"); goTo.marker('10'); -//verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); +verify.currentSignatureHelpDocCommentIs("jsdoc comment \nanother jsDocComment"); goTo.marker('10q'); -verify.quickInfoIs("(): void", "jsdoc comment \nanother jsDocComment", "jsDocMixedComments5", "function"); +verify.quickInfoIs("(function) jsDocMixedComments5(): void", "jsdoc comment \nanother jsDocComment"); goTo.marker('11'); -//verify.currentSignatureHelpDocCommentIs("another jsDocComment\njsdoc comment "); +verify.currentSignatureHelpDocCommentIs("another jsDocComment\njsdoc comment "); goTo.marker('11q'); -verify.quickInfoIs("(): void", "another jsDocComment\njsdoc comment ", "jsDocMixedComments6", "function"); +verify.quickInfoIs("(function) jsDocMixedComments6(): void", "another jsDocComment\njsdoc comment "); goTo.marker('12'); -//verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); goTo.marker('12q'); -verify.quickInfoIs("(): void", "", "noHelpComment1", "function"); +verify.quickInfoIs("(function) noHelpComment1(): void", ""); goTo.marker('13'); -//verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); goTo.marker('13q'); -verify.quickInfoIs("(): void", "", "noHelpComment2", "function"); +verify.quickInfoIs("(function) noHelpComment2(): void", ""); goTo.marker('14'); -//verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); goTo.marker('14q'); -verify.quickInfoIs("(): void", "", "noHelpComment3", "function"); +verify.quickInfoIs("(function) noHelpComment3(): void", ""); goTo.marker('15'); -verify.completionListContains("sum", "(a: number, b: number): number", "Adds two integers and returns the result", "sum", "function"); +verify.completionListContains("sum", "(function) sum(a: number, b: number): number", "Adds two integers and returns the result"); goTo.marker('16'); -//verify.currentSignatureHelpDocCommentIs("Adds two integers and returns the result"); -//verify.currentParameterHelpArgumentDocCommentIs("first number"); +verify.currentSignatureHelpDocCommentIs("Adds two integers and returns the result"); +verify.currentParameterHelpArgumentDocCommentIs("first number"); goTo.marker('16q'); -verify.quickInfoIs("(a: number, b: number): number", "Adds two integers and returns the result", "sum", "function"); +verify.quickInfoIs("(function) sum(a: number, b: number): number", "Adds two integers and returns the result"); goTo.marker('16aq'); -verify.quickInfoIs("number", "first number", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", "first number"); goTo.marker('17'); -//verify.currentSignatureHelpDocCommentIs("Adds two integers and returns the result"); -//verify.currentParameterHelpArgumentDocCommentIs("second number"); +verify.currentSignatureHelpDocCommentIs("Adds two integers and returns the result"); +verify.currentParameterHelpArgumentDocCommentIs("second number"); goTo.marker('17aq'); -verify.quickInfoIs("number", "second number", "b", "parameter"); +verify.quickInfoIs("(parameter) b: number", "second number"); goTo.marker('18'); -verify.quickInfoIs("number", "first number", "a", "parameter"); -verify.completionListContains("a", "number", "first number", "a", "parameter"); -verify.completionListContains("b", "number", "second number", "b", "parameter"); +verify.quickInfoIs("(parameter) a: number", "first number"); +verify.completionListContains("a", "(parameter) a: number", "first number"); +verify.completionListContains("b", "(parameter) b: number", "second number"); goTo.marker('19'); -//verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); -//verify.currentParameterHelpArgumentDocCommentIs("first number"); +verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); +verify.currentParameterHelpArgumentDocCommentIs("first number"); goTo.marker('19q'); -verify.quickInfoIs("(a: number, b: number, c?: number, d?: any, e?: any): void", "This is multiplication function\n@anotherTag\n@anotherTag", "multiply", "function"); +verify.quickInfoIs("(function) multiply(a: number, b: number, c?: number, d?: any, e?: any): void", "This is multiplication function\n@anotherTag\n@anotherTag"); goTo.marker('19aq'); -verify.quickInfoIs("number", "first number", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", "first number"); goTo.marker('20'); -//verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('20aq'); -verify.quickInfoIs("number", "", "b", "parameter"); +verify.quickInfoIs("(parameter) b: number", ""); goTo.marker('21'); -//verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); -//verify.currentParameterHelpArgumentDocCommentIs("{"); +verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); +verify.currentParameterHelpArgumentDocCommentIs("{"); goTo.marker('21aq'); -verify.quickInfoIs("number", "{", "c", "parameter"); +verify.quickInfoIs("(parameter) c: number", "{"); goTo.marker('22'); -//verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('22aq'); -verify.quickInfoIs("any", "", "d", "parameter"); +verify.quickInfoIs("(parameter) d: any", ""); goTo.marker('23'); -//verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); -//verify.currentParameterHelpArgumentDocCommentIs("LastParam "); +verify.currentSignatureHelpDocCommentIs("This is multiplication function\n@anotherTag\n@anotherTag"); +verify.currentParameterHelpArgumentDocCommentIs("LastParam "); goTo.marker('23aq'); -verify.quickInfoIs("any", "LastParam ", "e", "parameter"); +verify.quickInfoIs("(parameter) e: any", "LastParam "); goTo.marker('24'); -verify.completionListContains("aOrb", "any", "", "aOrb", "parameter"); -verify.completionListContains("opt", "any", "optional parameter", "opt", "parameter"); +verify.completionListContains("aOrb", "(parameter) aOrb: any", ""); +verify.completionListContains("opt", "(parameter) opt: any", "optional parameter"); goTo.marker('25'); -//verify.currentSignatureHelpDocCommentIs("fn f1 with number"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("fn f1 with number"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('25q'); // TODO: type name format for the overload //verify.quickInfoIs("(a: number): any (+ 1 overload(s))", "fn f1 with number", "f1", "function"); -verify.quickInfoIs(undefined, "fn f1 with number", "f1", "function"); +verify.quickInfoIs(undefined, "fn f1 with number"); goTo.marker('25aq'); -verify.quickInfoIs("number", "", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", ""); goTo.marker('26'); -//verify.currentSignatureHelpDocCommentIs(""); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs(""); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('26q'); // TODO: Selection of correct overload and doc comment only from that overload //verify.quickInfoIs("(b: string): any (+ 1 overload(s))", "", "f1", "function"); goTo.marker('26aq'); -verify.quickInfoIs("string", "", "b", "parameter"); +verify.quickInfoIs("(parameter) b: string", ""); goTo.marker('27'); -verify.completionListContains("multiply", "(a: number, b: number, c?: number, d?: any, e?: any): void", "This is multiplication function\n@anotherTag\n@anotherTag", "multiply", "function"); +verify.completionListContains("multiply", "(function) multiply(a: number, b: number, c?: number, d?: any, e?: any): void", "This is multiplication function\n@anotherTag\n@anotherTag"); // TODO: overload formatting //verify.completionListContains("f1", "(a: number): any (+ 1 overload(s))", "fn f1 with number", "f1", "function"); -verify.completionListContains("f1", undefined, "fn f1 with number", "f1", "function"); +verify.completionListContains("f1", undefined, "fn f1 with number"); goTo.marker('28'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('28q'); -verify.quickInfoIs("(a: number, b: number, c?: () => string, d?: () => string, e?: () => string, f?: () => string): void", "This is subtract function", "subtract", "function"); +verify.quickInfoIs("(function) subtract(a: number, b: number, c?: () => string, d?: () => string, e?: () => string, f?: () => string): void", "This is subtract function"); goTo.marker('28aq'); -verify.quickInfoIs("number", "", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", ""); goTo.marker('29'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs("this is about b"); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs("this is about b"); goTo.marker('29aq'); -verify.quickInfoIs("number", "this is about b", "b", "parameter"); +verify.quickInfoIs("(parameter) b: number", "this is about b"); goTo.marker('30'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs("this is optional param c"); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs("this is optional param c"); goTo.marker('30aq'); -verify.quickInfoIs("() => string", "this is optional param c", "c", "parameter"); +verify.quickInfoIs("(parameter) c: () => string", "this is optional param c"); goTo.marker('31'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('31aq'); -verify.quickInfoIs("() => string", "", "d", "parameter"); +verify.quickInfoIs("(parameter) d: () => string", ""); goTo.marker('32'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs("this is optional param e"); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs("this is optional param e"); goTo.marker('32aq'); -verify.quickInfoIs("() => string", "this is optional param e", "e", "parameter"); +verify.quickInfoIs("(parameter) e: () => string", "this is optional param e"); goTo.marker('33'); -//verify.currentSignatureHelpDocCommentIs("This is subtract function"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("This is subtract function"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('33aq'); -verify.quickInfoIs("() => string", "", "f", "parameter"); +verify.quickInfoIs("(parameter) f: () => string", ""); goTo.marker('34'); -//verify.currentSignatureHelpDocCommentIs("this is square function\n@paramTag { number } a this is input number of paramTag\n@returnType { number } it is return type"); -//verify.currentParameterHelpArgumentDocCommentIs("this is input number"); +verify.currentSignatureHelpDocCommentIs("this is square function\n@paramTag { number } a this is input number of paramTag\n@returnType { number } it is return type"); +verify.currentParameterHelpArgumentDocCommentIs("this is input number"); goTo.marker('34q'); -verify.quickInfoIs("(a: number): number", "this is square function\n@paramTag { number } a this is input number of paramTag\n@returnType { number } it is return type", "square", "function"); +verify.quickInfoIs("(function) square(a: number): number", "this is square function\n@paramTag { number } a this is input number of paramTag\n@returnType { number } it is return type"); goTo.marker('34aq'); -verify.quickInfoIs("number", "this is input number", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", "this is input number"); goTo.marker('35'); -//verify.currentSignatureHelpDocCommentIs("this is divide function\n@paramTag { number } g this is optional param g"); -//verify.currentParameterHelpArgumentDocCommentIs("this is a"); +verify.currentSignatureHelpDocCommentIs("this is divide function\n@paramTag { number } g this is optional param g"); +verify.currentParameterHelpArgumentDocCommentIs("this is a"); goTo.marker('35q'); -verify.quickInfoIs("(a: number, b: number): void", "this is divide function\n@paramTag { number } g this is optional param g", "divide", "function"); +verify.quickInfoIs("(function) divide(a: number, b: number): void", "this is divide function\n@paramTag { number } g this is optional param g"); goTo.marker('35aq'); -verify.quickInfoIs("number", "this is a", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", "this is a"); goTo.marker('36'); -//verify.currentSignatureHelpDocCommentIs("this is divide function\n@paramTag { number } g this is optional param g"); -//verify.currentParameterHelpArgumentDocCommentIs("this is b"); +verify.currentSignatureHelpDocCommentIs("this is divide function\n@paramTag { number } g this is optional param g"); +verify.currentParameterHelpArgumentDocCommentIs("this is b"); goTo.marker('36aq'); -verify.quickInfoIs("number", "this is b", "b", "parameter"); +verify.quickInfoIs("(parameter) b: number", "this is b"); goTo.marker('37'); -//verify.currentSignatureHelpDocCommentIs("Function returns string concat of foo and bar"); -//verify.currentParameterHelpArgumentDocCommentIs("is string"); +verify.currentSignatureHelpDocCommentIs("Function returns string concat of foo and bar"); +verify.currentParameterHelpArgumentDocCommentIs("is string"); goTo.marker('37q'); -verify.quickInfoIs("(foo: string, bar: string): string", "Function returns string concat of foo and bar", "fooBar", "function"); +verify.quickInfoIs("(function) fooBar(foo: string, bar: string): string", "Function returns string concat of foo and bar"); goTo.marker('37aq'); -verify.quickInfoIs("string", "is string", "foo", "parameter"); +verify.quickInfoIs("(parameter) foo: string", "is string"); goTo.marker('38'); -//verify.currentSignatureHelpDocCommentIs("Function returns string concat of foo and bar"); -//verify.currentParameterHelpArgumentDocCommentIs("is second string"); +verify.currentSignatureHelpDocCommentIs("Function returns string concat of foo and bar"); +verify.currentParameterHelpArgumentDocCommentIs("is second string"); goTo.marker('38aq'); -verify.quickInfoIs("string", "is second string", "bar", "parameter"); +verify.quickInfoIs("(parameter) bar: string", "is second string"); goTo.marker('39'); -verify.completionListContains("a", "number", "it is first parameter\nthis is inline comment for a ", "a", "parameter"); -verify.completionListContains("b", "number", "this is inline comment for b", "b", "parameter"); -verify.completionListContains("c", "number", "it is third parameter", "c", "parameter"); -verify.completionListContains("d", "number", "", "d", "parameter"); +verify.completionListContains("a", "(parameter) a: number", "it is first parameter\nthis is inline comment for a "); +verify.completionListContains("b", "(parameter) b: number", "this is inline comment for b"); +verify.completionListContains("c", "(parameter) c: number", "it is third parameter"); +verify.completionListContains("d", "(parameter) d: number", ""); goTo.marker('40'); -//verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); -//verify.currentParameterHelpArgumentDocCommentIs("it is first parameter\nthis is inline comment for a "); +verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); +verify.currentParameterHelpArgumentDocCommentIs("it is first parameter\nthis is inline comment for a "); goTo.marker('40q'); -verify.quickInfoIs("(a: number, b: number, c: number, d: number): number", "this is jsdoc style function with param tag as well as inline parameter help", "jsDocParamTest", "function"); +verify.quickInfoIs("(function) jsDocParamTest(a: number, b: number, c: number, d: number): number", "this is jsdoc style function with param tag as well as inline parameter help"); goTo.marker('40aq'); -verify.quickInfoIs("number", "it is first parameter\nthis is inline comment for a ", "a", "parameter"); +verify.quickInfoIs("(parameter) a: number", "it is first parameter\nthis is inline comment for a "); goTo.marker('41'); -//verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); -//verify.currentParameterHelpArgumentDocCommentIs("this is inline comment for b"); +verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); +verify.currentParameterHelpArgumentDocCommentIs("this is inline comment for b"); goTo.marker('41aq'); -verify.quickInfoIs("number", "this is inline comment for b", "b", "parameter"); +verify.quickInfoIs("(parameter) b: number", "this is inline comment for b"); goTo.marker('42'); -//verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); -//verify.currentParameterHelpArgumentDocCommentIs("it is third parameter"); +verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); +verify.currentParameterHelpArgumentDocCommentIs("it is third parameter"); goTo.marker('42aq'); -verify.quickInfoIs("number", "it is third parameter", "c", "parameter"); +verify.quickInfoIs("(parameter) c: number", "it is third parameter"); goTo.marker('43'); -//verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); -//verify.currentParameterHelpArgumentDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("this is jsdoc style function with param tag as well as inline parameter help"); +verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('43aq'); -verify.quickInfoIs("number", "", "d", "parameter"); +verify.quickInfoIs("(parameter) d: number", ""); goTo.marker('44'); -verify.completionListContains("jsDocParamTest", "(a: number, b: number, c: number, d: number): number", "this is jsdoc style function with param tag as well as inline parameter help", "jsDocParamTest", "function"); -verify.completionListContains("x", "any", "This is a comment ", "x", "var"); -verify.completionListContains("y", "any", "This is a comment ", "y", "var"); +verify.completionListContains("jsDocParamTest", "(function) jsDocParamTest(a: number, b: number, c: number, d: number): number", "this is jsdoc style function with param tag as well as inline parameter help"); +verify.completionListContains("x", "(var) x: any", "This is a comment "); +verify.completionListContains("y", "(var) y: any", "This is a comment "); goTo.marker('45'); -//verify.currentSignatureHelpDocCommentIs("This is function comment\nAnd properly aligned comment "); +verify.currentSignatureHelpDocCommentIs("This is function comment\nAnd properly aligned comment "); goTo.marker('45q'); -verify.quickInfoIs("(): void", "This is function comment\nAnd properly aligned comment ", "jsDocCommentAlignmentTest1", "function"); +verify.quickInfoIs("(function) jsDocCommentAlignmentTest1(): void", "This is function comment\nAnd properly aligned comment "); goTo.marker('46'); -//verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); +verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); goTo.marker('46q'); -verify.quickInfoIs("(): void", "This is function comment\n And aligned with 4 space char margin", "jsDocCommentAlignmentTest2", "function"); +verify.quickInfoIs("(function) jsDocCommentAlignmentTest2(): void", "This is function comment\n And aligned with 4 space char margin"); goTo.marker('47'); -//verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); -//verify.currentParameterHelpArgumentDocCommentIs("this is info about a\nspanning on two lines and aligned perfectly"); +verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); +verify.currentParameterHelpArgumentDocCommentIs("this is info about a\nspanning on two lines and aligned perfectly"); goTo.marker('47q'); -verify.quickInfoIs("(a: string, b: any, c: any): void", "This is function comment\n And aligned with 4 space char margin", "jsDocCommentAlignmentTest3", "function"); +verify.quickInfoIs("(function) jsDocCommentAlignmentTest3(a: string, b: any, c: any): void", "This is function comment\n And aligned with 4 space char margin"); goTo.marker('47aq'); -verify.quickInfoIs("string", "this is info about a\nspanning on two lines and aligned perfectly", "a", "parameter"); +verify.quickInfoIs("(parameter) a: string", "this is info about a\nspanning on two lines and aligned perfectly"); goTo.marker('48'); -//verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); -//verify.currentParameterHelpArgumentDocCommentIs("this is info about b\nspanning on two lines and aligned perfectly\nspanning one more line alined perfectly\n spanning another line with more margin"); +verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); +verify.currentParameterHelpArgumentDocCommentIs("this is info about b\nspanning on two lines and aligned perfectly\nspanning one more line alined perfectly\n spanning another line with more margin"); goTo.marker('48aq'); -verify.quickInfoIs("any", "this is info about b\nspanning on two lines and aligned perfectly\nspanning one more line alined perfectly\n spanning another line with more margin", "b", "parameter"); +verify.quickInfoIs("(parameter) b: any", "this is info about b\nspanning on two lines and aligned perfectly\nspanning one more line alined perfectly\n spanning another line with more margin"); goTo.marker('49'); -//verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); -//verify.currentParameterHelpArgumentDocCommentIs("this is info about b\nnot aligned text about parameter will eat only one space"); +verify.currentSignatureHelpDocCommentIs("This is function comment\n And aligned with 4 space char margin"); +verify.currentParameterHelpArgumentDocCommentIs("this is info about b\nnot aligned text about parameter will eat only one space"); goTo.marker('49aq'); -verify.quickInfoIs("any", "this is info about b\nnot aligned text about parameter will eat only one space", "c", "parameter"); +verify.quickInfoIs("(parameter) c: any", "this is info about b\nnot aligned text about parameter will eat only one space"); goTo.marker('50'); -verify.quickInfoIs(undefined, "", "NoQuickInfoClass", "class"); \ No newline at end of file +verify.quickInfoIs("class NoQuickInfoClass", ""); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 35b6894b1ce..f4dfe41029d 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -153,11 +153,11 @@ module FourSlashInterface { // Verifies the member list contains the specified symbol. The // member list is brought up if necessary - public memberListContains(symbol: string, type?: string, docComment?: string, fullSymbolName?: string, kind?: string) { + public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) { if (this.negative) { FourSlash.currentTestState.verifyMemberListDoesNotContain(symbol); } else { - FourSlash.currentTestState.verifyMemberListContains(symbol, type, docComment, fullSymbolName, kind); + FourSlash.currentTestState.verifyMemberListContains(symbol, text, documenation, kind); } } @@ -167,11 +167,11 @@ module FourSlashInterface { // Verifies the completion list contains the specified symbol. The // completion list is brought up if necessary - public completionListContains(symbol: string, type?: string, docComment?: string, fullSymbolName?: string, kind?: string) { + public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { if (this.negative) { FourSlash.currentTestState.verifyCompletionListDoesNotContain(symbol); } else { - FourSlash.currentTestState.verifyCompletionListContains(symbol, type, docComment, fullSymbolName, kind); + FourSlash.currentTestState.verifyCompletionListContains(symbol, text, documentation, kind); } } @@ -222,12 +222,12 @@ module FourSlashInterface { FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, false); } - public quickInfoIs(typeName?: string, docComment?: string, symbolName?: string, kind?: string) { - FourSlash.currentTestState.verifyQuickInfo(this.negative, typeName, docComment, symbolName, kind); + public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { + FourSlash.currentTestState.verifyQuickInfo(this.negative, expectedText, expectedDocumentation); } - public quickInfoSymbolNameIs(symbolName) { - FourSlash.currentTestState.verifyQuickInfo(this.negative, undefined, undefined, symbolName, undefined); + public quickInfoSymbolNameIs(expectedSymbolInfo: string) { + FourSlash.currentTestState.verifyQuickInfo(this.negative, expectedSymbolInfo); } public quickInfoExists() { @@ -394,8 +394,8 @@ module FourSlashInterface { FourSlash.currentTestState.verifyOccurrencesAtPositionListCount(expectedCount); } - public completionEntryDetailIs(entryName: string, type: string, docComment?: string, fullSymbolName?: string, kind?: string) { - FourSlash.currentTestState.verifyCompletionEntryDetails(entryName, type, docComment, fullSymbolName, kind); + public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) { + FourSlash.currentTestState.verifyCompletionEntryDetails(entryName, text, documentation, kind); } public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) {