diff --git a/src/services/services.ts b/src/services/services.ts index 4b618e71c4e..dd2f0025c58 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -131,6 +131,45 @@ namespace ts { let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); let emptyArray: any[] = []; + + const JsDocTagNames: string[] = [ + "augments", + "author", + "argument", + "borrows", + "class", + "constant", + "constructor", + "constructs", + "default", + "deprecated", + "description", + "event", + "example", + "extends", + "field", + "fileOverview", + "function", + "ignore", + "inner", + "lends", + "link", + "memberOf", + "name", + "namespace", + "param", + "private", + "property", + "public", + "requires", + "returns", + "see", + "since", + "static", + "throws", + "type", + "version" + ]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { let node = new (getNodeConstructor(kind))(); @@ -2936,21 +2975,16 @@ namespace ts { if (tag) { switch (tag.kind) { case SyntaxKind.JSDocTypeTag: - let typeTag = tag; - if (typeTag.typeExpression) { - insideJsDocTagExpression = position > typeTag.typeExpression.pos && position < typeTag.typeExpression.end; - }; - break; case SyntaxKind.JSDocParameterTag: - let paramTag = tag; - if (paramTag.typeExpression) { - insideJsDocTagExpression = position > paramTag.typeExpression.pos && position < paramTag.typeExpression.end; + let tagWithExpression = tag; + if (tagWithExpression.typeExpression) { + insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; }; break; } } if (!insideJsDocTagExpression) { - log("Returning an empty list because completion was inside a comment."); + log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); return undefined; } } @@ -3739,32 +3773,30 @@ namespace ts { return undefined; } - // The current position is right after an At sign + // Return a list of JsDoc tag names for completion if the current position is right after an '@' sign if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { return getAllJsDocCompletionEntries(); } - // Or if the current position is in a tag name + // Also return tag names if the current position is inside a tag name, e.g. (at the location of '^') + // /** @par^ */ let tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { - if (position >= tag.atToken.end && position <= tag.tagName.end) { + if (tag.atToken.end <= position && position <= tag.tagName.end) { return getAllJsDocCompletionEntries(); } } } function getAllJsDocCompletionEntries(): CompletionEntry[] { - let tagNames = ["augments", "author", "argument", "borrows", "class", "constant", "constructor", "constructs", "default", "deprecated", "description", "event", "example", "extends", "field", "fileOverview", "function", "ignore", "inner", "lends", "link", "memberOf", "name", "namespace", "param", "private", "property", "public", "requires", "returns", "see", "since", "static", "throws", "type", "version"]; - let entries: CompletionEntry[] = []; - for (let tagName of tagNames) { - entries.push({ + return ts.map(JsDocTagNames, tagName => { + return { name: tagName, kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - }); - } - return entries; + } + }); } function createCompletionEntry(symbol: Symbol, location: Node): CompletionEntry { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9c475694a17..e48eefd92ad 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -486,9 +486,10 @@ namespace ts { } node = node.parent; } + if (jsDocComment) { for (let tag of jsDocComment.tags) { - if (position >= tag.pos && position <= tag.end) { + if (tag.pos <= position && position <= tag.end) { return tag; } } @@ -667,7 +668,6 @@ namespace ts { else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; } else if (flags & SymbolFlags.Alias) { return SymbolDisplayPartKind.aliasName; } - return SymbolDisplayPartKind.text; } }