move to textedit

This commit is contained in:
Pine Wu 2018-02-25 19:27:34 -08:00
parent 18aed804c5
commit 4eca3c3d89
2 changed files with 40 additions and 15 deletions

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TextDocument, CompletionList, CompletionItemKind, CompletionItem } from 'vscode-languageserver-types';
import { TextDocument, CompletionList, CompletionItemKind, CompletionItem, TextEdit, Range, Position } from 'vscode-languageserver-types';
import { WorkspaceFolder } from 'vscode-languageserver-protocol/lib/protocol.workspaceFolders.proposed';
import * as path from 'path';
import * as fs from 'fs';
@ -32,7 +32,7 @@ export function getPathCompletionParticipant(
workspaceRoot = resolveWorkspaceRoot(document, workspaceFolders);
}
const suggestions = providePathSuggestions(value, URI.parse(document.uri).fsPath, workspaceRoot);
const suggestions = providePathSuggestions(value, range, URI.parse(document.uri).fsPath, workspaceRoot);
result.items = [...suggestions, ...result.items];
}
}
@ -55,7 +55,7 @@ function shouldDoPathCompletion(tag: string, attr: string, value: string): boole
return false;
}
export function providePathSuggestions(value: string, activeDocFsPath: string, root?: string): CompletionItem[] {
export function providePathSuggestions(value: string, range: Range, activeDocFsPath: string, root?: string): CompletionItem[] {
if (value.indexOf('/') === -1) {
return [];
}
@ -65,8 +65,8 @@ export function providePathSuggestions(value: string, activeDocFsPath: string, r
}
const lastIndexOfSlash = value.lastIndexOf('/');
const valueAfterLastSlash = value.slice(lastIndexOfSlash + 1);
const valueBeforeLastSlash = value.slice(0, lastIndexOfSlash + 1);
const valueAfterLastSlash = value.slice(lastIndexOfSlash + 1);
const parentDir = startsWith(value, '/')
? path.resolve(root, '.' + valueBeforeLastSlash)
: path.resolve(activeDocFsPath, '..', valueBeforeLastSlash);
@ -75,11 +75,13 @@ export function providePathSuggestions(value: string, activeDocFsPath: string, r
return [];
}
const replaceRange = Range.create(Position.create(range.end.line, range.end.character - valueAfterLastSlash.length), range.end);
return fs.readdirSync(parentDir).map(f => {
return {
label: f,
kind: isDir(path.resolve(parentDir, f)) ? CompletionItemKind.Folder : CompletionItemKind.File,
insertText: f.slice(valueAfterLastSlash.length)
textEdit: TextEdit.replace(replaceRange, f)
};
});
}

View file

@ -7,16 +7,17 @@
import * as assert from 'assert';
import * as path from 'path';
import { providePathSuggestions } from '../../modes/pathCompletion';
import { CompletionItemKind } from 'vscode-languageserver/lib/main';
import { CompletionItemKind, Range, Position } from 'vscode-languageserver-types';
const fixtureRoot = path.resolve(__dirname, '../../../test/pathCompletionFixtures');
suite('Path Completion - Relative Path', () => {
const mockRange = Range.create(Position.create(0, 3), Position.create(0, 5));
test('Current Folder', () => {
const value = './';
const activeFileFsPath = path.resolve(fixtureRoot, 'index.html');
const suggestions = providePathSuggestions(value, activeFileFsPath);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath);
assert.equal(suggestions.length, 3);
assert.equal(suggestions[0].label, 'about');
@ -31,7 +32,7 @@ suite('Path Completion - Relative Path', () => {
test('Parent Folder', () => {
const value = '../';
const activeFileFsPath = path.resolve(fixtureRoot, 'about/about.html');
const suggestions = providePathSuggestions(value, activeFileFsPath);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath);
assert.equal(suggestions.length, 3);
assert.equal(suggestions[0].label, 'about');
@ -46,7 +47,7 @@ suite('Path Completion - Relative Path', () => {
test('Adjacent Folder', () => {
const value = '../src/';
const activeFileFsPath = path.resolve(fixtureRoot, 'about/about.html');
const suggestions = providePathSuggestions(value, activeFileFsPath);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath);
assert.equal(suggestions.length, 2);
assert.equal(suggestions[0].label, 'feature.js');
@ -60,13 +61,15 @@ suite('Path Completion - Relative Path', () => {
});
suite('Path Completion - Absolute Path', () => {
const mockRange = Range.create(Position.create(0, 3), Position.create(0, 5));
test('Root', () => {
const value = '/';
const activeFileFsPath1 = path.resolve(fixtureRoot, 'index.html');
const activeFileFsPath2 = path.resolve(fixtureRoot, 'about/index.html');
const suggestions1 = providePathSuggestions(value, activeFileFsPath1, fixtureRoot);
const suggestions2 = providePathSuggestions(value, activeFileFsPath2, fixtureRoot);
const suggestions1 = providePathSuggestions(value, mockRange, activeFileFsPath1, fixtureRoot);
const suggestions2 = providePathSuggestions(value, mockRange, activeFileFsPath2, fixtureRoot);
const verify = (suggestions) => {
assert.equal(suggestions[0].label, 'about');
@ -85,7 +88,7 @@ suite('Path Completion - Absolute Path', () => {
test('Sub Folder', () => {
const value = '/src/';
const activeFileFsPath = path.resolve(fixtureRoot, 'about/about.html');
const suggestions = providePathSuggestions(value, activeFileFsPath, fixtureRoot);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath, fixtureRoot);
assert.equal(suggestions.length, 2);
assert.equal(suggestions[0].label, 'feature.js');
@ -97,10 +100,12 @@ suite('Path Completion - Absolute Path', () => {
});
suite('Path Completion - Incomplete Path at End', () => {
const mockRange = Range.create(Position.create(0, 3), Position.create(0, 5));
test('Incomplete Path that starts with slash', () => {
const value = '/src/f';
const activeFileFsPath = path.resolve(fixtureRoot, 'about/about.html');
const suggestions = providePathSuggestions(value, activeFileFsPath, fixtureRoot);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath, fixtureRoot);
assert.equal(suggestions.length, 2);
assert.equal(suggestions[0].label, 'feature.js');
@ -113,7 +118,7 @@ suite('Path Completion - Incomplete Path at End', () => {
test('Incomplete Path that does not start with slash', () => {
const value = '../src/f';
const activeFileFsPath = path.resolve(fixtureRoot, 'about/about.html');
const suggestions = providePathSuggestions(value, activeFileFsPath, fixtureRoot);
const suggestions = providePathSuggestions(value, mockRange, activeFileFsPath, fixtureRoot);
assert.equal(suggestions.length, 2);
assert.equal(suggestions[0].label, 'feature.js');
@ -122,4 +127,22 @@ suite('Path Completion - Incomplete Path at End', () => {
assert.equal(suggestions[0].kind, CompletionItemKind.File);
assert.equal(suggestions[1].kind, CompletionItemKind.File);
});
});
});
suite('Path Completion - TextEdit', () => {
test('TextEdit has correct replace text and range', () => {
const value = './';
const activeFileFsPath = path.resolve(fixtureRoot, 'index.html');
const range = Range.create(Position.create(0, 3), Position.create(0, 5));
const suggestions = providePathSuggestions(value, range, activeFileFsPath);
assert.equal(suggestions[0].textEdit.newText, 'about');
assert.equal(suggestions[1].textEdit.newText, 'index.html');
assert.equal(suggestions[2].textEdit.newText, 'src');
assert.equal(suggestions[0].textEdit.range.start.character, 5);
assert.equal(suggestions[1].textEdit.range.start.character, 5);
assert.equal(suggestions[2].textEdit.range.start.character, 5);
});
});