Skip to content

Commit 9233842

Browse files
committed
feat: css vscode language service integration
1 parent 62b3dd6 commit 9233842

File tree

10 files changed

+111
-12
lines changed

10 files changed

+111
-12
lines changed

.brackets.json

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
"defaultExtension": "js",
1111
"language": {
1212
"javascript": {
13-
"linting.prefer": ["ESLint", "JSHint"],
13+
"linting.prefer": [
14+
"ESLint",
15+
"JSHint"
16+
],
1417
"linting.usePreferredOnly": true
1518
}
1619
},
@@ -25,5 +28,9 @@
2528
}
2629
},
2730
"spaceUnits": 4,
28-
"useTabChar": false
29-
}
31+
"useTabChar": false,
32+
"livePreviewUseDevServer": false,
33+
"livePreviewServerURL": "",
34+
"livePreviewServerProjectPath": "/",
35+
"livePreviewHotReloadSupported": false
36+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ test/thirdparty/jasmine-reporters
5050
/src/thirdparty/bugsnag.min.js.map
5151
/src/thirdparty/bugsnag-performance.min.js
5252
/src/thirdparty/bugsnag-performance.min.js.map
53+
/src/thirdparty/language-worker.js
5354

5455
# ignore files copied from node_modules to src/thirdparty
5556
# https://github.com/phcode-dev/phoenix/issues/10

