mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-19 14:22:19 +01:00
add executeFoldingRangeProvider command (#172968)
* add executeFoldingRangeProvider command * add jsdoc for FoldingRangeKind.fromValue
This commit is contained in:
@@ -191,4 +191,47 @@ suite('vscode API - languages', () => {
|
||||
assert.ok(result!.items.some(i => i.label === 'foo'), 'Results do not include "foo"');
|
||||
});
|
||||
|
||||
test('folding command', async function () {
|
||||
const content = `[
|
||||
/**
|
||||
* This is a comment with indentation issues
|
||||
*/
|
||||
{
|
||||
"name": "bag of items",
|
||||
"items": [
|
||||
"foo", "bar"
|
||||
]
|
||||
}
|
||||
]`;
|
||||
const uri = await createRandomFile(content, undefined, '.jsonc');
|
||||
await vscode.workspace.openTextDocument(uri);
|
||||
const jsonExtension = await vscode.extensions.getExtension('vscode.json-language-features');
|
||||
assert.ok(jsonExtension);
|
||||
await jsonExtension.activate();
|
||||
const result1 = await vscode.commands.executeCommand<vscode.FoldingRange[]>('vscode.executeFoldingRangeProvider', uri);
|
||||
assert.deepEqual(result1, [
|
||||
{ start: 0, end: 9 },
|
||||
{ start: 1, end: 3, kind: vscode.FoldingRangeKind.Comment },
|
||||
{ start: 4, end: 8 },
|
||||
{ start: 6, end: 7 },
|
||||
]);
|
||||
|
||||
await vscode.workspace.getConfiguration('editor').update('foldingStrategy', 'indentation');
|
||||
try {
|
||||
const result2 = await vscode.commands.executeCommand<vscode.FoldingRange[]>('vscode.executeFoldingRangeProvider', uri);
|
||||
assert.deepEqual(result2, [
|
||||
{ start: 0, end: 10 },
|
||||
{ start: 1, end: 2 },
|
||||
{ start: 3, end: 9 },
|
||||
{ start: 4, end: 8 },
|
||||
{ start: 6, end: 7 },
|
||||
]);
|
||||
await vscode.workspace.getConfiguration('editor').update('folding', false);
|
||||
const result3 = await vscode.commands.executeCommand<vscode.FoldingRange[]>('vscode.executeFoldingRangeProvider', uri);
|
||||
assert.deepEqual(result3, []);
|
||||
} finally {
|
||||
await vscode.workspace.getConfiguration('editor').update('foldingStrategy', undefined);
|
||||
await vscode.workspace.getConfiguration('editor').update('folding', undefined);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1394,6 +1394,20 @@ export class FoldingRangeKind {
|
||||
*/
|
||||
static readonly Region = new FoldingRangeKind('region');
|
||||
|
||||
/**
|
||||
* Returns a {@link FoldingRangeKind} for the given value.
|
||||
*
|
||||
* @param value of the kind.
|
||||
*/
|
||||
static fromValue(value: string) {
|
||||
switch (value) {
|
||||
case 'comment': return FoldingRangeKind.Comment;
|
||||
case 'imports': return FoldingRangeKind.Imports;
|
||||
case 'region': return FoldingRangeKind.Region;
|
||||
}
|
||||
return new FoldingRangeKind(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link FoldingRangeKind}.
|
||||
*
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { CancelablePromise, createCancelablePromise, Delayer, RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { illegalArgument, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
@@ -21,7 +21,7 @@ import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IModelContentChangedEvent } from 'vs/editor/common/textModelEvents';
|
||||
import { FoldingRangeKind, FoldingRangeProvider } from 'vs/editor/common/languages';
|
||||
import { FoldingRange, FoldingRangeKind, FoldingRangeProvider } from 'vs/editor/common/languages';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { CollapseMemento, FoldingModel, getNextFoldLine, getParentFoldLine as getParentFoldLine, getPreviousFoldLine, setCollapseStateAtLevel, setCollapseStateForMatchingLines, setCollapseStateForRest, setCollapseStateForType, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateUp, toggleCollapseState } from 'vs/editor/contrib/folding/browser/foldingModel';
|
||||
import { HiddenRangeModel } from 'vs/editor/contrib/folding/browser/hiddenRangeModel';
|
||||
@@ -37,6 +37,10 @@ import { IFeatureDebounceInformation, ILanguageFeatureDebounceService } from 'vs
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
const CONTEXT_FOLDING_ENABLED = new RawContextKey<boolean>('foldingEnabled', false);
|
||||
|
||||
@@ -75,6 +79,11 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
|
||||
private static _foldingRangeSelector: FoldingRangeProviderSelector | undefined;
|
||||
|
||||
public static getFoldingRangeProviders(languageFeaturesService: ILanguageFeaturesService, model: ITextModel): FoldingRangeProvider[] {
|
||||
const foldingRangeProviders = languageFeaturesService.foldingRangeProvider.ordered(model);
|
||||
return (FoldingController._foldingRangeSelector?.(foldingRangeProviders, model)) ?? foldingRangeProviders;
|
||||
}
|
||||
|
||||
public static setFoldingRangeProviderSelector(foldingRangeSelector: FoldingRangeProviderSelector): IDisposable {
|
||||
FoldingController._foldingRangeSelector = foldingRangeSelector;
|
||||
return { dispose: () => { FoldingController._foldingRangeSelector = undefined; } };
|
||||
@@ -289,8 +298,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
const indentRangeProvider = new IndentRangeProvider(editorModel, this.languageConfigurationService, this._foldingLimitReporter);
|
||||
this.rangeProvider = indentRangeProvider; // fallback
|
||||
if (this._useFoldingProviders && this.foldingModel) {
|
||||
const foldingProviders = this.languageFeaturesService.foldingRangeProvider.ordered(this.foldingModel.textModel);
|
||||
const selectedProviders = (FoldingController._foldingRangeSelector?.(foldingProviders, editorModel)) ?? foldingProviders;
|
||||
const selectedProviders = FoldingController.getFoldingRangeProviders(this.languageFeaturesService, editorModel);
|
||||
if (selectedProviders.length > 0) {
|
||||
this.rangeProvider = new SyntaxRangeProvider(editorModel, selectedProviders, () => this.triggerFoldingModelChanged(), this._foldingLimitReporter, indentRangeProvider);
|
||||
}
|
||||
@@ -1198,3 +1206,55 @@ for (let i = 1; i <= 7; i++) {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_executeFoldingRangeProvider', async function (accessor, ...args) {
|
||||
const [resource] = args;
|
||||
if (!(resource instanceof URI)) {
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
|
||||
|
||||
const model = accessor.get(IModelService).getModel(resource);
|
||||
if (!model) {
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
if (!configurationService.getValue('editor.folding', { resource })) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const languageConfigurationService = accessor.get(ILanguageConfigurationService);
|
||||
|
||||
const strategy = configurationService.getValue('editor.foldingStrategy', { resource });
|
||||
const foldingLimitReporter = {
|
||||
get limit() {
|
||||
return <number>configurationService.getValue('editor.foldingMaximumRegions', { resource });
|
||||
},
|
||||
report: (info: FoldingLimitInfo) => { }
|
||||
};
|
||||
|
||||
const indentRangeProvider = new IndentRangeProvider(model, languageConfigurationService, foldingLimitReporter);
|
||||
let rangeProvider: RangeProvider = indentRangeProvider;
|
||||
if (strategy !== 'indentation') {
|
||||
const providers = FoldingController.getFoldingRangeProviders(languageFeaturesService, model);
|
||||
if (providers.length) {
|
||||
rangeProvider = new SyntaxRangeProvider(model, providers, () => { }, foldingLimitReporter, indentRangeProvider);
|
||||
}
|
||||
}
|
||||
const ranges = await rangeProvider.compute(CancellationToken.None);
|
||||
const result: FoldingRange[] = [];
|
||||
try {
|
||||
if (ranges) {
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const type = ranges.getType(i);
|
||||
result.push({ start: ranges.getStartLineNumber(i), end: ranges.getEndLineNumber(i), kind: type ? FoldingRangeKind.fromValue(type) : undefined });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
rangeProvider.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Vendored
+6
@@ -7313,6 +7313,12 @@ declare namespace monaco.languages {
|
||||
* The value of the kind is 'region'.
|
||||
*/
|
||||
static readonly Region: FoldingRangeKind;
|
||||
/**
|
||||
* Returns a {@link FoldingRangeKind} for the given value.
|
||||
*
|
||||
* @param value of the kind.
|
||||
*/
|
||||
static fromValue(value: string): FoldingRangeKind;
|
||||
/**
|
||||
* Creates a new {@link FoldingRangeKind}.
|
||||
*
|
||||
|
||||
@@ -338,6 +338,18 @@ const newCommands: ApiCommand[] = [
|
||||
return result.map(typeConverters.InlayHint.to.bind(undefined, converter));
|
||||
})
|
||||
),
|
||||
// --- folding
|
||||
new ApiCommand(
|
||||
'vscode.executeFoldingRangeProvider', '_executeFoldingRangeProvider', 'Execute folding range provider',
|
||||
[ApiCommandArgument.Uri],
|
||||
new ApiCommandResult<languages.FoldingRange[] | undefined, vscode.FoldingRange[] | undefined>('A promise that resolves to an array of FoldingRange objects', (result, args) => {
|
||||
if (result) {
|
||||
return result.map(typeConverters.FoldingRange.to);
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
),
|
||||
|
||||
// --- notebooks
|
||||
new ApiCommand(
|
||||
'vscode.resolveNotebookContentProviders', '_resolveNotebookContentProvider', 'Resolve Notebook Content Providers',
|
||||
|
||||
@@ -1382,6 +1382,13 @@ export namespace FoldingRange {
|
||||
}
|
||||
return range;
|
||||
}
|
||||
export function to(r: languages.FoldingRange): vscode.FoldingRange {
|
||||
const range: vscode.FoldingRange = { start: r.start - 1, end: r.end - 1 };
|
||||
if (r.kind) {
|
||||
range.kind = FoldingRangeKind.to(r.kind);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace FoldingRangeKind {
|
||||
@@ -1398,6 +1405,19 @@ export namespace FoldingRangeKind {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
export function to(kind: languages.FoldingRangeKind | undefined): vscode.FoldingRangeKind | undefined {
|
||||
if (kind) {
|
||||
switch (kind.value) {
|
||||
case languages.FoldingRangeKind.Comment.value:
|
||||
return types.FoldingRangeKind.Comment;
|
||||
case languages.FoldingRangeKind.Imports.value:
|
||||
return types.FoldingRangeKind.Imports;
|
||||
case languages.FoldingRangeKind.Region.value:
|
||||
return types.FoldingRangeKind.Region;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export interface TextEditorOpenOptions extends vscode.TextDocumentShowOptions {
|
||||
|
||||
Reference in New Issue
Block a user