Skip asterisks after newline when parsing JSDoc types (#26528)

* Skip asterisks after newline when parsing JSDoc types

* Single boolean expression

* Test for parsing and printing multiline function signatures with *
This commit is contained in:
Tim Schaub
2018-09-04 16:41:08 -06:00
committed by Nathan Shively-Sanders
parent 64ac5a53f4
commit 262ea5b06e
8 changed files with 641 additions and 12 deletions

View File

@@ -2377,8 +2377,10 @@ namespace ts {
}
function parseJSDocType(): TypeNode {
scanner.setInJSDocType(true);
const dotdotdot = parseOptionalToken(SyntaxKind.DotDotDotToken);
let type = parseTypeOrTypePredicate();
scanner.setInJSDocType(false);
if (dotdotdot) {
const variadic = createNode(SyntaxKind.JSDocVariadicType, dotdotdot.pos) as JSDocVariadicType;
variadic.type = type;

View File

@@ -42,6 +42,8 @@ namespace ts {
setScriptTarget(scriptTarget: ScriptTarget): void;
setLanguageVariant(variant: LanguageVariant): void;
setTextPos(textPos: number): void;
/* @internal */
setInJSDocType(inType: boolean): 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
// is returned from this function.
@@ -824,6 +826,8 @@ namespace ts {
let tokenValue!: string;
let tokenFlags: TokenFlags;
let inJSDocType = 0;
setText(text, start, length);
return {
@@ -854,6 +858,7 @@ namespace ts {
setLanguageVariant,
setOnError,
setTextPos,
setInJSDocType,
tryScan,
lookAhead,
scanRange,
@@ -1350,6 +1355,7 @@ namespace ts {
function scan(): SyntaxKind {
startPos = pos;
tokenFlags = 0;
let asteriskSeen = false;
while (true) {
tokenPos = pos;
if (pos >= end) {
@@ -1447,6 +1453,11 @@ namespace ts {
return pos += 2, token = SyntaxKind.AsteriskAsteriskToken;
}
pos++;
if (inJSDocType && !asteriskSeen && (tokenFlags & TokenFlags.PrecedingLineBreak)) {
// decoration at the start of a JSDoc comment line
asteriskSeen = true;
continue;
}
return token = SyntaxKind.AsteriskToken;
case CharacterCodes.plus:
if (text.charCodeAt(pos + 1) === CharacterCodes.plus) {
@@ -2078,5 +2089,9 @@ namespace ts {
tokenValue = undefined!;
tokenFlags = 0;
}
function setInJSDocType(inType: boolean) {
inJSDocType += inType ? 1 : -1;
}
}
}

View File

@@ -490,12 +490,23 @@ namespace ts {
return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia);
}
function isJSDocTypeExpressionOrChild(node: Node): boolean {
return node.kind === SyntaxKind.JSDocTypeExpression || (node.parent && isJSDocTypeExpressionOrChild(node.parent));
}
export function getTextOfNodeFromSourceText(sourceText: string, node: Node, includeTrivia = false): string {
if (nodeIsMissing(node)) {
return "";
}
return sourceText.substring(includeTrivia ? node.pos : skipTrivia(sourceText, node.pos), node.end);
let text = sourceText.substring(includeTrivia ? node.pos : skipTrivia(sourceText, node.pos), node.end);
if (isJSDocTypeExpressionOrChild(node)) {
// strip space + asterisk at line start
text = text.replace(/(^|\r?\n|\r)\s*\*\s*/g, "$1");
}
return text;
}
export function getTextOfNode(node: Node, includeTrivia = false): string {