Skip to content

Commit

Permalink
#2350 implement 'registerCompletionItemProvider' method
Browse files Browse the repository at this point in the history
Signed-off-by: Yevhen Vydolob <[email protected]>
  • Loading branch information
evidolob committed Aug 14, 2018
1 parent 26ac9ad commit 26fa9af
Show file tree
Hide file tree
Showing 15 changed files with 1,188 additions and 71 deletions.
137 changes: 137 additions & 0 deletions packages/plugin-ext/src/api/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/********************************************************************************
* 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';
// Should contains internal Plugin API types

export interface Range {
/**
* Line number on which the range starts (starts at 1).
*/
readonly startLineNumber: number;
/**
* Column on which the range starts in line `startLineNumber` (starts at 1).
*/
readonly startColumn: number;
/**
* Line number on which the range ends.
*/
readonly endLineNumber: number;
/**
* Column on which the range ends in line `endLineNumber`.
*/
readonly endColumn: number;
}

export interface MarkdownString {
value: string;
isTrusted?: boolean;
}

export interface SerializedDocumentFilter {
$serialized: true;
language?: string;
scheme?: string;
pattern?: theia.GlobPattern;
}

export enum CompletionTriggerKind {
Invoke = 0,
TriggerCharacter = 1,
TriggerForIncompleteCompletions = 2
}

export interface CompletionContext {
triggerKind: CompletionTriggerKind;
triggerCharacter?: string;
}

export interface Completion {
label: string;
insertText: string;
type: CompletionType;
detail?: string;
documentation?: string | MarkdownString;
filterText?: string;
sortText?: string;
preselect?: boolean;
noAutoAccept?: boolean;
commitCharacters?: string[];
overwriteBefore?: number;
overwriteAfter?: number;
additionalTextEdits?: SingleEditOperation[];
command?: Command;
snippetType?: SnippetType;
}
export interface SingleEditOperation {
range: Range;
text: string;
/**
* This indicates that this operation has "insert" semantics.
* i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved.
*/
forceMoveMarkers?: boolean;
}

export type SnippetType = 'internal' | 'textmate';

export interface Command {
id: string;
title: string;
tooltip?: string;
// tslint:disable-next-line:no-any
arguments?: any[];
}

export type CompletionType = 'method'
| 'function'
| 'constructor'
| 'field'
| 'variable'
| 'class'
| 'struct'
| 'interface'
| 'module'
| 'property'
| 'event'
| 'operator'
| 'unit'
| 'value'
| 'constant'
| 'enum'
| 'enum-member'
| 'keyword'
| 'snippet'
| 'text'
| 'color'
| 'file'
| 'reference'
| 'customcolor'
| 'folder'
| 'type-parameter';

export class IdObject {
id?: number;
}
export interface CompletionDto extends Completion {
id: number;
parentId: number;
}

