Address PR comments from Andy

I'll take a look at Wesley's next and see if those require any changes.
This commit is contained in:
Nathan Shively-Sanders 2017-07-25 14:14:12 -07:00
parent 59961394cb
commit c55a043767
7 changed files with 64 additions and 35 deletions

View file

@ -2170,10 +2170,11 @@ namespace ts {
}
// falls through
case SyntaxKind.JSDocPropertyTag:
return declareSymbolAndAddToSymbolTable(node as JSDocPropertyLikeTag,
(node as JSDocPropertyLikeTag).isBracketed || ((node as JSDocPropertyLikeTag).typeExpression && (node as JSDocPropertyLikeTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) ?
SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property,
SymbolFlags.PropertyExcludes);
const propTag = node as JSDocPropertyLikeTag;
const flags = propTag.isBracketed || propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ?
SymbolFlags.Property | SymbolFlags.Optional :
SymbolFlags.Property;
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
case SyntaxKind.JSDocTypedefTag: {
const { fullName } = node as JSDocTypedefTag;
if (!fullName || fullName.kind === SyntaxKind.Identifier) {

View file

@ -5074,8 +5074,8 @@ namespace ts {
return unknownType;
}
const declaration = getDeclarationOfKind<JSDocTypedefTag>(symbol, SyntaxKind.JSDocTypedefTag) ||
getDeclarationOfKind<TypeAliasDeclaration>(symbol, SyntaxKind.TypeAliasDeclaration);
const declaration = <JSDocTypedefTag | TypeAliasDeclaration>findDeclaration(
symbol, d => d.kind === SyntaxKind.JSDocTypedefTag || d.kind === SyntaxKind.TypeAliasDeclaration);
let type = getTypeFromTypeNode(declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type);
if (popTypeResolution()) {
@ -22610,8 +22610,7 @@ namespace ts {
}
if (entityName.parent!.kind === SyntaxKind.JSDocParameterTag) {
const parameter = getParameterFromJSDoc(entityName.parent as JSDocParameterTag);
return parameter && parameter.symbol;
return getParameterSymbolFromJSDoc(entityName.parent as JSDocParameterTag);
}
if (entityName.parent.kind === SyntaxKind.TypeParameter && entityName.parent.parent.kind === SyntaxKind.JSDocTemplateTag) {

View file

@ -411,7 +411,7 @@ namespace ts {
return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.JSDocPropertyTag:
if ((node as JSDocPropertyLikeTag).isParameterNameFirst) {
if ((node as JSDocPropertyLikeTag).isNameFirst) {
return visitNode(cbNode, (<JSDocPropertyLikeTag>node).fullName) ||
visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression);
}
@ -431,12 +431,10 @@ namespace ts {
if ((node as JSDocTypedefTag).typeExpression &&
(node as JSDocTypedefTag).typeExpression.kind === SyntaxKind.JSDocTypeExpression) {
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).name);
visitNode(cbNode, (<JSDocTypedefTag>node).fullName);
}
else {
return visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).name) ||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
}
case SyntaxKind.JSDocTypeLiteral:
@ -6520,7 +6518,27 @@ namespace ts {
const result: JSDocPropertyLikeTag = target ?
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos) :
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, fullName);
if (nestedTypeLiteral) {
typeExpression = nestedTypeLiteral;
}
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = typeExpression;
if (typeExpression) {
result.type = typeExpression.type;
}
result.fullName = postName || preName;
result.name = ts.isIdentifier(result.fullName) ? result.fullName : result.fullName.right;
result.isNameFirst = !!nestedTypeLiteral || (postName ? false : !!preName);
result.isBracketed = isBracketed;
return finishNode(result);
}
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, fullName: EntityName) {
if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
const typeLiteralExpression = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
let child: JSDocPropertyLikeTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral;
const start = scanner.getStartPos();
@ -6535,21 +6553,10 @@ namespace ts {
if (typeExpression.type.kind === SyntaxKind.ArrayType) {
jsdocTypeLiteral.isArrayType = true;
}
typeExpression.type = finishNode(jsdocTypeLiteral);
typeLiteralExpression.type = finishNode(jsdocTypeLiteral);
return finishNode(typeLiteralExpression);
}
}
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = typeExpression;
if (typeExpression) {
result.type = typeExpression.type;
}
result.fullName = postName || preName;
result.name = ts.isIdentifier(result.fullName) ? result.fullName : result.fullName.right;
result.isParameterNameFirst = postName ? false : !!preName;
result.isBracketed = isBracketed;
return finishNode(result);
}
function parseReturnTag(atToken: AtToken, tagName: Identifier): JSDocReturnTag {

View file

@ -2135,7 +2135,7 @@ namespace ts {
name: Identifier;
typeExpression: JSDocTypeExpression;
/** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */
isParameterNameFirst: boolean;
isNameFirst: boolean;
isBracketed: boolean;
}

View file

@ -1552,19 +1552,19 @@ namespace ts {
}
/** Does the opposite of `getJSDocParameterTags`: given a JSDoc parameter, finds the parameter corresponding to it. */
export function getParameterFromJSDoc(node: JSDocParameterTag): ParameterDeclaration | undefined {
if (!isIdentifier(node.fullName)) {
// `@param {T} obj.prop` is not a top-level param, so it doesn't map to a top-level parameter
return undefined;
export function getParameterSymbolFromJSDoc(node: JSDocParameterTag): Symbol | undefined {
if (node.symbol) {
return node.symbol;
}
const name = node.name.text;
const grandParent = node.parent!.parent!;
Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment);
if (!isFunctionLike(grandParent)) {
const func = node.parent!.parent!;
if (!isFunctionLike(func)) {
return undefined;
}
return find(grandParent.parameters, p =>
const parameter = find(func.parameters, p =>
p.name.kind === SyntaxKind.Identifier && p.name.text === name);
return parameter && parameter.symbol;
}
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {

View file

@ -755,7 +755,7 @@ namespace ts {
return;
function processJSDocParameterTag(tag: JSDocParameterTag) {
if (tag.isParameterNameFirst) {
if (tag.isNameFirst) {
pushCommentRange(pos, tag.name.pos - pos);
pushClassification(tag.name.pos, tag.name.end - tag.name.pos, ClassificationType.parameterName);
pos = tag.name.end;
@ -767,7 +767,7 @@ namespace ts {
pos = tag.typeExpression.end;
}
if (!tag.isParameterNameFirst) {
if (!tag.isNameFirst) {
pushCommentRange(pos, tag.name.pos - pos);
pushClassification(tag.name.pos, tag.name.end - tag.name.pos, ClassificationType.parameterName);
pos = tag.name.end;

View file

@ -0,0 +1,22 @@
// @allowJs: true
// @checkJs: true
/// <reference path='fourslash.ts' />
// @Filename: foo.js
/////**
//// * @param {object} o - very important!
//// * @param {string} o.x - a thing, its ok
//// * @param {number} o.y - another thing
//// * @param {Object} o.nested - very nested
//// * @param {boolean} o.nested.[|great|] - much greatness
//// * @param {number} o.nested.times - twice? probably!??
//// */
//// function f(o) { return o.nested.[|great|]; }
verify.rangesReferenceEachOther();
///**
// * @param {object} [|o|] - very important!
// * @param {string} o.x - a thing, its ok
// */
// function f([|o|]) { return [|o|].x; }