Skip to content

Commit

Permalink
feat: add vue file basic support
Browse files Browse the repository at this point in the history
  • Loading branch information
yoyo930021 committed Dec 11, 2019
1 parent 4d4e254 commit b921b16
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"Programming Languages"
],
"activationEvents": [
"onLanguage:scss"
"onLanguage:scss",
"onLanguage:vue"
],
"main": "./out/client.js",
"contributes": {
Expand Down
2 changes: 1 addition & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
39 changes: 30 additions & 9 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
});

Expand Down
8 changes: 7 additions & 1 deletion src/services/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down Expand Up @@ -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 });
Expand Down
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 };
}

0 comments on commit b921b16

Please sign in to comment.