Skip to content

Commit

Permalink
feat: Sync core for full web support (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Jun 2, 2023
1 parent 143b8ce commit bf7df8f
Show file tree
Hide file tree
Showing 13 changed files with 487 additions and 369 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -11,8 +11,8 @@
"@lerna-lite/cli": "latest",
"@lerna-lite/publish": "latest",
"@types/node": "latest",
"@volar/source-map": "1.6.9",
"@volar/language-service": "1.6.9",
"@volar/source-map": "1.7.0",
"@volar/language-service": "1.7.0",
"typescript": "latest",
"vscode-languageserver-protocol": "^3.17.3"
}
Expand Down
3 changes: 2 additions & 1 deletion packages/css/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/css"
},
"dependencies": {
"vscode-css-languageservice": "^6.2.3"
"vscode-css-languageservice": "^6.2.3",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
42 changes: 30 additions & 12 deletions packages/css/src/index.ts
@@ -1,7 +1,8 @@
import type { CodeAction, Diagnostic, LocationLink, Service } from '@volar/language-service';
import * as path from 'path';
import { posix as path } from 'path';
import * as css from 'vscode-css-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { URI, Utils } from 'vscode-uri';

export interface Provide {
'css/stylesheet': (document: TextDocument) => css.Stylesheet | undefined;
Expand All @@ -19,16 +20,39 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =
let inited = false;

const stylesheets = new WeakMap<TextDocument, [number, css.Stylesheet]>();
const fileSystemProvider: css.FileSystemProvider = {
stat: async uri => await context.env.fs?.stat(uri) ?? {
type: css.FileType.Unknown,
ctime: 0,
mtime: 0,
size: 0,
},
readDirectory: async (uri) => context.env.fs?.readDirectory(uri) ?? [],
};
const documentContext: css.DocumentContext = {
resolveReference(ref, base) {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const cssLs = css.getCSSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const scssLs = css.getSCSSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const lessLs = css.getLESSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const postcssLs: css.LanguageService = {
Expand All @@ -55,9 +79,7 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =
return worker(document, async (stylesheet, cssLs) => {

const settings = await context.env.getConfiguration?.<css.LanguageSettings>(document.languageId);
const cssResult = context.env.documentContext
? await cssLs.doComplete2(document, position, stylesheet, context.env.documentContext, settings?.completion)
: await cssLs.doComplete(document, position, stylesheet, settings?.completion);
const cssResult = await cssLs.doComplete2(document, position, stylesheet, documentContext, settings?.completion);

return cssResult;
});
Expand Down Expand Up @@ -128,11 +150,7 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =

async provideDocumentLinks(document) {
return await worker(document, (stylesheet, cssLs) => {

if (!context.env.documentContext)
return;

return cssLs.findDocumentLinks2(document, stylesheet, context.env.documentContext);
return cssLs.findDocumentLinks2(document, stylesheet, documentContext);
});
},

Expand Down
3 changes: 2 additions & 1 deletion packages/html/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/html"
},
"dependencies": {
"vscode-html-languageservice": "^5.0.4"
"vscode-html-languageservice": "^5.0.4",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
41 changes: 29 additions & 12 deletions packages/html/src/index.ts
Expand Up @@ -2,13 +2,15 @@ import type { Service, DocumentSymbol, SymbolKind } from '@volar/language-servic
import * as html from 'vscode-html-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import * as path from 'path';
import { URI, Utils } from 'vscode-uri';

const parserLs = html.getLanguageService();
const htmlDocuments = new WeakMap<TextDocument, [number, html.HTMLDocument]>();

export interface Provide {
'html/htmlDocument': (document: TextDocument) => html.HTMLDocument | undefined;
'html/languageService': () => html.LanguageService;
'html/documentContext': () => html.DocumentContext;
'html/updateCustomData': (extraData: html.IHTMLDataProvider[]) => void;
}

Expand Down Expand Up @@ -44,8 +46,31 @@ export default (options: {
let customData: html.IHTMLDataProvider[] = [];
let extraData: html.IHTMLDataProvider[] = [];

const fileSystemProvider: html.FileSystemProvider = {
stat: async uri => await context.env.fs?.stat(uri) ?? {
type: html.FileType.Unknown,
ctime: 0,
mtime: 0,
size: 0,
},
readDirectory: async (uri) => context.env.fs?.readDirectory(uri) ?? [],
};
const documentContext: html.DocumentContext = {
resolveReference(ref, base) {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const htmlLs = html.getLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});

Expand All @@ -62,6 +87,7 @@ export default (options: {
}
},
'html/languageService': () => htmlLs,
'html/documentContext': () => documentContext,
'html/updateCustomData': updateExtraCustomData,
},

Expand All @@ -72,12 +98,7 @@ export default (options: {

const configs = await context.env.getConfiguration?.<html.CompletionConfiguration>('html.completion');

if (context.env.documentContext) {
return htmlLs.doComplete2(document, position, htmlDocument, context.env.documentContext, configs);
}
else {
return htmlLs.doComplete(document, position, htmlDocument, configs);
}
return htmlLs.doComplete2(document, position, htmlDocument, documentContext, configs);
});
},

Expand Down Expand Up @@ -114,11 +135,7 @@ export default (options: {

provideDocumentLinks(document) {
return worker(document, () => {

if (!context.env.documentContext)
return;

return htmlLs.findDocumentLinks(document, context.env.documentContext);
return htmlLs.findDocumentLinks(document, documentContext);
});
},

Expand Down
3 changes: 2 additions & 1 deletion packages/json/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/json"
},
"dependencies": {
"vscode-json-languageservice": "^5.2.0"
"vscode-json-languageservice": "^5.2.0",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
21 changes: 20 additions & 1 deletion packages/json/src/index.ts
@@ -1,6 +1,7 @@
import type { Service, Diagnostic } from '@volar/language-service';
import * as json from 'vscode-json-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { URI, Utils } from 'vscode-uri';

export interface Provide {
'json/jsonDocument': (document: TextDocument) => json.JSONDocument | undefined;
Expand All @@ -16,7 +17,25 @@ export default (settings?: json.LanguageSettings): Service<Provide> => (context)
return { triggerCharacters } as any;
}
const jsonDocuments = new WeakMap<TextDocument, [number, json.JSONDocument]>();
const jsonLs = json.getLanguageService({ schemaRequestService: context.env.schemaRequestService });
const workspaceContext: json.WorkspaceContextService = {
resolveRelativePath: (ref: string, base: string) => {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const jsonLs = json.getLanguageService({
schemaRequestService: async (uri) => await context.env.fs?.readFile(uri) ?? '',
workspaceContext,
clientCapabilities: context.env.clientCapabilities,
});

if (settings) {
jsonLs.configure(settings);
Expand Down
6 changes: 2 additions & 4 deletions packages/pug/src/index.ts
Expand Up @@ -33,7 +33,7 @@ export default (): Service<Provide> => (context, modules): ReturnType<Service<Pr

provideCompletionItems(document, position, _) {
return worker(document, (pugDocument) => {
return pugLs.doComplete(pugDocument, position, context.env.documentContext, /** TODO: CompletionConfiguration */);
return pugLs.doComplete(pugDocument, position, htmlService.provide['html/documentContext'](), /** TODO: CompletionConfiguration */);
});
},

Expand Down Expand Up @@ -74,9 +74,7 @@ export default (): Service<Provide> => (context, modules): ReturnType<Service<Pr

provideDocumentLinks(document) {
return worker(document, (pugDocument) => {
if (context.env.documentContext) {
return pugLs.findDocumentLinks(pugDocument, context.env.documentContext);
}
return pugLs.findDocumentLinks(pugDocument, htmlService.provide['html/documentContext']());
});
},

Expand Down
23 changes: 7 additions & 16 deletions packages/tsconfig/src/index.ts
@@ -1,4 +1,4 @@
import type { DocumentLink, Service } from '@volar/language-service';
import type { DocumentLink, FileType, Service } from '@volar/language-service';
import * as jsonc from 'jsonc-parser';
import { minimatch } from 'minimatch';
import type { TextDocument } from 'vscode-languageserver-textdocument';
Expand Down Expand Up @@ -52,7 +52,7 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
},

async resolveDocumentLink(link) {

const data: OpenExtendsLinkCommandArgs = link.data;
if (data) {
const tsconfigPath = await getTsconfigPath(Utils.dirname(URI.parse(data.resourceUri)), data.extendsValue);
Expand Down Expand Up @@ -153,14 +153,9 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
const moduleBasePath = baseCandidate.split('/').slice(0, sepIndex).join('/');
while (true) {
const moduleAbsoluteUrl = Utils.joinPath(currentUri, 'node_modules', moduleBasePath);
let moduleStat: Awaited<ReturnType<NonNullable<typeof ctx.env.fileSystemProvider>['stat']>> | undefined;
try {
moduleStat = await ctx.env.fileSystemProvider?.stat(moduleAbsoluteUrl.toString());
} catch (err) {
// noop
}
const moduleStat = await ctx.env.fs?.stat(moduleAbsoluteUrl.toString());

if (moduleStat && moduleStat.type === 2 /* Directory */) {
if (moduleStat && moduleStat.type === 2 satisfies FileType.Directory) {
for (const uriCandidate of pathCandidates
.map((relativePath) => relativePath.split('/').slice(sepIndex).join('/'))
// skip empty paths within module
Expand Down Expand Up @@ -214,12 +209,8 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
}

async function exists(resource: URI): Promise<boolean> {
try {
const stat = await ctx.env.fileSystemProvider?.stat(resource.toString());
// stat.type is an enum flag
return !!(stat?.type === 1);
} catch {
return false;
}
const stat = await ctx.env.fs?.stat(resource.toString());
// stat.type is an enum flag
return stat?.type === 1 satisfies FileType.File;
}
};
4 changes: 2 additions & 2 deletions packages/typescript/package.json
Expand Up @@ -14,12 +14,12 @@
},
"devDependencies": {
"@types/semver": "^7.3.13",
"@volar/typescript": "1.6.9",
"vscode-languageserver-textdocument": "^1.0.8"
"@volar/typescript": "1.7.0"
},
"dependencies": {
"semver": "^7.3.8",
"typescript-auto-import-cache": "^0.3.0",
"vscode-languageserver-textdocument": "^1.0.8",
"vscode-nls": "^5.2.0",
"vscode-uri": "^3.0.7"
},
Expand Down
11 changes: 3 additions & 8 deletions packages/typescript/src/features/formatting.ts
Expand Up @@ -2,13 +2,11 @@ import type * as vscode from '@volar/language-service';
import { getFormatCodeSettings } from '../configs/getFormatCodeSettings';
import { safeCall } from '../shared';
import { SharedContext } from '../types';
import type { TextDocument } from 'vscode-languageserver-textdocument';

export function register(ctx: SharedContext) {
return {
onRange: async (uri: string, range: vscode.Range | undefined, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> => {

const document = ctx.getTextDocument(uri);
if (!document) return [];
onRange: async (document: TextDocument, range: vscode.Range | undefined, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> => {

const fileName = ctx.env.uriToFileName(document.uri);
const tsOptions = await getFormatCodeSettings(ctx, document, options);
Expand All @@ -35,10 +33,7 @@ export function register(ctx: SharedContext) {

return result;
},
onType: async (uri: string, options: vscode.FormattingOptions, position: vscode.Position, key: string): Promise<vscode.TextEdit[]> => {

const document = ctx.getTextDocument(uri);
if (!document) return [];
onType: async (document: TextDocument, options: vscode.FormattingOptions, position: vscode.Position, key: string): Promise<vscode.TextEdit[]> => {

const fileName = ctx.env.uriToFileName(document.uri);
const tsOptions = await getFormatCodeSettings(ctx, document, options);
Expand Down

0 comments on commit bf7df8f

Please sign in to comment.