fix type issues with previewer and completion

This commit is contained in:
Qiming Zhao 2021-07-22 22:18:08 +08:00
parent 05c2a824a0
commit e99f1c8079
9 changed files with 144 additions and 29 deletions

View file

@ -675,7 +675,7 @@
"license": "MIT",
"devDependencies": {
"@types/node": "^10.12.0",
"coc.nvim": "^0.0.80",
"coc.nvim": "^0.0.81-next.4",
"esbuild": "^0.8.29",
"semver": "^7.3.2",
"vscode-languageserver-protocol": "^3.16.0",

View file

@ -93,7 +93,7 @@ function fromProtocolCallHierarchyItem(item: Proto.CallHierarchyItem): CallHiera
}
const kindModifiers = item.kindModifiers ? parseKindModifier(item.kindModifiers) : undefined
if (kindModifiers?.has(PConst.KindModifiers.depreacted)) {
if (kindModifiers?.has(PConst.KindModifiers.deprecated)) {
result.tags = [SymbolTag.Deprecated]
}
return result

View file

@ -1,9 +1,9 @@
import { commands, CompletionItemProvider, TextDocument, window, workspace } from 'coc.nvim'
import { commands, CompletionItemProvider, TextDocument, CompletionList, CompletionItem, window, workspace } from 'coc.nvim'
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CancellationToken, Command, CompletionContext, CompletionItem, CompletionList, InsertTextFormat, MarkupContent, MarkupKind, Position, Range, TextEdit } from 'vscode-languageserver-protocol'
import { CancellationToken, Command, CompletionContext, InsertTextFormat, MarkupContent, MarkupKind, Position, Range, TextEdit } from 'vscode-languageserver-protocol'
import Proto from '../protocol'
import * as PConst from '../protocol.const'
import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService'

View file

