in tsdoc/src/parser/NodeParser.ts [506:656]
private _parseParamBlock(
tokenReader: TokenReader,
docBlockTag: DocBlockTag,
tagName: string
): DocParamBlock {
const startMarker: number = tokenReader.createMarker();
const spacingBeforeParameterNameExcerpt: TokenSequence | undefined = this._tryReadSpacingAndNewlines(
tokenReader
);
// Skip past a JSDoc type (i.e., '@param {type} paramName') if found, and report a warning.
const unsupportedJsdocTypeBeforeParameterNameExcerpt:
| TokenSequence
| undefined = this._tryParseUnsupportedJSDocType(tokenReader, docBlockTag, tagName);
// Parse opening of invalid JSDoc optional parameter name (e.g., '[')
let unsupportedJsdocOptionalNameOpenBracketExcerpt: TokenSequence | undefined;
if (tokenReader.peekTokenKind() === TokenKind.LeftSquareBracket) {
tokenReader.readToken(); // read the "["
unsupportedJsdocOptionalNameOpenBracketExcerpt = tokenReader.extractAccumulatedSequence();
}
let parameterName: string = '';
let done: boolean = false;
while (!done) {
switch (tokenReader.peekTokenKind()) {
case TokenKind.AsciiWord:
case TokenKind.Period:
case TokenKind.DollarSign:
parameterName += tokenReader.readToken();
break;
default:
done = true;
break;
}
}
const explanation: string | undefined = StringChecks.explainIfInvalidUnquotedIdentifier(parameterName);
if (explanation !== undefined) {
tokenReader.backtrackToMarker(startMarker);
const errorParamBlock: DocParamBlock = new DocParamBlock({
configuration: this._configuration,
blockTag: docBlockTag,
parameterName: ''
});
const errorMessage: string =
parameterName.length > 0
? 'The ' + tagName + ' block should be followed by a valid parameter name: ' + explanation
: 'The ' + tagName + ' block should be followed by a parameter name';
this._parserContext.log.addMessageForTokenSequence(
TSDocMessageId.ParamTagWithInvalidName,
errorMessage,
docBlockTag.getTokenSequence(),
docBlockTag
);
return errorParamBlock;
}
const parameterNameExcerpt: TokenSequence = tokenReader.extractAccumulatedSequence();
// Parse closing of invalid JSDoc optional parameter name (e.g., ']', '=default]').
let unsupportedJsdocOptionalNameRestExcerpt: TokenSequence | undefined;
if (unsupportedJsdocOptionalNameOpenBracketExcerpt) {
unsupportedJsdocOptionalNameRestExcerpt = this._tryParseJSDocOptionalNameRest(tokenReader);
let errorSequence: TokenSequence | undefined = unsupportedJsdocOptionalNameOpenBracketExcerpt;
if (unsupportedJsdocOptionalNameRestExcerpt) {
errorSequence = docBlockTag
.getTokenSequence()
.getNewSequence(
unsupportedJsdocOptionalNameOpenBracketExcerpt.startIndex,
unsupportedJsdocOptionalNameRestExcerpt.endIndex
);
}
this._parserContext.log.addMessageForTokenSequence(
TSDocMessageId.ParamTagWithInvalidOptionalName,
'The ' +
tagName +
" should not include a JSDoc-style optional name; it must not be enclosed in '[ ]' brackets.",
errorSequence,
docBlockTag
);
}
const spacingAfterParameterNameExcerpt: TokenSequence | undefined = this._tryReadSpacingAndNewlines(
tokenReader
);
// Skip past a trailing JSDoc type (i.e., '@param paramName {type}') if found, and report a warning.
const unsupportedJsdocTypeAfterParameterNameExcerpt:
| TokenSequence
| undefined = this._tryParseUnsupportedJSDocType(tokenReader, docBlockTag, tagName);
// TODO: Warn if there is no space before or after the hyphen
let hyphenExcerpt: TokenSequence | undefined;
let spacingAfterHyphenExcerpt: TokenSequence | undefined;
let unsupportedJsdocTypeAfterHyphenExcerpt: TokenSequence | undefined;
if (tokenReader.peekTokenKind() === TokenKind.Hyphen) {
tokenReader.readToken();
hyphenExcerpt = tokenReader.extractAccumulatedSequence();
// TODO: Only read one space
spacingAfterHyphenExcerpt = this._tryReadSpacingAndNewlines(tokenReader);
// Skip past a JSDoc type (i.e., '@param paramName - {type}') if found, and report a warning.
unsupportedJsdocTypeAfterHyphenExcerpt = this._tryParseUnsupportedJSDocType(
tokenReader,
docBlockTag,
tagName
);
} else {
this._parserContext.log.addMessageForTokenSequence(
TSDocMessageId.ParamTagMissingHyphen,
'The ' + tagName + ' block should be followed by a parameter name and then a hyphen',
docBlockTag.getTokenSequence(),
docBlockTag
);
}
return new DocParamBlock({
parsed: true,
configuration: this._configuration,
blockTag: docBlockTag,
spacingBeforeParameterNameExcerpt,
unsupportedJsdocTypeBeforeParameterNameExcerpt,
unsupportedJsdocOptionalNameOpenBracketExcerpt,
parameterNameExcerpt,
parameterName,
unsupportedJsdocOptionalNameRestExcerpt,
spacingAfterParameterNameExcerpt,
unsupportedJsdocTypeAfterParameterNameExcerpt,
hyphenExcerpt,
spacingAfterHyphenExcerpt,
unsupportedJsdocTypeAfterHyphenExcerpt
});
}