Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
*/

import { prepareExecutable } from './javaServerStarter';
import { LanguageClientOptions, RevealOutputChannelOn, LanguageClient, DidChangeConfigurationNotification, RequestType, TextDocumentPositionParams } from 'vscode-languageclient';
import { LanguageClientOptions, RevealOutputChannelOn, LanguageClient, DidChangeConfigurationNotification, RequestType, TextDocumentPositionParams, RequestType0 } from 'vscode-languageclient';
import * as requirements from './requirements';
import { languages, IndentAction, workspace, window, commands, ExtensionContext, TextDocument, Position, LanguageConfiguration } from "vscode";
import * as path from 'path';
import * as os from 'os';
import { activateTagClosing } from './tagClosing';
import { activateTagClosing, AutoCloseResult } from './tagClosing';

export interface ScopeInfo {
scope : "default" | "global" | "workspace" | "folder";
configurationTarget: boolean;
}

namespace TagCloseRequest {
export const type: RequestType<TextDocumentPositionParams, string, any, any> = new RequestType('xml/closeTag');
export const type: RequestType<TextDocumentPositionParams, AutoCloseResult, any, any> = new RequestType('xml/closeTag');
}

let ignoreAutoCloseTags = false;
Expand Down Expand Up @@ -81,13 +81,14 @@ export function activate(context: ExtensionContext) {
let disposable = languageClient.start();
toDispose.push(disposable);
languageClient.onReady().then(() => {
//init
let tagRequestor = (document: TextDocument, position: Position) => {
//Setup autoCloseTags
let tagProvider = (document: TextDocument, position: Position) => {
let param = languageClient.code2ProtocolConverter.asTextDocumentPositionParams(document, position);
return languageClient.sendRequest(TagCloseRequest.type, param);
let text = languageClient.sendRequest(TagCloseRequest.type, param);
return text;
};

disposable = activateTagClosing(tagRequestor, { xml: true, xsl: true }, 'xml.completion.autoCloseTags');
disposable = activateTagClosing(tagProvider, { xml: true, xsl: true }, 'xml.completion.autoCloseTags');
toDispose.push(disposable);
});
languages.setLanguageConfiguration('xml', getIndentationRules());
Expand Down
37 changes: 27 additions & 10 deletions src/tagClosing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import { window, workspace, Disposable, TextDocumentContentChangeEvent, TextDocument, Position, SnippetString } from 'vscode';
import { window, workspace, Disposable, TextDocumentContentChangeEvent, TextDocument, Position, SnippetString, Range } from 'vscode';

export function activateTagClosing(tagProvider: (document: TextDocument, position: Position) => Thenable<string>, supportedLanguages: { [id: string]: boolean }, configName: string): Disposable {
export interface AutoCloseResult {
snippet: string,
range?: Range
}

export function activateTagClosing(tagProvider: (document: TextDocument, position: Position) => Thenable<AutoCloseResult>, supportedLanguages: { [id: string]: boolean }, configName: string): Disposable {
const TRIGGER_CHARACTERS = ['>', '/'];
let disposables: Disposable[] = [];
workspace.onDidChangeTextDocument(event => onDidChangeTextDocument(event.document, event.contentChanges), null, disposables);

Expand Down Expand Up @@ -50,25 +55,37 @@ export function activateTagClosing(tagProvider: (document: TextDocument, positio
}
let lastChange = changes[changes.length - 1];
let lastCharacter = lastChange.text[lastChange.text.length - 1];
if (lastChange.rangeLength > 0 || lastCharacter !== '>' && lastCharacter !== '/') {
if (lastChange.rangeLength > 0 || lastChange.text.length > 1 || lastCharacter in TRIGGER_CHARACTERS) {
return;
}
let rangeStart = lastChange.range.start;
let version = document.version;
timeout = setTimeout(() => {
let position = new Position(rangeStart.line, rangeStart.character + lastChange.text.length);
tagProvider(document, position).then(text => {
tagProvider(document, position).then(result => {
let text = result.snippet;
let replaceLocation : Position | Range;
let range : Range = result.range;
if(range != null) {
// re-create Range
let line = range.start.line;
let character = range.start.character;
let startPosition = new Position(line, character);
line = range.end.line;
character = range.end.character;
let endPosition = new Position(line, character);
replaceLocation = new Range(startPosition, endPosition);
}
else {
replaceLocation = position;
}
if (text && isEnabled) {
let activeEditor = window.activeTextEditor;
if (activeEditor) {
let activeDocument = activeEditor.document;
if (document === activeDocument && activeDocument.version === version) {
let selections = activeEditor.selections;
if (selections.length && selections.some(s => s.active.isEqual(position))) {
activeEditor.insertSnippet(new SnippetString(text), selections.map(s => s.active));
} else {
activeEditor.insertSnippet(new SnippetString(text), position);
}
activeEditor.insertSnippet(new SnippetString(text), replaceLocation);

}
}
}
Expand Down