Skip to content

Commit d9a93de

Browse files
Handles modification of autoCloseTags from the server side.
Signed-off-by: Nikolas Komonen <nikolaskomonen@gmail.com>
1 parent 7aaa9b0 commit d9a93de

File tree

2 files changed

+35
-17
lines changed

2 files changed

+35
-17
lines changed

src/extension.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111
*/
1212

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

2121
export interface ScopeInfo {
2222
scope : "default" | "global" | "workspace" | "folder";
2323
configurationTarget: boolean;
2424
}
2525

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

3030
let ignoreAutoCloseTags = false;
@@ -81,13 +81,14 @@ export function activate(context: ExtensionContext) {
8181
let disposable = languageClient.start();
8282
toDispose.push(disposable);
8383
languageClient.onReady().then(() => {
84-
//init
85-
let tagRequestor = (document: TextDocument, position: Position) => {
84+
//Setup autoCloseTags
85+
let tagProvider = (document: TextDocument, position: Position) => {
8686
let param = languageClient.code2ProtocolConverter.asTextDocumentPositionParams(document, position);
87-
return languageClient.sendRequest(TagCloseRequest.type, param);
87+
let text = languageClient.sendRequest(TagCloseRequest.type, param);
88+
return text;
8889
};
8990

90-
disposable = activateTagClosing(tagRequestor, { xml: true, xsl: true }, 'xml.completion.autoCloseTags');
91+
disposable = activateTagClosing(tagProvider, { xml: true, xsl: true }, 'xml.completion.autoCloseTags');
9192
toDispose.push(disposable);
9293
});
9394
languages.setLanguageConfiguration('xml', getIndentationRules());

src/tagClosing.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
*--------------------------------------------------------------------------------------------*/
77
'use strict';
88

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

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

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

@@ -50,25 +55,37 @@ export function activateTagClosing(tagProvider: (document: TextDocument, positio
5055
}
5156
let lastChange = changes[changes.length - 1];
5257
let lastCharacter = lastChange.text[lastChange.text.length - 1];
53-
if (lastChange.rangeLength > 0 || lastCharacter !== '>' && lastCharacter !== '/') {
58+
if (lastChange.rangeLength > 0 || lastChange.text.length > 1 || lastCharacter in TRIGGER_CHARACTERS) {
5459
return;
5560
}
5661
let rangeStart = lastChange.range.start;
5762
let version = document.version;
5863
timeout = setTimeout(() => {
5964
let position = new Position(rangeStart.line, rangeStart.character + lastChange.text.length);
60-
tagProvider(document, position).then(text => {
65+
tagProvider(document, position).then(result => {
66+
let text = result.snippet;
67+
let replaceLocation : Position | Range;
68+
let range : Range = result.range;
69+
if(range != null) {
70+
// re-create Range
71+
let line = range.start.line;
72+
let character = range.start.character;
73+
let startPosition = new Position(line, character);
74+
line = range.end.line;
75+
character = range.end.character;
76+
let endPosition = new Position(line, character);
77+
replaceLocation = new Range(startPosition, endPosition);
78+
}
79+
else {
80+
replaceLocation = position;
81+
}
6182
if (text && isEnabled) {
6283
let activeEditor = window.activeTextEditor;
6384
if (activeEditor) {
6485
let activeDocument = activeEditor.document;
6586
if (document === activeDocument && activeDocument.version === version) {
66-
let selections = activeEditor.selections;
67-
if (selections.length && selections.some(s => s.active.isEqual(position))) {
68-
activeEditor.insertSnippet(new SnippetString(text), selections.map(s => s.active));
69-
} else {
70-
activeEditor.insertSnippet(new SnippetString(text), position);
71-
}
87+
activeEditor.insertSnippet(new SnippetString(text), replaceLocation);
88+
7289
}
7390
}
7491
}

0 commit comments

Comments
 (0)