74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { CancellationToken } from 'vscode-jsonrpc'
|
|
import { FoldingRange, TextDocument } from 'vscode-languageserver-types'
|
|
import { FoldingContext, FoldingRangeProvider } from 'coc.nvim/lib/provider'
|
|
import { workspace } from 'coc.nvim'
|
|
import Proto from '../protocol'
|
|
import { ITypeScriptServiceClient } from '../typescriptService'
|
|
import * as typeConverters from '../utils/typeConverters'
|
|
|
|
export default class TypeScriptFoldingProvider implements FoldingRangeProvider {
|
|
public constructor(private readonly client: ITypeScriptServiceClient) { }
|
|
|
|
public async provideFoldingRanges(
|
|
document: TextDocument,
|
|
_context: FoldingContext,
|
|
token: CancellationToken
|
|
): Promise<FoldingRange[] | undefined> {
|
|
const file = this.client.toPath(document.uri)
|
|
if (!file) {
|
|
return
|
|
}
|
|
|
|
const args: Proto.FileRequestArgs = { file }
|
|
const res = await this.client.execute('getOutliningSpans', args, token)
|
|
if (res.type != 'response') {
|
|
return
|
|
}
|
|
const { body } = res
|
|
if (!body) {
|
|
return
|
|
}
|
|
|
|
return body
|
|
.map(span => this.convertOutliningSpan(span, document))
|
|
.filter(foldingRange => !!foldingRange) as FoldingRange[]
|
|
}
|
|
|
|
private convertOutliningSpan(
|
|
span: Proto.OutliningSpan,
|
|
document: TextDocument
|
|
): FoldingRange | undefined {
|
|
const range = typeConverters.Range.fromTextSpan(span.textSpan)
|
|
const kind = TypeScriptFoldingProvider.getFoldingRangeKind(span)
|
|
|
|
// Workaround for #49904
|
|
if (span.kind === 'comment') {
|
|
let doc = workspace.getDocument(document.uri)
|
|
const line = doc.getline(range.start.line)
|
|
if (line.match(/\/\/\s*#endregion/gi)) {
|
|
return undefined
|
|
}
|
|
}
|
|
let { start, end } = range
|
|
return FoldingRange.create(start.line, end.line, start.character, end.character, kind)
|
|
}
|
|
|
|
private static getFoldingRangeKind(
|
|
span: Proto.OutliningSpan
|
|
): string {
|
|
switch (span.kind) {
|
|
case 'comment':
|
|
case 'region':
|
|
case 'imports':
|
|
case 'code':
|
|
return span.kind
|
|
default:
|
|
return undefined
|
|
}
|
|
}
|
|
}
|