Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add vue file basic support, alias path, fix #79 #53 #101

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
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
Next Next commit
feat: add vue file basic support
yoyo930021 committed Dec 11, 2019
commit b921b169a3639a3e4cf52d504f44bc52dc53a805
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -25,7 +25,8 @@
"Programming Languages"
],
"activationEvents": [
"onLanguage:scss"
"onLanguage:scss",
"onLanguage:vue"
],
"main": "./out/client.js",
"contributes": {
2 changes: 1 addition & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ export function activate(context: vscode.ExtensionContext) {
};

const clientOptions: LanguageClientOptions = {
documentSelector: ['scss'],
documentSelector: ['scss', 'vue'],
synchronize: {
configurationSection: ['scss'],
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.scss')
39 changes: 30 additions & 9 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ import { doSignatureHelp } from './providers/signatureHelp';
import { goDefinition } from './providers/goDefinition';
import { searchWorkspaceSymbol } from './providers/workspaceSymbol';
import { findFiles } from './utils/fs';
import { getSCSSRegionsDocument } from './utils/vue';

let workspaceRoot: string;
let settings: ISettings;
@@ -51,7 +52,7 @@ connection.onInitialize(
storageService = new StorageService();
scannerService = new ScannerService(storageService, settings);

const files = await findFiles('**/*.scss', {
const files = await findFiles('**/*.{scss,vue}', {
cwd: params.rootPath,
deep: settings.scannerDepth,
ignore: settings.scannerExclude
@@ -91,26 +92,46 @@ connection.onDidChangeWatchedFiles(event => {
});

connection.onCompletion(textDocumentPosition => {
const document = documents.get(textDocumentPosition.textDocument.uri);
const offset = document.offsetAt(textDocumentPosition.position);
const { document, offset } = getSCSSRegionsDocument(
documents.get(textDocumentPosition.textDocument.uri),
textDocumentPosition.position
);
if (!document) {
return null;
}
return doCompletion(document, offset, settings, storageService);
});

connection.onHover(textDocumentPosition => {
const document = documents.get(textDocumentPosition.textDocument.uri);
const offset = document.offsetAt(textDocumentPosition.position);
const { document, offset } = getSCSSRegionsDocument(
documents.get(textDocumentPosition.textDocument.uri),
textDocumentPosition.position
);
if (!document) {
return null;
}
return doHover(document, offset, storageService);
});

connection.onSignatureHelp(textDocumentPosition => {
const document = documents.get(textDocumentPosition.textDocument.uri);
const offset = document.offsetAt(textDocumentPosition.position);
const { document, offset } = getSCSSRegionsDocument(
documents.get(textDocumentPosition.textDocument.uri),
textDocumentPosition.position
);
if (!document) {
return null;
}
return doSignatureHelp(document, offset, storageService);
});

connection.onDefinition(textDocumentPosition => {
const document = documents.get(textDocumentPosition.textDocument.uri);
const offset = document.offsetAt(textDocumentPosition.position);
const { document, offset } = getSCSSRegionsDocument(
documents.get(textDocumentPosition.textDocument.uri),
textDocumentPosition.position
);
if (!document) {
return null;
}
return goDefinition(document, offset, storageService);
});

8 changes: 7 additions & 1 deletion src/services/scanner.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { ISettings } from '../types/settings';
import { readFile, fileExists } from '../utils/fs';
import { parseDocument } from './parser';
import StorageService from './storage';
import { isVueFile, getVueSCSSContent } from '../utils/vue';

export default class ScannerService {
constructor(private readonly _storage: StorageService, private readonly _settings: ISettings) {}
@@ -37,7 +38,12 @@ export default class ScannerService {
}

const content = await this._readFile(filepath);
const document = TextDocument.create(originalFilepath, 'scss', 1, content);
const document = TextDocument.create(
originalFilepath,
'scss',
1,
isVueFile(filepath) ? getVueSCSSContent(content) : content
);
const { symbols } = parseDocument(document, null);

this._storage.set(filepath, { ...symbols, filepath });
50 changes: 50 additions & 0 deletions src/utils/vue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { TextDocument, Position } from 'vscode-languageserver';

export function isVueFile(path: string) {
return path.endsWith('.vue');
}

export function getVueSCSSRegions(content: string) {
const regions: Array<[number, number]> = [];
const startRe = /<style[\w=\"\' \n\t]{1,}lang=[\"\']scss[\"\'][\w=\"\' \n\t]{0,}>/g;
const endRe = /<\/style>/g;
/* tslint:disable:no-conditional-assignment */
let start: RegExpExecArray;
let end: RegExpExecArray;
while ((start = startRe.exec(content)) !== null && (end = endRe.exec(content)) !== null) {
regions.push([start.index + start[0].length, end.index]);
}
return regions;
}

export function getVueSCSSContent(content: string) {
const oldContent = content;

let newContent = oldContent
.split('\n')
.map(line => ' '.repeat(line.length))
.join('\n');

for (const r of getVueSCSSRegions(oldContent)) {
newContent = newContent.slice(0, r[0]) + oldContent.slice(r[0], r[1]) + newContent.slice(r[1]);
}

return newContent;
}

function convertVueTextDocument(document: TextDocument) {
return TextDocument.create(document.uri, 'scss', document.version, getVueSCSSContent(document.getText()));
}

export function getSCSSRegionsDocument(document: TextDocument, position: Position) {
const offset = document.offsetAt(position);
if (isVueFile(document.uri)) {
const vueSCSSRegions = getVueSCSSRegions(document.getText());
if (vueSCSSRegions.some(region => region[0] <= offset && region[1] >= offset)) {
return { document: convertVueTextDocument(document), offset };
}
return { document: null, offset };
}

return { document, offset };
}