Skip to content

joh/petite barnacle #54

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

Merged
merged 5 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
],
"preLaunchTask": "npm: watch",
"request": "launch",
"type": "pwa-extensionHost"
"type": "extensionHost"
}
]
}
23 changes: 12 additions & 11 deletions anycode/client/src/common/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languagecli
import { CommonLanguageClient } from 'vscode-languageclient';
import { SupportedLanguages } from './supportedLanguages';
import TelemetryReporter from '@vscode/extension-telemetry';
import type { InitOptions } from '../../../shared/common/initOptions';
import type { InitOptions, Language, LanguageInfo } from '../../../shared/common/initOptions';
import { CustomMessages } from '../../../shared/common/messages';

export interface LanguageClientFactory {
Expand Down Expand Up @@ -100,9 +100,9 @@ async function _startServer(factory: LanguageClientFactory, context: vscode.Exte
// Build a glob-patterns for languages which have features enabled, like workspace symbol search,
// and use this pattern for initial file discovery and file watching
const findAndSearchSuffixes: string[][] = [];
for (const [info, config] of supportedLanguages) {
for (const [lang, config] of supportedLanguages) {
if (config.workspaceSymbols || config.references || config.definitions) {
findAndSearchSuffixes.push(info.suffixes);
findAndSearchSuffixes.push(lang.info.suffixes);
}
}
const langPattern = `**/*.{${findAndSearchSuffixes.join(',')}}`;
Expand All @@ -112,7 +112,7 @@ async function _startServer(factory: LanguageClientFactory, context: vscode.Exte
const treeSitterWasmUri = vscode.Uri.joinPath(context.extensionUri, './server/node_modules/web-tree-sitter/tree-sitter.wasm');
const initializationOptions: InitOptions = {
treeSitterWasmUri: 'importScripts' in globalThis ? treeSitterWasmUri.toString() : treeSitterWasmUri.fsPath,
supportedLanguages: Array.from(supportedLanguages.entries()),
supportedLanguages: Array.from(supportedLanguages.entries(), tuple => [tuple[0].info, tuple[1]]),
databaseName
};

Expand Down Expand Up @@ -201,17 +201,18 @@ async function _startServer(factory: LanguageClientFactory, context: vscode.Exte
// incremental indexing: per language we wait for the first document to appear
// and only then we starting indexing all files matching the language. this is
// done with the "unleash" message
const suffixesByLangId = new Map<string, string[]>();
const suffixesByLangId = new Map<string, Language>();
for (const [lang] of supportedLanguages) {
suffixesByLangId.set(lang.languageId, lang.suffixes);
suffixesByLangId.set(lang.info.languageId, lang);
}
const handleTextDocument = (doc: vscode.TextDocument) => {
const suffixes = suffixesByLangId.get(doc.languageId);
if (!suffixes) {
const handleTextDocument = async (doc: vscode.TextDocument) => {
const lang = suffixesByLangId.get(doc.languageId);
if (!lang) {
return;
}
suffixesByLangId.delete(doc.languageId);
const initLang = client.sendRequest(CustomMessages.QueueUnleash, suffixes);
const langData = await lang.fetchLanguageData();
const initLang = client.sendRequest(CustomMessages.QueueUnleash, [lang.info, langData]);

const initCancel = new Promise<void>(resolve => disposables.push(new vscode.Disposable(resolve)));
vscode.window.withProgress({ location: vscode.ProgressLocation.Window, title: `Updating Index for '${doc.languageId}'...` }, () => Promise.race([initLang, initCancel]));
Expand Down Expand Up @@ -268,7 +269,7 @@ async function _startServer(factory: LanguageClientFactory, context: vscode.Exte
});


return new vscode.Disposable(() => disposables.forEach(d => d.dispose()));
return vscode.Disposable.from(...disposables);
}

function _getRemoteHubExtension() {
Expand Down
65 changes: 25 additions & 40 deletions anycode/client/src/common/supportedLanguages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { Queries, LanguageInfo, FeatureConfig } from '../../../shared/common/initOptions';
import { encodeBase64 } from '../../../shared/common/base64';
import { Queries, LanguageInfo, FeatureConfig, LanguageData, Language } from '../../../shared/common/initOptions';

type JSONQueryPaths = {
comments?: string;
Expand Down Expand Up @@ -47,7 +48,7 @@ export class SupportedLanguages {
private readonly _onDidChange = new vscode.EventEmitter<this>();
readonly onDidChange = this._onDidChange.event;

private _tuples?: Map<LanguageInfo, FeatureConfig>;
private _tuples?: Map<Language, FeatureConfig>;

private readonly _disposable: vscode.Disposable;

Expand All @@ -74,50 +75,49 @@ export class SupportedLanguages {
this._onDidChange.fire(this);
}

async getSupportedLanguages(): Promise<ReadonlyMap<LanguageInfo, FeatureConfig>> {
async getSupportedLanguages(): Promise<ReadonlyMap<Language, FeatureConfig>> {

if (!this._tuples) {

const languageInfos = await this._readLanguageInfos();

this._tuples = new Map();

for (const info of languageInfos.values()) {
const config = vscode.workspace.getConfiguration('anycode', { languageId: info.languageId });
for (const language of languageInfos.values()) {
const config = vscode.workspace.getConfiguration('anycode', { languageId: language.info.languageId });
const featureConfig: FeatureConfig = { ...config.get<FeatureConfig>(`language.features`) };
const empty = Object.keys(featureConfig).every(key => !(<Record<string, any>>featureConfig)[key]);
if (empty) {
this._log.appendLine(`[CONFIG] ignoring ${info.languageId} because configuration IS EMPTY`);
this._log.appendLine(`[CONFIG] ignoring ${language.info.languageId} because configuration IS EMPTY`);
continue;
}

if (info.suppressedBy) {
if (language.info.suppressedBy) {
const inspectConfig = config.inspect('language.features');
const explicitlyEnabled = inspectConfig?.globalLanguageValue || inspectConfig?.workspaceLanguageValue || inspectConfig?.workspaceFolderLanguageValue;
if (!explicitlyEnabled && info.suppressedBy.some(id => vscode.extensions.getExtension(id, true))) {
this._log.appendLine(`[CONFIG] ignoring ${info.languageId} because it is SUPPRESSED by any of [${info.suppressedBy.join(', ')}]`);
if (!explicitlyEnabled && language.info.suppressedBy.some(id => vscode.extensions.getExtension(id, true))) {
this._log.appendLine(`[CONFIG] ignoring ${language.info.languageId} because it is SUPPRESSED by any of [${language.info.suppressedBy.join(', ')}]`);
continue;
}
}

this._tuples.set(info, featureConfig);
this._tuples.set(language, featureConfig);
}
}

return this._tuples;
}

async getSupportedLanguagesAsSelector(): Promise<string[]> {
const infos = await this.getSupportedLanguages();
return Array.from(infos.keys()).map(info => info.languageId);
const languages = await this.getSupportedLanguages();
return Array.from(languages.keys()).map(language => language.info.languageId);
}

async _readLanguageInfos(): Promise<ReadonlyMap<string, LanguageInfo>> {
async _readLanguageInfos(): Promise<ReadonlyMap<string, Language>> {

type Contribution = { ['anycodeLanguages']: JSONAnycodeLanguage | JSONAnycodeLanguage[] };

const result = new Map<string, LanguageInfo>();
const isWebWorker = 'importScripts' in globalThis;
const result = new Map<string, Language>();

for (const extension of vscode.extensions.allAcrossExtensionHosts) {

Expand All @@ -138,39 +138,24 @@ export class SupportedLanguages {
continue;
}

if (extension.extensionUri.scheme === 'vscode-remote') {
console.warn(`UNSUPPORTED extension location from ${extension.id}`, extension.extensionUri.toString());
continue;
}

let queries: Queries;
try {
queries = await SupportedLanguages._readQueryPath(extension, lang.queryPaths);
} catch (err) {
console.warn(`INVALID anycode-language queryPaths from ${extension.id}`, err);
continue;
}

const grammarUri = vscode.Uri.joinPath(extension.extensionUri, lang.grammarPath);
try {
vscode.workspace.fs.stat(grammarUri);
} catch (err) {
console.warn(`INVALID anycode-language grammerPath from ${extension.id}`, err);
continue;
}

const info = new LanguageInfo(
extension.id,
lang.languageId,
isWebWorker ? grammarUri.toString() : grammarUri.fsPath,
lang.extensions,
queries,
lang.suppressedBy
lang.suppressedBy ?? [],
lang.queryPaths
);

const language = new Language(info, async () => {
const grammar = await vscode.workspace.fs.readFile(vscode.Uri.joinPath(extension.extensionUri, lang.grammarPath));
const queries = await SupportedLanguages._readQueryPath(extension, lang.queryPaths);
return new LanguageData(encodeBase64(grammar), queries);
});

if (result.has(info.languageId)) {
console.info(`extension ${extension.id} OVERWRITES language info for ${info.languageId}`);
}
result.set(info.languageId, info);
result.set(info.languageId, language);
}
}
return result;
Expand Down
Loading