Skip to content

Commit

Permalink
Implement 'registerFoldingRangeProvider' Languages API
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
  • Loading branch information
akurinnoy committed Jan 2, 2019
1 parent 146315e commit ec797b0
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 9 deletions.
16 changes: 16 additions & 0 deletions packages/plugin-ext/src/api/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,19 @@ export interface WorkspaceSymbolProvider {
export interface WorkspaceSymbolParams {
query: string
}

export interface FoldingContext {
}

export interface FoldingRange {
start: number;
end: number;
kind?: FoldingRangeKind;
}

export class FoldingRangeKind {
static readonly Comment = new FoldingRangeKind('comment');
static readonly Imports = new FoldingRangeKind('imports');
static readonly Region = new FoldingRangeKind('region');
public constructor(public value: string) { }
}
6 changes: 6 additions & 0 deletions packages/plugin-ext/src/api/plugin-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,11 @@ export interface LanguagesExt {
$provideDocumentSymbols(handle: number, resource: UriComponents): Promise<DocumentSymbol[] | undefined>;
$provideWorkspaceSymbols(handle: number, query: string): PromiseLike<SymbolInformation[]>;
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformation): PromiseLike<SymbolInformation>;
$provideFoldingRange(
handle: number,
resource: UriComponents,
context: monaco.languages.FoldingContext
): PromiseLike<monaco.languages.FoldingRange[] | undefined>;
}

