incorperate folding api feedback
This commit is contained in:
parent
89163a5f59
commit
a1bb202eb6
18 changed files with 232 additions and 180 deletions
|
@ -8,7 +8,7 @@ import * as path from 'path';
|
|||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { languages, window, commands, ExtensionContext, Range, Position, TextDocument, CompletionItem, CompletionItemKind, TextEdit, SnippetString, FoldingRangeList, FoldingRange, FoldingContext, CancellationToken } from 'vscode';
|
||||
import { languages, window, commands, ExtensionContext, Range, Position, TextDocument, CompletionItem, CompletionItemKind, TextEdit, SnippetString, FoldingRangeKind, FoldingRange, FoldingContext, CancellationToken } from 'vscode';
|
||||
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Disposable } from 'vscode-languageclient';
|
||||
import { FoldingRangeRequest, FoldingRangeRequestParam, FoldingRangeClientCapabilities } from 'vscode-languageserver-protocol-foldingprovider';
|
||||
|
||||
|
@ -117,14 +117,26 @@ export function activate(context: ExtensionContext) {
|
|||
}
|
||||
|
||||
function initFoldingProvider(): Disposable {
|
||||
return languages.registerFoldingProvider(documentSelector, {
|
||||
const kinds: { [value: string]: FoldingRangeKind } = Object.create(null);
|
||||
function getKind(value: string | undefined) {
|
||||
if (!value) {
|
||||
return void 0;
|
||||
}
|
||||
let kind = kinds[value];
|
||||
if (!kind) {
|
||||
kind = new FoldingRangeKind(value);
|
||||
kinds[value] = kind;
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
return languages.registerFoldingRangeProvider(documentSelector, {
|
||||
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
|
||||
const param: FoldingRangeRequestParam = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
|
||||
};
|
||||
return client.sendRequest(FoldingRangeRequest.type, param, token).then(ranges => {
|
||||
if (Array.isArray(ranges)) {
|
||||
return new FoldingRangeList(ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.kind)));
|
||||
return ranges.map(r => new FoldingRange(r.startLine, r.endLine, getKind(r.kind)));
|
||||
}
|
||||
return null;
|
||||
}, error => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as path from 'path';
|
|||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, FoldingRangeList, FoldingRange, FoldingContext } from 'vscode';
|
||||
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, FoldingRangeKind, FoldingRange, FoldingContext } from 'vscode';
|
||||
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams, Disposable, CancellationToken } from 'vscode-languageclient';
|
||||
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
|
||||
import { activateTagClosing } from './tagClosing';
|
||||
|
@ -174,14 +174,26 @@ export function activate(context: ExtensionContext) {
|
|||
});
|
||||
|
||||
function initFoldingProvider(): Disposable {
|
||||
return languages.registerFoldingProvider(documentSelector, {
|
||||
const kinds: { [value: string]: FoldingRangeKind } = Object.create(null);
|
||||
function getKind(value: string | undefined) {
|
||||
if (!value) {
|
||||
return void 0;
|
||||
}
|
||||
let kind = kinds[value];
|
||||
if (!kind) {
|
||||
kind = new FoldingRangeKind(value);
|
||||
kinds[value] = kind;
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
return languages.registerFoldingRangeProvider(documentSelector, {
|
||||
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
|
||||
const param: FoldingRangeRequestParam = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
|
||||
};
|
||||
return client.sendRequest(FoldingRangeRequest.type, param, token).then(ranges => {
|
||||
if (Array.isArray(ranges)) {
|
||||
return new FoldingRangeList(ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.kind)));
|
||||
return ranges.map(r => new FoldingRange(r.startLine, r.endLine, getKind(r.kind)));
|
||||
}
|
||||
return null;
|
||||
}, error => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as path from 'path';
|
|||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeList, FoldingRange, Disposable, FoldingContext } from 'vscode';
|
||||
import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeKind, FoldingRange, Disposable, FoldingContext } from 'vscode';
|
||||
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, CancellationToken } from 'vscode-languageclient';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
|
@ -156,14 +156,26 @@ export function activate(context: ExtensionContext) {
|
|||
languages.setLanguageConfiguration('jsonc', languageConfiguration);
|
||||
|
||||
function initFoldingProvider(): Disposable {
|
||||
return languages.registerFoldingProvider(documentSelector, {
|
||||
const kinds: { [value: string]: FoldingRangeKind } = Object.create(null);
|
||||
function getKind(value: string | undefined) {
|
||||
if (!value) {
|
||||
return void 0;
|
||||
}
|
||||
let kind = kinds[value];
|
||||
if (!kind) {
|
||||
kind = new FoldingRangeKind(value);
|
||||
kinds[value] = kind;
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
return languages.registerFoldingRangeProvider(documentSelector, {
|
||||
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
|
||||
const param: FoldingRangeRequestParam = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
|
||||
};
|
||||
return client.sendRequest(FoldingRangeRequest.type, param, token).then(ranges => {
|
||||
if (Array.isArray(ranges)) {
|
||||
return new FoldingRangeList(ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.kind)));
|
||||
return ranges.map(r => new FoldingRange(r.startLine, r.endLine, getKind(r.kind)));
|
||||
}
|
||||
return null;
|
||||
}, error => {
|
||||
|
|
|
@ -39,7 +39,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider));
|
||||
context.subscriptions.push(vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()));
|
||||
context.subscriptions.push(vscode.languages.registerFoldingProvider(selector, new MarkdownFoldingProvider(engine)));
|
||||
context.subscriptions.push(vscode.languages.registerFoldingRangeProvider(selector, new MarkdownFoldingProvider(engine)));
|
||||
context.subscriptions.push(vscode.languages.registerWorkspaceSymbolProvider(new MarkdownWorkspaceSymbolProvider(symbolProvider)));
|
||||
|
||||
const previewSecuritySelector = new PreviewSecuritySelector(cspArbiter, previewManager);
|
||||
|
|
|
@ -8,7 +8,9 @@ import * as vscode from 'vscode';
|
|||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
|
||||
export default class MarkdownFoldingProvider implements vscode.FoldingProvider {
|
||||
const rangeLimit = 5000;
|
||||
|
||||
export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvider {
|
||||
|
||||
constructor(
|
||||
private readonly engine: MarkdownEngine
|
||||
|
@ -16,13 +18,13 @@ export default class MarkdownFoldingProvider implements vscode.FoldingProvider {
|
|||
|
||||
public async provideFoldingRanges(
|
||||
document: vscode.TextDocument,
|
||||
context: vscode.FoldingContext,
|
||||
_: vscode.FoldingContext,
|
||||
_token: vscode.CancellationToken
|
||||
): Promise<vscode.FoldingRangeList> {
|
||||
): Promise<vscode.FoldingRange[]> {
|
||||
const tocProvider = new TableOfContentsProvider(this.engine, document);
|
||||
let toc = await tocProvider.getToc();
|
||||
if (context.maxRanges && toc.length > context.maxRanges) {
|
||||
toc = toc.slice(0, context.maxRanges);
|
||||
if (toc.length > rangeLimit) {
|
||||
toc = toc.slice(0, rangeLimit);
|
||||
}
|
||||
|
||||
const foldingRanges = toc.map((entry, startIndex) => {
|
||||
|
@ -43,6 +45,6 @@ export default class MarkdownFoldingProvider implements vscode.FoldingProvider {
|
|||
});
|
||||
|
||||
|
||||
return new vscode.FoldingRangeList(foldingRanges);
|
||||
return foldingRanges;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ const testFileName = vscode.Uri.parse('test.md');
|
|||
suite('markdown.FoldingProvider', () => {
|
||||
test('Should not return anything for empty document', async () => {
|
||||
const folds = await getFoldsForDocument(``);
|
||||
assert.strictEqual(folds.ranges.length, 0);
|
||||
assert.strictEqual(folds.length, 0);
|
||||
});
|
||||
|
||||
test('Should not return anything for document without headers', async () => {
|
||||
|
@ -24,7 +24,7 @@ suite('markdown.FoldingProvider', () => {
|
|||
**b** afas
|
||||
a#b
|
||||
a`);
|
||||
assert.strictEqual(folds.ranges.length, 0);
|
||||
assert.strictEqual(folds.length, 0);
|
||||
});
|
||||
|
||||
test('Should fold from header to end of document', async () => {
|
||||
|
@ -32,10 +32,10 @@ a`);
|
|||
# b
|
||||
c
|
||||
d`);
|
||||
assert.strictEqual(folds.ranges.length, 1);
|
||||
const firstFold = folds.ranges[0];
|
||||
assert.strictEqual(firstFold.startLine, 1);
|
||||
assert.strictEqual(firstFold.endLine, 3);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
|
||||
test('Should leave single newline before next header', async () => {
|
||||
|
@ -45,10 +45,10 @@ x
|
|||
|
||||
# b
|
||||
y`);
|
||||
assert.strictEqual(folds.ranges.length, 2);
|
||||
const firstFold = folds.ranges[0];
|
||||
assert.strictEqual(firstFold.startLine, 1);
|
||||
assert.strictEqual(firstFold.endLine, 3);
|
||||
assert.strictEqual(folds.length, 2);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
|
||||
test('Should collapse multuple newlines to single newline before next header', async () => {
|
||||
|
@ -60,10 +60,10 @@ x
|
|||
|
||||
# b
|
||||
y`);
|
||||
assert.strictEqual(folds.ranges.length, 2);
|
||||
const firstFold = folds.ranges[0];
|
||||
assert.strictEqual(firstFold.startLine, 1);
|
||||
assert.strictEqual(firstFold.endLine, 5);
|
||||
assert.strictEqual(folds.length, 2);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 5);
|
||||
});
|
||||
|
||||
test('Should not collapse if there is no newline before next header', async () => {
|
||||
|
@ -72,10 +72,10 @@ y`);
|
|||
x
|
||||
# b
|
||||
y`);
|
||||
assert.strictEqual(folds.ranges.length, 2);
|
||||
const firstFold = folds.ranges[0];
|
||||
assert.strictEqual(firstFold.startLine, 1);
|
||||
assert.strictEqual(firstFold.endLine, 2);
|
||||
assert.strictEqual(folds.length, 2);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 2);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as Proto from '../protocol';
|
|||
import * as typeConverters from '../utils/typeConverters';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
|
||||
export default class TypeScriptFoldingProvider implements vscode.FoldingProvider {
|
||||
export default class TypeScriptFoldingProvider implements vscode.FoldingRangeProvider {
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient
|
||||
) { }
|
||||
|
@ -18,7 +18,7 @@ export default class TypeScriptFoldingProvider implements vscode.FoldingProvider
|
|||
document: vscode.TextDocument,
|
||||
_context: vscode.FoldingContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.FoldingRangeList | undefined> {
|
||||
): Promise<vscode.FoldingRange[] | undefined> {
|
||||
if (!this.client.apiVersion.has280Features()) {
|
||||
return;
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ export default class TypeScriptFoldingProvider implements vscode.FoldingProvider
|
|||
return;
|
||||
}
|
||||
|
||||
return new vscode.FoldingRangeList(response.body.map(span => {
|
||||
return response.body.map(span => {
|
||||
const range = typeConverters.Range.fromTextSpan(span.textSpan);
|
||||
// workaround for #47240
|
||||
if (range.end.character > 0 && document.getText(new vscode.Range(range.end.translate(0, -1), range.end)) === '}') {
|
||||
return new vscode.FoldingRange(range.start.line, Math.max(range.end.line - 1, range.start.line));
|
||||
}
|
||||
return new vscode.FoldingRange(range.start.line, range.end.line);
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ export default class LanguageProvider {
|
|||
let enable = workspace.getConfiguration().get(foldingSetting, false);
|
||||
if (enable && this.client.apiVersion.has280Features()) {
|
||||
if (!this.foldingProviderRegistration) {
|
||||
this.foldingProviderRegistration = languages.registerFoldingProvider(this.documentSelector, new (await import('./features/foldingProvider')).default(this.client));
|
||||
this.foldingProviderRegistration = languages.registerFoldingRangeProvider(this.documentSelector, new (await import('./features/foldingProvider')).default(this.client));
|
||||
}
|
||||
} else {
|
||||
if (this.foldingProviderRegistration) {
|
||||
|
|
|
@ -835,7 +835,6 @@ export interface DocumentColorProvider {
|
|||
* @internal
|
||||
*/
|
||||
export interface FoldingContext {
|
||||
maxRanges?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -844,59 +843,61 @@ export interface FoldingContext {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface FoldingProvider {
|
||||
export interface FoldingRangeProvider {
|
||||
/**
|
||||
* Provides the color ranges for a specific model.
|
||||
*/
|
||||
provideFoldingRanges(model: model.ITextModel, context: FoldingContext, token: CancellationToken): IFoldingRangeList | Thenable<IFoldingRangeList>;
|
||||
provideFoldingRanges(model: model.ITextModel, context: FoldingContext, token: CancellationToken): IFoldingRange[] | Thenable<IFoldingRange[]>;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IFoldingRangeList {
|
||||
|
||||
ranges: IFoldingRange[];
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IFoldingRange {
|
||||
|
||||
/**
|
||||
* The start line number
|
||||
* The zero-based start line of the range to fold. The folded area starts after the line's last character.
|
||||
*/
|
||||
startLineNumber: number;
|
||||
start: number;
|
||||
|
||||
/**
|
||||
* The end line number
|
||||
* The zero-based end line of the range to fold. The folded area ends with the line's last character.
|
||||
*/
|
||||
endLineNumber: number;
|
||||
end: number;
|
||||
|
||||
/**
|
||||
* The optional type of the folding range
|
||||
* Describes the [Kind](#FoldingRangeKind) of the folding range such as [Comment](#FoldingRangeKind.Comment) or
|
||||
* [Region](#FoldingRangeKind.Region). The kind is used to categorize folding ranges and used by commands
|
||||
* like 'Fold all comments'. See
|
||||
* [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
|
||||
*/
|
||||
type?: FoldingRangeType | string;
|
||||
|
||||
// auto-collapse
|
||||
// header span
|
||||
|
||||
kind?: FoldingRangeKind;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export enum FoldingRangeType {
|
||||
export class FoldingRangeKind {
|
||||
/**
|
||||
* Folding range for a comment
|
||||
* Kind for folding range representing a comment. The value of the kind is 'comment'.
|
||||
*/
|
||||
Comment = 'comment',
|
||||
static readonly Comment = new FoldingRangeKind('comment');
|
||||
/**
|
||||
* Folding range for a imports or includes
|
||||
* Kind for folding range representing a import. The value of the kind is 'imports'.
|
||||
*/
|
||||
Imports = 'imports',
|
||||
static readonly Imports = new FoldingRangeKind('imports');
|
||||
/**
|
||||
* Folding range for a region (e.g. `#region`)
|
||||
* Kind for folding range representing regions (for example marked by `#region`, `#endregion`).
|
||||
* The value of the kind is 'region'.
|
||||
*/
|
||||
Region = 'region'
|
||||
static readonly Region = new FoldingRangeKind('region');
|
||||
|
||||
/**
|
||||
* Creates a new [FoldingRangeKind](#FoldingRangeKind).
|
||||
*
|
||||
* @param value of the kind.
|
||||
*/
|
||||
public constructor(public value: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1047,7 +1048,7 @@ export const ColorProviderRegistry = new LanguageFeatureRegistry<DocumentColorPr
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FoldingProviderRegistry = new LanguageFeatureRegistry<FoldingProvider>();
|
||||
export const FoldingRangeProviderRegistry = new LanguageFeatureRegistry<FoldingRangeProvider>();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
|
|
@ -28,7 +28,7 @@ import { IRange } from 'vs/editor/common/core/range';
|
|||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { IndentRangeProvider } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { FoldingProviderRegistry, FoldingRangeType } from 'vs/editor/common/modes';
|
||||
import { FoldingRangeProviderRegistry, FoldingRangeKind } from 'vs/editor/common/modes';
|
||||
import { SyntaxRangeProvider } from './syntaxRangeProvider';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
|
@ -82,7 +82,7 @@ export class FoldingController implements IEditorContribution {
|
|||
this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls;
|
||||
|
||||
this.globalToDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged()));
|
||||
this.globalToDispose.push(FoldingProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged()));
|
||||
this.globalToDispose.push(FoldingRangeProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged()));
|
||||
|
||||
this.globalToDispose.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
|
||||
if (e.contribInfo) {
|
||||
|
@ -205,7 +205,7 @@ export class FoldingController implements IEditorContribution {
|
|||
private getRangeProvider(): RangeProvider {
|
||||
if (!this.rangeProvider) {
|
||||
if (this._useFoldingProviders) {
|
||||
let foldingProviders = FoldingProviderRegistry.ordered(this.foldingModel.textModel);
|
||||
let foldingProviders = FoldingRangeProviderRegistry.ordered(this.foldingModel.textModel);
|
||||
this.rangeProvider = foldingProviders.length ? new SyntaxRangeProvider(foldingProviders) : new IndentRangeProvider();
|
||||
} else {
|
||||
this.rangeProvider = new IndentRangeProvider();
|
||||
|
@ -584,7 +584,7 @@ class FoldAllBlockCommentsAction extends FoldingAction<void> {
|
|||
|
||||
invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void {
|
||||
if (foldingModel.regions.hasTypes()) {
|
||||
setCollapseStateForType(foldingModel, FoldingRangeType.Comment, true);
|
||||
setCollapseStateForType(foldingModel, FoldingRangeKind.Comment.value, true);
|
||||
} else {
|
||||
let comments = LanguageConfigurationRegistry.getComments(editor.getModel().getLanguageIdentifier().id);
|
||||
if (comments && comments.blockCommentStartToken) {
|
||||
|
@ -612,7 +612,7 @@ class FoldAllRegionsAction extends FoldingAction<void> {
|
|||
|
||||
invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void {
|
||||
if (foldingModel.regions.hasTypes()) {
|
||||
setCollapseStateForType(foldingModel, FoldingRangeType.Region, true);
|
||||
setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, true);
|
||||
} else {
|
||||
let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id);
|
||||
if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
|
||||
|
@ -640,7 +640,7 @@ class UnfoldAllRegionsAction extends FoldingAction<void> {
|
|||
|
||||
invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void {
|
||||
if (foldingModel.regions.hasTypes()) {
|
||||
setCollapseStateForType(foldingModel, FoldingRangeType.Region, false);
|
||||
setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, false);
|
||||
} else {
|
||||
let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id);
|
||||
if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import { FoldingProvider, IFoldingRange, FoldingContext } from 'vs/editor/common/modes';
|
||||
import { FoldingRangeProvider, IFoldingRange, FoldingContext } from 'vs/editor/common/modes';
|
||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { toThenable } from 'vs/base/common/async';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
|
@ -26,7 +26,7 @@ const foldingContext: FoldingContext = {
|
|||
|
||||
export class SyntaxRangeProvider implements RangeProvider {
|
||||
|
||||
constructor(private providers: FoldingProvider[]) {
|
||||
constructor(private providers: FoldingRangeProvider[]) {
|
||||
}
|
||||
|
||||
compute(model: ITextModel, cancellationToken: CancellationToken): Thenable<FoldingRegions> {
|
||||
|
@ -41,23 +41,23 @@ export class SyntaxRangeProvider implements RangeProvider {
|
|||
|
||||
}
|
||||
|
||||
function collectSyntaxRanges(providers: FoldingProvider[], model: ITextModel, cancellationToken: CancellationToken): Thenable<IFoldingRangeData[] | null> {
|
||||
function collectSyntaxRanges(providers: FoldingRangeProvider[], model: ITextModel, cancellationToken: CancellationToken): Thenable<IFoldingRangeData[] | null> {
|
||||
let promises = providers.map(provider => toThenable(provider.provideFoldingRanges(model, foldingContext, cancellationToken)));
|
||||
return TPromise.join(promises).then(lists => {
|
||||
return TPromise.join(promises).then(results => {
|
||||
let rangeData: IFoldingRangeData[] = null;
|
||||
if (cancellationToken.isCancellationRequested) {
|
||||
return null;
|
||||
}
|
||||
for (let i = 0; i < lists.length; i++) {
|
||||
let list = lists[i];
|
||||
if (list && Array.isArray(list.ranges)) {
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let ranges = results[i];
|
||||
if (Array.isArray(ranges)) {
|
||||
if (!Array.isArray(rangeData)) {
|
||||
rangeData = [];
|
||||
}
|
||||
let nLines = model.getLineCount();
|
||||
for (let r of list.ranges) {
|
||||
if (r.startLineNumber > 0 && r.endLineNumber > r.startLineNumber && r.endLineNumber <= nLines) {
|
||||
rangeData.push({ startLineNumber: r.startLineNumber, endLineNumber: r.endLineNumber, rank: i, type: r.type });
|
||||
for (let r of ranges) {
|
||||
if (r.start > 0 && r.end > r.start && r.end <= nLines) {
|
||||
rangeData.push({ start: r.start, end: r.end, rank: i, kind: r.kind });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ export class RangesCollector {
|
|||
export function sanitizeRanges(rangeData: IFoldingRangeData[]): FoldingRegions {
|
||||
|
||||
let sorted = rangeData.sort((d1, d2) => {
|
||||
let diff = d1.startLineNumber - d2.startLineNumber;
|
||||
let diff = d1.start - d2.start;
|
||||
if (diff === 0) {
|
||||
diff = d1.rank - d2.rank;
|
||||
}
|
||||
|
@ -158,20 +158,20 @@ export function sanitizeRanges(rangeData: IFoldingRangeData[]): FoldingRegions {
|
|||
for (let entry of sorted) {
|
||||
if (!top) {
|
||||
top = entry;
|
||||
collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length);
|
||||
collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);
|
||||
} else {
|
||||
if (entry.startLineNumber > top.startLineNumber) {
|
||||
if (entry.endLineNumber <= top.endLineNumber) {
|
||||
if (entry.start > top.start) {
|
||||
if (entry.end <= top.end) {
|
||||
previous.push(top);
|
||||
top = entry;
|
||||
collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length);
|
||||
} else if (entry.startLineNumber > top.endLineNumber) {
|
||||
collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);
|
||||
} else if (entry.start > top.end) {
|
||||
do {
|
||||
top = previous.pop();
|
||||
} while (top && entry.startLineNumber > top.endLineNumber);
|
||||
} while (top && entry.start > top.end);
|
||||
previous.push(top);
|
||||
top = entry;
|
||||
collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length);
|
||||
collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
108
src/vs/vscode.proposed.d.ts
vendored
108
src/vs/vscode.proposed.d.ts
vendored
|
@ -13,88 +13,104 @@ declare module 'vscode' {
|
|||
|
||||
//#region Aeschli: folding
|
||||
|
||||
export class FoldingRangeList {
|
||||
|
||||
/**
|
||||
* The folding ranges.
|
||||
*/
|
||||
ranges: FoldingRange[];
|
||||
|
||||
/**
|
||||
* Creates new folding range list.
|
||||
*
|
||||
* @param ranges The folding ranges
|
||||
*/
|
||||
constructor(ranges: FoldingRange[]);
|
||||
}
|
||||
|
||||
|
||||
export class FoldingRange {
|
||||
|
||||
/**
|
||||
* The start line number (zero-based) of the range to fold. The hidden area starts after the last character of that line.
|
||||
* The zero-based start line of the range to fold. The folded area starts after the line's last character.
|
||||
*/
|
||||
startLine: number;
|
||||
start: number;
|
||||
|
||||
/**
|
||||
* The end line number (0-based) of the range to fold. The hidden area ends at the last character of that line.
|
||||
* The zero-based end line of the range to fold. The folded area ends with the line's last character.
|
||||
*/
|
||||
endLine: number;
|
||||
end: number;
|
||||
|
||||
/**
|
||||
* The actual color value for this color range.
|
||||
* Describes the [Kind](#FoldingRangeKind) of the folding range such as [Comment](#FoldingRangeKind.Comment) or
|
||||
* [Region](#FoldingRangeKind.Region). The kind is used to categorize folding ranges and used by commands
|
||||
* like 'Fold all comments'. See
|
||||
* [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
|
||||
*/
|
||||
type?: FoldingRangeType | string;
|
||||
kind?: FoldingRangeKind;
|
||||
|
||||
/**
|
||||
* Creates a new folding range.
|
||||
*
|
||||
* @param startLineNumber The first line of the fold
|
||||
* @param type The last line of the fold
|
||||
* @param start The start line of the folded range.
|
||||
* @param end The end line of the folded range.
|
||||
* @param kind The kind of the folding range.
|
||||
*/
|
||||
constructor(startLineNumber: number, endLineNumber: number, type?: FoldingRangeType | string);
|
||||
constructor(start: number, end: number, kind?: FoldingRangeKind);
|
||||
}
|
||||
|
||||
export enum FoldingRangeType {
|
||||
export class FoldingRangeKind {
|
||||
/**
|
||||
* Folding range for a comment
|
||||
* Kind for folding range representing a comment. The value of the kind is 'comment'.
|
||||
*/
|
||||
Comment = 'comment',
|
||||
static readonly Comment: FoldingRangeKind;
|
||||
/**
|
||||
* Folding range for a imports or includes
|
||||
* Kind for folding range representing a import. The value of the kind is 'imports'.
|
||||
*/
|
||||
Imports = 'imports',
|
||||
static readonly Imports: FoldingRangeKind;
|
||||
/**
|
||||
* Folding range for a region (e.g. `#region`)
|
||||
* Kind for folding range representing regions (for example a folding range marked by `#region` and `#endregion`).
|
||||
* The value of the kind is 'region'.
|
||||
*/
|
||||
Region = 'region'
|
||||
static readonly Region: FoldingRangeKind;
|
||||
/**
|
||||
* String value of the kind, e.g. `comment`.
|
||||
*/
|
||||
readonly value: string;
|
||||
/**
|
||||
* Creates a new [FoldingRangeKind](#FoldingRangeKind).
|
||||
*
|
||||
* @param value of the kind.
|
||||
*/
|
||||
public constructor(value: string);
|
||||
}
|
||||
|
||||
export namespace languages {
|
||||
|
||||
/**
|
||||
* Register a folding provider.
|
||||
* Register a folding range provider.
|
||||
*
|
||||
* Multiple folding can be registered for a language. In that case providers are sorted
|
||||
* by their [score](#languages.match) and the best-matching provider is used. Failure
|
||||
* of the selected provider will cause a failure of the whole operation.
|
||||
*
|
||||
* @param selector A selector that defines the documents this provider is applicable to.
|
||||
* @param provider A folding provider.
|
||||
* @param provider A folding range provider.
|
||||
* @param metadata Metadata about the kind of code actions the provider providers.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerFoldingProvider(selector: DocumentSelector, provider: FoldingProvider): Disposable;
|
||||
export function registerFoldingRangeProvider(selector: DocumentSelector, provider: FoldingRangeProvider, metadata?: FoldingRangeProviderMetadata): Disposable;
|
||||
}
|
||||
|
||||
export interface FoldingContext {
|
||||
maxRanges?: number;
|
||||
}
|
||||
|
||||
export interface FoldingProvider {
|
||||
/**
|
||||
* Metadata about the kind of folding ranges that a [FoldingRangeProvider](#FoldingRangeProvider) providers uses.
|
||||
*/
|
||||
export interface FoldingRangeProviderMetadata {
|
||||
/**
|
||||
* Returns a list of folding ranges or null if the provider does not want to participate or was cancelled.
|
||||
* [FoldingRangeKind](#FoldingRangeKind) that this provider may return.
|
||||
*/
|
||||
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): ProviderResult<FoldingRangeList>;
|
||||
readonly providedFoldingRangeKinds?: ReadonlyArray<FoldingRangeKind>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Folding context (for future use)
|
||||
*/
|
||||
export interface FoldingContext {
|
||||
}
|
||||
|
||||
export interface FoldingRangeProvider {
|
||||
/**
|
||||
* Returns a list of folding ranges or null and undefined if the provider
|
||||
* does not want to participate or was cancelled.
|
||||
* @param document The document in which the command was invoked.
|
||||
* @param context Additional context information (for future use)
|
||||
* @param token A cancellation token.
|
||||
*/
|
||||
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): ProviderResult<FoldingRange[]>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
@ -242,9 +258,9 @@ declare module 'vscode' {
|
|||
readonly onDidChangeFile: Event<FileChange2[]>;
|
||||
|
||||
/**
|
||||
* Subscribe to events in the file or folder denoted by `uri`.
|
||||
* @param uri
|
||||
* @param options
|
||||
* Subscribe to events in the file or folder denoted by `uri`.
|
||||
* @param uri
|
||||
* @param options
|
||||
*/
|
||||
watch(uri: Uri, options: { recursive?: boolean; excludes?: string[] }): Disposable;
|
||||
|
||||
|
@ -269,7 +285,7 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* Create a new directory. *Note* that new files are created via `write`-calls.
|
||||
*
|
||||
*
|
||||
* @param uri The uri of the *new* folder.
|
||||
* @param token A cancellation token.
|
||||
*/
|
||||
|
|
|
@ -349,9 +349,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
|
||||
// --- folding
|
||||
|
||||
$registerFoldingProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
const proxy = this._proxy;
|
||||
this._registrations[handle] = modes.FoldingProviderRegistry.register(toLanguageSelector(selector), <modes.FoldingProvider>{
|
||||
this._registrations[handle] = modes.FoldingRangeProviderRegistry.register(toLanguageSelector(selector), <modes.FoldingRangeProvider>{
|
||||
provideFoldingRanges: (model, context, token) => {
|
||||
return wireCancellationToken(token, proxy.$provideFoldingRanges(handle, model.uri, context));
|
||||
}
|
||||
|
|
|
@ -328,8 +328,8 @@ export function createApiFactory(
|
|||
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
|
||||
return extHostLanguageFeatures.registerColorProvider(checkSelector(selector), provider);
|
||||
},
|
||||
registerFoldingProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable => {
|
||||
return extHostLanguageFeatures.registerFoldingProvider(checkSelector(selector), provider);
|
||||
registerFoldingRangeProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable => {
|
||||
return extHostLanguageFeatures.registerFoldingRangeProvider(checkSelector(selector), provider);
|
||||
}),
|
||||
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
|
||||
return extHostLanguageFeatures.setLanguageConfiguration(language, configuration);
|
||||
|
@ -714,9 +714,8 @@ export function createApiFactory(
|
|||
FileType2: extHostTypes.FileType2,
|
||||
FileOpenFlags: files.FileOpenFlags,
|
||||
FileError: files.FileError,
|
||||
FoldingRangeList: extHostTypes.FoldingRangeList,
|
||||
FoldingRange: extHostTypes.FoldingRange,
|
||||
FoldingRangeType: extHostTypes.FoldingRangeType
|
||||
FoldingRangeKind: extHostTypes.FoldingRangeKind
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
|||
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerFoldingProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
|
||||
}
|
||||
|
||||
|
@ -722,7 +722,7 @@ export interface ExtHostLanguageFeaturesShape {
|
|||
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
|
||||
$provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]>;
|
||||
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]>;
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.IFoldingRangeList>;
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.IFoldingRange[]>;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
|
|
|
@ -817,16 +817,16 @@ class FoldingProviderAdapter {
|
|||
|
||||
constructor(
|
||||
private _documents: ExtHostDocuments,
|
||||
private _provider: vscode.FoldingProvider
|
||||
private _provider: vscode.FoldingRangeProvider
|
||||
) { }
|
||||
|
||||
provideFoldingRanges(resource: URI, context: modes.FoldingContext): TPromise<modes.IFoldingRangeList> {
|
||||
provideFoldingRanges(resource: URI, context: modes.FoldingContext): TPromise<modes.IFoldingRange[]> {
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, context, token)).then(list => {
|
||||
if (!Array.isArray(list.ranges)) {
|
||||
return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => {
|
||||
if (!Array.isArray(ranges)) {
|
||||
return void 0;
|
||||
}
|
||||
return TypeConverters.FoldingRangeList.from(list);
|
||||
return ranges.map(TypeConverters.FoldingRange.from);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1178,13 +1178,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
|||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo));
|
||||
}
|
||||
|
||||
registerFoldingProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable {
|
||||
registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new FoldingProviderAdapter(this._documents, provider));
|
||||
this._proxy.$registerFoldingProvider(handle, this._transformDocumentSelector(selector));
|
||||
this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.IFoldingRangeList> {
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.IFoldingRange[]> {
|
||||
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context));
|
||||
}
|
||||
|
||||
|
|
|
@ -623,11 +623,9 @@ export namespace ProgressLocation {
|
|||
}
|
||||
}
|
||||
|
||||
export namespace FoldingRangeList {
|
||||
export function from(rangeList: vscode.FoldingRangeList): modes.IFoldingRangeList {
|
||||
return {
|
||||
ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1, type: r.type }))
|
||||
};
|
||||
export namespace FoldingRange {
|
||||
export function from(r: vscode.FoldingRange): modes.IFoldingRange {
|
||||
return { start: r.start + 1, end: r.end + 1, kind: r.kind };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1841,43 +1841,43 @@ export enum FileType2 {
|
|||
|
||||
//#region folding api
|
||||
|
||||
export class FoldingRangeList {
|
||||
|
||||
ranges: FoldingRange[];
|
||||
|
||||
constructor(ranges: FoldingRange[]) {
|
||||
this.ranges = ranges;
|
||||
}
|
||||
}
|
||||
|
||||
export class FoldingRange {
|
||||
|
||||
startLine: number;
|
||||
start: number;
|
||||
|
||||
endLine: number;
|
||||
end: number;
|
||||
|
||||
type?: FoldingRangeType | string;
|
||||
kind?: FoldingRangeKind;
|
||||
|
||||
constructor(startLine: number, endLine: number, type?: FoldingRangeType | string) {
|
||||
this.startLine = startLine;
|
||||
this.endLine = endLine;
|
||||
this.type = type;
|
||||
constructor(start: number, end: number, kind?: FoldingRangeKind) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
export enum FoldingRangeType {
|
||||
export class FoldingRangeKind {
|
||||
/**
|
||||
* Folding range for a comment
|
||||
* Kind for folding range representing a comment. The value of the kind is 'comment'.
|
||||
*/
|
||||
Comment = 'comment',
|
||||
static readonly Comment = new FoldingRangeKind('comment');
|
||||
/**
|
||||
* Folding range for a imports or includes
|
||||
* Kind for folding range representing a import. The value of the kind is 'imports'.
|
||||
*/
|
||||
Imports = 'imports',
|
||||
static readonly Imports = new FoldingRangeKind('imports');
|
||||
/**
|
||||
* Folding range for a region (e.g. `#region`)
|
||||
* Kind for folding range representing regions (for example marked by `#region`, `#endregion`).
|
||||
* The value of the kind is 'region'.
|
||||
*/
|
||||
Region = 'region'
|
||||
static readonly Region = new FoldingRangeKind('region');
|
||||
|
||||
/**
|
||||
* Creates a new [FoldingRangeKind](#FoldingRangeKind).
|
||||
*
|
||||
* @param value of the kind.
|
||||
*/
|
||||
public constructor(public value: string) {
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
|
Loading…
Reference in a new issue