export interface CompletionResultDto extends IdObject {
completions: CompletionDto[];
incomplete?: boolean;
}
38 changes: 13 additions & 25 deletions packages/plugin-ext/src/api/plugin-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ import { TextEditorLineNumbersStyle, EndOfLine, OverviewRulerLane, IndentAction
import { UriComponents } from '../common/uri-components';
import { PreferenceChange } from '@theia/core/lib/browser';
import { ConfigurationTarget } from '../plugin/types-impl';
import {
SerializedDocumentFilter,
CompletionContext,
MarkdownString,
Range,
Completion,
CompletionResultDto
} from './model';

export interface HostedPluginManagerExt {
$initialize(contextPath: string, pluginMetadata: PluginMetadata): void;
Expand Down Expand Up @@ -227,25 +235,6 @@ export interface Position {
readonly column: number;
}

export interface Range {
/**
* Line number on which the range starts (starts at 1).
*/
readonly startLineNumber: number;
/**
* Column on which the range starts in line `startLineNumber` (starts at 1).
*/
readonly startColumn: number;
/**
* Line number on which the range ends.
*/
readonly endLineNumber: number;
/**
* Column on which the range ends in line `endLineNumber`.
*/
readonly endColumn: number;
}

export interface Selection {
/**
* The line number on which the selection has started.
Expand Down Expand Up @@ -402,11 +391,6 @@ export interface DecorationInstanceRenderOptions extends ThemeDecorationInstance
dark?: ThemeDecorationInstanceRenderOptions;
}

export interface MarkdownString {
value: string;
isTrusted?: boolean;
}

export interface DecorationOptions {
range: Range;
hoverMessage?: MarkdownString | MarkdownString[];
Expand Down Expand Up @@ -559,14 +543,18 @@ export interface SerializedLanguageConfiguration {
indentationRules?: SerializedIndentationRule;
onEnterRules?: SerializedOnEnterRule[];
}
export interface LanguagesExt {

export interface LanguagesExt {
$provideCompletionItems(handle: number, resource: UriComponents, position: Position, context: CompletionContext): Promise<CompletionResultDto | undefined>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: Position, completion: Completion): Promise<Completion>;
$releaseCompletionItems(handle: number, id: number): void;
}

export interface LanguagesMain {
$getLanguages(): Promise<string[]>;
$setLanguageConfiguration(handle: number, languageId: string, configuration: SerializedLanguageConfiguration): void;
$unregister(handle: number): void;
$registerCompletionSupport(handle: number, selector: SerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void;
}

export const PLUGIN_RPC_CONTEXT = {
Expand Down
25 changes: 25 additions & 0 deletions packages/plugin-ext/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/**
* Returns `true` if the parameter has type "object" and not null, an array, a regexp, a date.
*/
// tslint:disable-next-line:no-any
export function isObject(obj: any): boolean {
return typeof obj === 'object'
&& obj !== null
Expand All @@ -25,6 +26,30 @@ export function isObject(obj: any): boolean {
&& !(obj instanceof Date);
}

// tslint:disable-next-line:no-any
export function mixin(destination: any, source: any, overwrite: boolean = true): any {
if (!isObject(destination)) {
return source;
}

if (isObject(source)) {
Object.keys(source).forEach(key => {
if (key in destination) {
if (overwrite) {
if (isObject(destination[key]) && isObject(source[key])) {
mixin(destination[key], source[key], overwrite);
} else {
destination[key] = source[key];
}
}
} else {
destination[key] = source[key];
}
});
}
return destination;
}

export enum LogType {
Info,
Error
Expand Down
36 changes: 33 additions & 3 deletions packages/plugin-ext/src/main/browser/languages-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ import {
SerializedLanguageConfiguration,
SerializedRegExp,
SerializedIndentationRule,
SerializedOnEnterRule
SerializedOnEnterRule,
MAIN_RPC_CONTEXT,
LanguagesExt
} from '../../api/plugin-api';
import { SerializedDocumentFilter } from '../../api/model';
import { RPCProtocol } from '../../api/rpc-protocol';
import { fromLanguageSelector } from '../../plugin/type-converters';

export class LanguagesMainImpl implements LanguagesMain {

private readonly proxy: LanguagesExt;
private readonly disposables = new Map<number, monaco.IDisposable>();
constructor() {

constructor(rpc: RPCProtocol) {
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.LANGUAGES_EXT);
}

$getLanguages(): Promise<string[]> {
Expand All @@ -52,6 +58,30 @@ export class LanguagesMainImpl implements LanguagesMain {

this.disposables.set(handle, monaco.languages.setLanguageConfiguration(languageId, config));
}

$registerCompletionSupport(handle: number, selector: SerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void {
this.disposables.set(handle, monaco.modes.SuggestRegistry.register(fromLanguageSelector(selector)!, {
triggerCharacters,
provideCompletionItems: (model: monaco.editor.ITextModel,
position: monaco.Position,
context: monaco.modes.SuggestContext,
token: monaco.CancellationToken): Thenable<monaco.modes.ISuggestResult> =>
Promise.resolve(this.proxy.$provideCompletionItems(handle, model.uri, position, context)).then(result => {
if (!result) {
return undefined!;
}
return {
suggestions: result.completions,
incomplete: result.incomplete,
dispose: () => this.proxy.$releaseCompletionItems(handle, (<any>result)._id)
};
}),
resolveCompletionItem: supportsResolveDetails
? (model, position, suggestion, token) => Promise.resolve(this.proxy.$resolveCompletionItem(handle, model.uri, position, suggestion))
: undefined
}));

}
}

function reviveRegExp(regExp?: SerializedRegExp): RegExp | undefined {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/main/browser/main-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
const outputChannelRegistryMain = new OutputChannelRegistryMainImpl(container);
rpc.set(PLUGIN_RPC_CONTEXT.OUTPUT_CHANNEL_REGISTRY_MAIN, outputChannelRegistryMain);

const languagesMain = new LanguagesMainImpl();
const languagesMain = new LanguagesMainImpl(rpc);
rpc.set(PLUGIN_RPC_CONTEXT.LANGUAGES_MAIN, languagesMain);
}
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/main/browser/text-editor-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import {
TextEditorRevealType,
SingleEditOperation,
ApplyEditsOptions,
Range,
UndoStopOptions,
DecorationOptions
} from '../../api/plugin-api';
import { Range } from '../../api/model';
import { DisposableCollection, Emitter, Event } from '@theia/core';
import { TextEditorCursorStyle, cursorStyleToString } from '../../common/editor-options';
import { TextEditorLineNumbersStyle, EndOfLine } from '../../plugin/types-impl';
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/main/browser/text-editors-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
********************************************************************************/

import {
Range,
TextEditorsMain,
MAIN_RPC_CONTEXT,
TextEditorsExt,
Expand All @@ -28,6 +27,7 @@ import {
DecorationRenderOptions,
DecorationOptions
} from '../../api/plugin-api';
import { Range } from '../../api/model';
import { EditorsAndDocumentsMain } from './editors-and-documents-main';
import { RPCProtocol } from '../../api/rpc-protocol';
import { DisposableCollection } from '@theia/core';
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-ext/src/plugin/document-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
********************************************************************************/

import * as theia from '@theia/plugin';
import { ModelChangedEvent, DocumentsMain, Range as ARange } from '../api/plugin-api';
import { ModelChangedEvent, DocumentsMain } from '../api/plugin-api';
import { Range as ARange } from '../api/model';
import URI from 'vscode-uri';
import { ok } from '../common/assert';
import { Range, Position, EndOfLine } from './types-impl';
Expand Down
Loading

0 comments on commit 26fa9af

Please sign in to comment.