@ -2,8 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CancellationToken, CompletionContext, CompletionItem, CompletionItemKind, CompletionList, Position, Range } from 'vscode-languageserver-protocol'
import { TextDocument } from 'coc.nvim'
import { CancellationToken, CompletionContext, CompletionItem, CompletionItemKind, CompletionList, Position, Range, TextDocument } from 'coc.nvim'
import { workspace } from 'coc.nvim'
import { ITypeScriptServiceClient } from '../typescriptService'
import API from '../utils/api'
@ -37,7 +36,7 @@ const tsDirectives390: Directive[] = [
]
export default class DirectiveCommentCompletionProvider {
constructor(private readonly client: ITypeScriptServiceClient) { }
constructor(private readonly client: ITypeScriptServiceClient) {}
public provideCompletionItems(
document: TextDocument,
@ -62,7 +61,7 @@ export default class DirectiveCommentCompletionProvider {
? tsDirectives390
: tsDirectives
let items = directives.map(directive => {
const item = CompletionItem.create(directive.value)
const item: CompletionItem = { label: directive.value }
item.kind = CompletionItemKind.Snippet
item.detail = directive.description
item.textEdit = {

View file

@ -86,7 +86,7 @@ export default class LanguageProvider {
if (this.client.apiVersion.gte(API.v230)) {
this._register(languages.registerCompletionItemProvider(
`${this.description.id}-directive`,
'TSC', languageIds, new DirectiveCommentCompletionProvider(client,), ['@']
'TSC', languageIds, new DirectiveCommentCompletionProvider(client), ['@']
))
}

View file

@ -44,7 +44,7 @@ export class DiagnosticCategory {
export class KindModifiers {
public static readonly optional = 'optional'
public static readonly depreacted = 'deprecated'
public static readonly deprecated = 'deprecated'
public static readonly color = 'color'
public static readonly dtsFile = '.d.ts'

View file

@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Range, CompletionItem, CompletionItemKind, InsertTextFormat, Position, TextEdit } from 'vscode-languageserver-protocol'
import { Range, CompletionItem, CompletionItemKind, InsertTextFormat, Position, TextEdit } from 'coc.nvim'
import * as Proto from '../protocol'
import * as PConst from '../protocol.const'

View file

@ -5,37 +5,83 @@
import { MarkupContent, MarkupKind } from 'vscode-languageserver-protocol'
import * as Proto from '../protocol'
import { Uri } from 'coc.nvim'
function toResource(filepath: string): Uri {
return Uri.file(filepath)
}
function replaceLinks(text: string): string {
return text
// Http(s) links
.replace(/\{@(link|linkplain|linkcode) (https?:\/\/[^ |}]+?)(?:[| ]([^{}\n]+?))?\}/gi, (_, tag: string, link: string, text?: string) => {
switch (tag) {
case 'linkcode':
return `[\`${text ? text.trim() : link}\`](${link})`
default:
return `[${text ? text.trim() : link}](${link})`
}
})
}
function processInlineTags(text: string): string {
return replaceLinks(text)
}
function getTagBodyText(tag: Proto.JSDocTagInfo): string | undefined {
if (!tag.text) {
return undefined
}
switch (tag.name) {
case 'example':
case 'default':
// Convert to markdown code block if it not already one
if (tag.text.match(/^\s*[~`]{3}/g)) {
return tag.text
}
return '```\n' + tag.text + '\n```'
// Convert to markdown code block if it is not already one
function makeCodeblock(text: string): string {
if (text.match(/^\s*[~`]{3}/g)) {
return text
}
return '```\n' + text + '\n```'
}
return tag.text
const text = convertLinkTags(tag.text)
switch (tag.name) {
case 'example':
// check for caption tags, fix for #79704
const captionTagMatches = text.match(/<caption>(.*?)<\/caption>\s*(\r\n|\n)/)
if (captionTagMatches && captionTagMatches.index === 0) {
return captionTagMatches[1] + '\n\n' + makeCodeblock(text.substr(captionTagMatches[0].length))
} else {
return makeCodeblock(text)
}
case 'author':
// fix obsucated email address, #80898
const emailMatch = text.match(/(.+)\s<([-.\w]+@[-.\w]+)>/)
if (emailMatch === null) {
return text
} else {
return `${emailMatch[1]} ${emailMatch[2]}`
}
case 'default':
return makeCodeblock(text)
}
return processInlineTags(text)
}
function getTagDocumentation(tag: Proto.JSDocTagInfo): string | undefined {
switch (tag.name) {
case 'augments':
case 'extends':
case 'param':
const body = (tag.text || '').split(/^([\w\.]+)\s*/)
if (body && body.length === 3) {
case 'template':
const body = (convertLinkTags(tag.text)).split(/^(\S+)\s*-?\s*/)
if (body?.length === 3) {
const param = body[1]
const doc = body[2]
const label = `*@${tag.name}* \`${param}\``
if (!doc) {
return label
}
return label + (doc.match(/\r\n|\n/g) ? '\n' + doc : `${doc}`)
return label + (doc.match(/\r\n|\n/g) ? ' \n' + processInlineTags(doc) : `${processInlineTags(doc)}`)
}
}
@ -45,7 +91,7 @@ function getTagDocumentation(tag: Proto.JSDocTagInfo): string | undefined {
if (!text) {
return label
}
return label + (text.match(/\r\n|\n/g) ? '\n' + text : `${text}`)
return label + (text.match(/\r\n|\n/g) ? ' \n' + text : `${text}`)
}
export function plain(parts: Proto.SymbolDisplayPart[]): string {
@ -71,3 +117,73 @@ export function markdownDocumentation(
value: out
}
}
/**
* Convert `@link` inline tags to markdown links
*/
function convertLinkTags(
parts: readonly Proto.SymbolDisplayPart[] | string | undefined
): string {
if (!parts) {
return ''
}
if (typeof parts === 'string') {
return parts
}
const out: string[] = []
let currentLink: { name?: string, target?: Proto.FileSpan, text?: string } | undefined
for (const part of parts) {
switch (part.kind) {
case 'link':
if (currentLink) {
const text = currentLink.text ?? currentLink.name
if (currentLink.target) {
const link = toResource(currentLink.target.file)
.with({
fragment: `L${currentLink.target.start.line},${currentLink.target.start.offset}`
})
out.push(`[${text}](${link.toString()})`)
} else {
if (text) {
if (/^https?:/.test(text)) {
const parts = text.split(' ')
if (parts.length === 1) {
out.push(parts[0])
} else if (parts.length > 1) {
out.push(`[${parts.slice(1).join(' ')}](${parts[0]})`)
}
} else {
out.push(text)
}
}
}
currentLink = undefined
} else {
currentLink = {}
}
break
case 'linkName':
if (currentLink) {
currentLink.name = part.text
// TODO: remove cast once we pick up TS 4.3
currentLink.target = (part as any as Proto.JSDocLinkDisplayPart).target
}
break
case 'linkText':
if (currentLink) {
currentLink.text = part.text
}
break
default:
out.push(part.text)
break
}
}
return processInlineTags(out.join(''))
}

View file

@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.44.tgz#3945e6b702cb6403f22b779c8ea9e5c3f44ead40"
integrity sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw==
coc.nvim@^0.0.80:
version "0.0.80"
resolved "https://registry.yarnpkg.com/coc.nvim/-/coc.nvim-0.0.80.tgz#785145c382660db03f517f9b497900d95cbd0e4f"
integrity sha512-/3vTcnofoAYMrdENrlQmADTzfXX4+PZ0fiM10a39UA37dTR2dpIGi9O469kcIksuunLjToqWG8S45AGx/9wV7g==
coc.nvim@^0.0.81-next.4:
version "0.0.81-next.4"
resolved "https://registry.yarnpkg.com/coc.nvim/-/coc.nvim-0.0.81-next.4.tgz#06d808ceca76a250041f3f3dbf33ed9c221eb19b"
integrity sha512-zAgDe8o0mMvmsz7lM3Y/TiDc/+ZQIp05Z21tp1+WnLpNlNjbrqp6xpdcgDutjJWS04nzPNRRJA/btCGpMg7+/Q==
esbuild@^0.8.29:
version "0.8.29"