export interface LanguagesMain {
Expand All @@ -870,6 +875,7 @@ export interface LanguagesMain {
$emitCodeLensEvent(eventHandle: number, event?: any): void;
$registerOutlineSupport(handle: number, selector: SerializedDocumentFilter[]): void;
$registerWorkspaceSymbolProvider(handle: number): void;
$registerFoldingRangeProvider(handle: number, selector: SerializedDocumentFilter[]): void;
}

export interface WebviewPanelViewState {
Expand Down
23 changes: 23 additions & 0 deletions packages/plugin-ext/src/main/browser/languages-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,29 @@ export class LanguagesMainImpl implements LanguagesMain {
};
}

$registerFoldingRangeProvider(handle: number, selector: SerializedDocumentFilter[]): void {
const languageSelector = fromLanguageSelector(selector);
const provider = this.createFoldingRangeProvider(handle, languageSelector);
const disposable = new DisposableCollection();
for (const language of getLanguages()) {
if (this.matchLanguage(languageSelector, language)) {
disposable.push(monaco.languages.registerFoldingRangeProvider(language, provider));
}
}
this.disposables.set(handle, disposable);
}

createFoldingRangeProvider(handle: number, selector: LanguageSelector | undefined): monaco.languages.FoldingRangeProvider {
return {
provideFoldingRanges: (model, context, token) => {
if (!this.matchModel(selector, MonacoModelIdentifier.fromModel(model))) {
return undefined!;
}
return this.proxy.$provideFoldingRange(handle, model.uri, context).then(v => v!);
}
};
}

$registerQuickFixProvider(handle: number, selector: SerializedDocumentFilter[], codeActionKinds?: string[]): void {
const languageSelector = fromLanguageSelector(selector);
const quickFixProvider = this.createQuickFixProvider(handle, languageSelector, codeActionKinds);
Expand Down
19 changes: 18 additions & 1 deletion packages/plugin-ext/src/plugin/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import { OutlineAdapter } from './languages/outline';
import { ReferenceAdapter } from './languages/reference';
import { WorkspaceSymbolAdapter } from './languages/workspace-symbol';
import { SymbolInformation } from 'vscode-languageserver-types';
import { FoldingProviderAdapter } from './languages/folding';

type Adapter = CompletionAdapter |
SignatureHelpAdapter |
Expand All @@ -88,7 +89,8 @@ type Adapter = CompletionAdapter |
OutlineAdapter |
LinkProviderAdapter |
ReferenceAdapter |
WorkspaceSymbolAdapter;
WorkspaceSymbolAdapter |
FoldingProviderAdapter;

export class LanguagesExtImpl implements LanguagesExt {

Expand Down Expand Up @@ -437,6 +439,21 @@ export class LanguagesExtImpl implements LanguagesExt {
}
// ### Document Symbol Provider end

// ### Folding Range Provider begin
registerFoldingRangeProvider(selector: theia.DocumentSelector, provider: theia.FoldingRangeProvider): theia.Disposable {
const callId = this.addNewAdapter(new FoldingProviderAdapter(provider, this.documents));
this.proxy.$registerFoldingRangeProvider(callId, this.transformDocumentSelector(selector));
return this.createDisposable(callId);
}

$provideFoldingRange(
callId: number,
resource: UriComponents,
context: theia.FoldingContext
): Promise<monaco.languages.FoldingRange[] | undefined> {
return this.withAdapter(callId, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context));
}
// ### Folging Range Provider end
}

function serializeEnterRules(rules?: theia.OnEnterRule[]): SerializedOnEnterRule[] | undefined {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/plugin/languages/code-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class CodeActionAdapter {
provideCodeAction(resource: URI, rangeOrSelection: Range | Selection, context: monaco.languages.CodeActionContext): Promise<monaco.languages.CodeAction[]> {
const document = this.document.getDocumentData(resource);
if (!document) {
return Promise.reject(new Error(`There are no document form ${resource}`));
return Promise.reject(new Error(`There are no document for ${resource}`));
}

const doc = document.document;
Expand Down
47 changes: 47 additions & 0 deletions packages/plugin-ext/src/plugin/languages/folding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/********************************************************************************
* Copyright (C) 2018 Red Hat, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import * as theia from '@theia/plugin';
import { DocumentsExtImpl } from '@theia/plugin-ext/src/plugin/documents';
import URI from 'vscode-uri/lib/umd';
import * as Converter from '../type-converters';
import * as model from '../../api/model';
import { createToken } from '../token-provider';

export class FoldingProviderAdapter {

constructor(
private readonly provider: theia.FoldingRangeProvider,
private readonly documents: DocumentsExtImpl
) { }

provideFoldingRanges(resource: URI, context: model.FoldingContext): Promise<model.FoldingRange[] | undefined> {
const document = this.documents.getDocumentData(resource);
if (!document) {
return Promise.reject(new Error(`There are no document for ${resource}`));
}

const doc = document.document;

return Promise.resolve(this.provider.provideFoldingRanges(doc, context, createToken())).then(ranges => {
if (!Array.isArray(ranges)) {
return undefined;
}

return ranges.map(Converter.fromFoldingRange);
});
}
}
13 changes: 10 additions & 3 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ import {
Task,
Breakpoint,
SourceBreakpoint,
FunctionBreakpoint
FunctionBreakpoint,
FoldingRange,
FoldingRangeKind,
} from './types-impl';
import { SymbolKind } from '../api/model';
import { EditorsAndDocumentsExtImpl } from './editors-and-documents';
Expand Down Expand Up @@ -488,7 +490,10 @@ export function createAPIFactory(
},
registerDocumentSymbolProvider(selector: theia.DocumentSelector, provider: theia.DocumentSymbolProvider): theia.Disposable {
return languagesExt.registerDocumentSymbolProvider(selector, provider);
}
},
registerFoldingRangeProvider(selector: theia.DocumentSelector, provider: theia.FoldingRangeProvider): theia.Disposable {
return languagesExt.registerFoldingRangeProvider(selector, provider);
},
};

const plugins: typeof theia.plugins = {
Expand Down Expand Up @@ -639,7 +644,9 @@ export function createAPIFactory(
Task,
Breakpoint,
SourceBreakpoint,
FunctionBreakpoint
FunctionBreakpoint,
FoldingRange,
FoldingRangeKind,
};
};
}
Expand Down
25 changes: 25 additions & 0 deletions packages/plugin-ext/src/plugin/type-converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,28 @@ export function toSymbolInformation(symbolInformation: SymbolInformation): theia
}
};
}

export function fromFoldingRange(foldingRange: theia.FoldingRange): model.FoldingRange {
const range: model.FoldingRange = {
start: foldingRange.start + 1,
end: foldingRange.end + 1
};
if (foldingRange.kind) {
range.kind = fromFoldingRangeKind(foldingRange.kind);
}
return range;
}

export function fromFoldingRangeKind(kind: theia.FoldingRangeKind | undefined): model.FoldingRangeKind | undefined {
if (kind) {
switch (kind) {
case types.FoldingRangeKind.Comment:
return model.FoldingRangeKind.Comment;
case types.FoldingRangeKind.Imports:
return model.FoldingRangeKind.Imports;
case types.FoldingRangeKind.Region:
return model.FoldingRangeKind.Region;
}
}
return undefined;
}
23 changes: 21 additions & 2 deletions packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -876,8 +876,9 @@ export class DocumentHighlight {
public kind?: DocumentHighlightKind;

constructor(
range: Range,
kind?: DocumentHighlightKind ) {
range: Range,
kind?: DocumentHighlightKind
) {
this.range = range;
this.kind = kind;
}
Expand Down Expand Up @@ -1717,3 +1718,21 @@ export class FunctionBreakpoint extends Breakpoint {
this.functionName = functionName;
}
}

export class FoldingRange {
start: number;
end: number;
kind?: FoldingRangeKind;

constructor(start: number, end: number, kind?: FoldingRangeKind) {
this.start = start;
this.end = end;
this.kind = kind;
}
}

export enum FoldingRangeKind {
Comment = 1,
Imports = 2,
Region = 3
}
23 changes: 21 additions & 2 deletions packages/plugin/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,8 @@ function provideSymbols(document: theia.TextDocument): theia.ProviderResult<thei
A workspace symbol provider allows you register symbols for the symbol search feature.
resolveWorkspaceSymbol is not needed if all SymbolInformation's returned from
provideWorkspaceSymbols have a location. Otherwise resolveWorkspaceSymbol is needed
resolveWorkspaceSymbol is not needed if all SymbolInformation's returned from
provideWorkspaceSymbols have a location. Otherwise resolveWorkspaceSymbol is needed
in order to resolve the location of the SymbolInformation.
Example of workspace symbol provider registration:
Expand Down Expand Up @@ -693,3 +693,22 @@ theia.languages.registerWorkspaceSymbolProvider({
resolveWorkspaceSymbol is needed here because we have not provided the location for every
symbol return from provideWorkspaceSymbol
#### Folding
A folding range provider allows you to add logic to fold and unfold custom regions of source code.
Example of folding range provider registration:
```typescript
const documentsSelector: theia.DocumentSelector = { scheme: 'file', language: 'typescript' };
const provider = { provideFoldingRanges: provideRanges };

const disposable = theia.languages.registerFoldingRangeProvider(documentsSelector, provider);

...

function provideRanges(document: theia.TextDocument): theia.ProviderResult<theia.FoldingRange[]> {
// code here
}
```
Loading

0 comments on commit ec797b0

Please sign in to comment.