gulpfile.js/thirdparty-lib-copy.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ let copyThirdPartyLibs = series(
9191
// @phcode/fs
9292
copyFiles.bind(copyFiles, ['node_modules/@phcode/fs/dist/virtualfs.js',
9393
'node_modules/@phcode/fs/dist/virtualfs.js.map'], 'src/phoenix'),
94+
// @phcode/language-support . // replace below with language-worker-debug.js if you wanna debug
95+
copyFiles.bind(copyFiles, ['node_modules/@phcode/language-support/dist/language-worker.js'],
96+
'src/thirdparty/'),
97+
copyLicence.bind(copyLicence, 'node_modules/@phcode/language-support/LICENSE-thirdParty', 'language-services'),
9498
// lessjs
9599
copyFiles.bind(copyFiles, ['node_modules/less/dist/less.min.js', 'node_modules/less/dist/less.min.js.map'],
96100
'src/thirdparty'),

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
"@fortawesome/fontawesome-free": "^6.1.2",
9292
"@highlightjs/cdn-assets": "^11.5.1",
9393
"@phcode/fs": "^3.0.0",
94+
"@phcode/language-support": "^1.0.2",
9495
"@pixelbrackets/gfm-stylesheet": "^1.1.0",
9596
"@prettier/plugin-php": "^0.22.2",
9697
"@uiw/file-icons": "^1.3.2",

src/extensions/default/HTMLCodeHints/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ define(function (require, exports, module) {
258258
CSSUtils.getAllCssSelectorsInProject({includeClasses: true}).then(hints=>{
259259
const result = $.map(hints, function (pvalue) {
260260
pvalue = pvalue.slice(1); // remove.
261+
if(!pvalue || pvalue.includes("#") || pvalue.includes("\\") || pvalue.includes("/")){
262+
return null;
263+
}
261264
return StringMatch.stringMatch(pvalue, queryStr, { preferPrefixMatches: true });
262265
});
263266
const validHints = formatHints(result);

src/language/CSSUtils.js

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ define(function (require, exports, module) {
3737
LanguageManager = require("language/LanguageManager"),
3838
ProjectManager = require("project/ProjectManager"),
3939
TokenUtils = require("utils/TokenUtils"),
40+
IndexingWorker = require("worker/IndexingWorker"),
4041
_ = require("thirdparty/lodash");
4142

4243
// Constants
@@ -1816,11 +1817,12 @@ define(function (require, exports, module) {
18161817
return selectors;
18171818
}
18181819
for(let item of selectorList) {
1819-
if(regex.test(item.selector)){
1820+
if(regex.test(item) || !item.trim()){
18201821
// this happens for scss selectors like #${var}-something. we ignore that for now instead of resolving
18211822
continue;
18221823
}
1823-
selectors.add(extractSelectorBase(item.selector)); // x:hover or x::some -> x
1824+
const extracted = extractSelectorBase(item);
1825+
extracted.trim() && selectors.add(extracted); // x:hover or x::some -> x
18241826
}
18251827
return selectors;
18261828
}
@@ -1845,22 +1847,41 @@ define(function (require, exports, module) {
18451847
}
18461848
}
18471849

1850+
const MODE_MAP = {
1851+
css: "CSS",
1852+
less: "LESS",
1853+
scss: "SCSS"
1854+
};
1855+
18481856
function _loadFileAndScanCSSSelectorCached(fullPath) {
18491857
return new Promise(resolve=>{
18501858
DocumentManager.getDocumentForPath(fullPath)
18511859
.done(function (doc) {
18521860
// Find all matching rules for the given CSS file's content, and add them to the
18531861
// overall search result
1854-
let selectors;
1862+
let selectors = new Set();
18551863
const cachedSelectors = CSSSelectorCache.get(fullPath);
18561864
if(cachedSelectors){
1857-
selectors = cachedSelectors;
1858-
} else {
1859-
selectors = extractAllSelectors(doc.getText(), doc.getLanguage().getMode());
1860-
selectors = _extractSelectorSet(selectors);
1861-
CSSSelectorCache.set(fullPath, selectors);
1865+
resolve(cachedSelectors);
1866+
return;
1867+
}
1868+
const langID = doc.getLanguage().getId();
1869+
if(!MODE_MAP[langID]){
1870+
console.log("Cannot parse CSS for mode :", langID, "ignoring", fullPath);
1871+
resolve(selectors);
1872+
return;
18621873
}
1863-
resolve(selectors);
1874+
console.log("scanning file for css selector collation: ", fullPath);
1875+
IndexingWorker.execPeer("css_getAllSymbols",
1876+
{text: doc.getText(), cssMode: "CSS", filePath: fullPath})
1877+
.then((selectorArray)=>{
1878+
selectors = _extractSelectorSet(selectorArray);
1879+
CSSSelectorCache.set(fullPath, selectors);
1880+
resolve(selectors);
1881+
}).catch(err=>{
1882+
console.warn("CSS language service unable to get selectors for" + fullPath, err);
1883+
resolve(selectors); // still resolve, so the overall result doesn't reject
1884+
});
18641885
})
18651886
.fail(function (error) {
18661887
console.warn("Unable to read " + fullPath + " during CSS selector search:", error);
@@ -1923,6 +1944,10 @@ define(function (require, exports, module) {
19231944
}
19241945

19251946
AppInit.appReady(function () {
1947+
if(Phoenix.isSpecRunnerWindow){
1948+
// no unit tests event handlers
1949+
return;
1950+
}
19261951
ProjectManager.on(ProjectManager.EVENT_PROJECT_FILE_CHANGED, _projectFileChanged);
19271952
ProjectManager.on(ProjectManager.EVENT_PROJECT_OPEN, ()=>{
19281953
CSSSelectorCache.clear();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## vscode-css-languageservice
2+
The MIT License (MIT)
3+
Copyright (c) Microsoft
4+
5+
## test/thirparty/chai
6+
MIT License
7+
Copyright (c) 2017 Chai.js Assertion Library
8+
9+
## test/thirparty/mocha
10+
(The MIT License)
11+
Copyright (c) 2011-2022 OpenJS Foundation and contributors, https://openjsf.org

src/worker/file-Indexing-Worker-thread.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const Phoenix = {
3131
importScripts('../phoenix/virtualfs.js');
3232
importScripts('../utils/EventDispatcher.js');
3333
importScripts('./WorkerComm.js');
34+
importScripts('./language-service-worker-thread.js');
3435

3536
virtualfs.debugMode = debugMode;
3637

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* GNU AGPL-3.0 License
3+
*
4+
* Copyright (c) 2021 - present core.ai . All rights reserved.
5+
* Original work Copyright (c) 2015 - 2021 Adobe Systems Incorporated. All rights reserved.
6+
*
7+
* This program is free software: you can redistribute it and/or modify it
8+
* under the terms of the GNU Affero General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
15+
* for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see https://opensource.org/licenses/AGPL-3.0.
19+
*
20+
*/
21+
22+
/*global virtualfs, fs, WorkerComm, CSSLanguageService */
23+
24+
importScripts('../thirdparty/language-worker.js');
25+
26+
(function () {
27+
function getAllSymbols({text, cssMode, filePath}) {
28+
if(!CSSLanguageService.CSS_MODES[cssMode]) {
29+
throw new Error("Language mode not supported "+ cssMode);
30+
}
31+
return CSSLanguageService.getAllSymbols(text, cssMode, filePath);
32+
}
33+
34+
WorkerComm.setExecHandler("css_getAllSymbols", getAllSymbols);
35+
}());

0 commit comments

Comments
 (0)