Enable gts

This commit is contained in:
Shuhei Takahashi 2025-01-30 21:08:48 +09:00
parent 9f1859fb38
commit 7ac219ccf4
9 changed files with 2007 additions and 335 deletions

8
vscode-gn/.editorconfig Normal file
View file

@ -0,0 +1,8 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
insert_final_newline = true

1
vscode-gn/.eslintignore Normal file
View file

@ -0,0 +1 @@
dist

3
vscode-gn/.eslintrc.json Normal file
View file

@ -0,0 +1,3 @@
{
"extends": "./node_modules/gts/"
}

19
vscode-gn/.prettierrc.js Normal file
View file

@ -0,0 +1,19 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module.exports = {
...require('gts/.prettierrc.json')
};

View file

@ -1,44 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
export default [{
files: ["**/*.ts"],
}, {
plugins: {
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: "module",
},
rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],
curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}];

File diff suppressed because it is too large Load diff

View file

@ -87,8 +87,8 @@
"build-extension": "webpack",
"build-server": "cargo build --release && bash -c 'cp ../target/${CARGO_BUILD_TARGET:-.}/release/gn-language-server${APPDATA:+.exe} dist/'",
"package": "vsce package",
"lint": "eslint src",
"pretest": "npm run build && npm run lint",
"lint": "gts lint",
"fix": "gts fix",
"vscode:prepublish": "npm ci && npm run build"
},
"dependencies": {
@ -101,7 +101,8 @@
"@typescript-eslint/eslint-plugin": "^8.17.0",
"@typescript-eslint/parser": "^8.17.0",
"@vscode/vsce": "^3.2.1",
"eslint": "^9.16.0",
"eslint": "^8.57.1",
"gts": "^5.3.1",
"ts-loader": "^9.5.1",
"typescript": "^5.7.2",
"webpack": "^5.95.0",

View file

@ -16,125 +16,148 @@
import * as path from 'path';
import * as vscode from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node';
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
TransportKind,
} from 'vscode-languageclient/node';
const EXECUTABLE_SUFFIX: string = process.platform === 'win32' ? '.exe' : '';
function ancestors(uri: vscode.Uri): vscode.Uri[] {
const ancestors = [];
let current = uri;
while (current.path !== '/') {
ancestors.push(current);
current = current.with({path: path.dirname(current.path)});
}
return ancestors;
const ancestors = [];
let current = uri;
while (current.path !== '/') {
ancestors.push(current);
current = current.with({path: path.dirname(current.path)});
}
return ancestors;
}
async function statNoThrow(uri: vscode.Uri): Promise<vscode.FileStat | undefined> {
try {
return await vscode.workspace.fs.stat(uri);
} catch {
return undefined;
}
async function statNoThrow(
uri: vscode.Uri
): Promise<vscode.FileStat | undefined> {
try {
return await vscode.workspace.fs.stat(uri);
} catch {
return undefined;
}
}
async function isInGnWorkspace(uri: vscode.Uri): Promise<boolean> {
for (const dirUri of ancestors(uri).slice(1)) {
for (const name of ['.gn', 'BUILD.gn']) {
const candidateUri = dirUri.with({path: path.join(dirUri.path, name)});
if (await statNoThrow(candidateUri)) {
return true;
}
}
}
return false;
for (const dirUri of ancestors(uri).slice(1)) {
for (const name of ['.gn', 'BUILD.gn']) {
const candidateUri = dirUri.with({path: path.join(dirUri.path, name)});
if (await statNoThrow(candidateUri)) {
return true;
}
}
}
return false;
}
async function updateActiveEditorContext(): Promise<void> {
const uri = vscode.window.activeTextEditor?.document?.uri;
const inGnWorkspace = uri ? await isInGnWorkspace(uri) : false;
vscode.commands.executeCommand('setContext', 'gn.inGnWorkspace', inGnWorkspace);
const uri = vscode.window.activeTextEditor?.document?.uri;
const inGnWorkspace = uri ? await isInGnWorkspace(uri) : false;
vscode.commands.executeCommand(
'setContext',
'gn.inGnWorkspace',
inGnWorkspace
);
}
async function openBuildFile(): Promise<void> {
const startUri = vscode.window.activeTextEditor?.document?.uri;
if (!startUri) {
void vscode.window.showErrorMessage('No open editor.');
return;
}
const startUri = vscode.window.activeTextEditor?.document?.uri;
if (!startUri) {
void vscode.window.showErrorMessage('No open editor.');
return;
}
const isGnFile = startUri.path.endsWith('.gn') || startUri.path.endsWith('.gni');
const isGnFile =
startUri.path.endsWith('.gn') || startUri.path.endsWith('.gni');
if (isGnFile) {
const dotGnUri = startUri.with({path: path.join(path.dirname(startUri.path), '.gn')});
if (await statNoThrow(dotGnUri)) {
void vscode.window.showInformationMessage('This file is in the top-level directory.');
return;
}
}
if (isGnFile) {
const dotGnUri = startUri.with({
path: path.join(path.dirname(startUri.path), '.gn'),
});
if (await statNoThrow(dotGnUri)) {
void vscode.window.showInformationMessage(
'This file is in the top-level directory.'
);
return;
}
}
for (const dirUri of ancestors(startUri).slice(isGnFile ? 2 : 1)) {
const buildUri = dirUri.with({path: path.join(dirUri.path, 'BUILD.gn')});
if (await statNoThrow(buildUri)) {
vscode.window.showTextDocument(buildUri);
return;
}
if (await statNoThrow(dirUri.with({path: path.join(dirUri.path, '.gn')}))) {
break;
}
}
for (const dirUri of ancestors(startUri).slice(isGnFile ? 2 : 1)) {
const buildUri = dirUri.with({path: path.join(dirUri.path, 'BUILD.gn')});
if (await statNoThrow(buildUri)) {
vscode.window.showTextDocument(buildUri);
return;
}
if (await statNoThrow(dirUri.with({path: path.join(dirUri.path, '.gn')}))) {
break;
}
}
void vscode.window.showErrorMessage('BUILD.gn not found in the ancestor directories.');
void vscode.window.showErrorMessage(
'BUILD.gn not found in the ancestor directories.'
);
}
async function startLanguageServer(context: vscode.ExtensionContext, output: vscode.OutputChannel): Promise<void> {
const clientOptions: LanguageClientOptions = {
documentSelector: [
{'scheme': 'file', 'pattern': '**/*.gn'},
{'scheme': 'file', 'pattern': '**/*.gni'},
],
synchronize: {
fileEvents: [
vscode.workspace.createFileSystemWatcher('**/*.gn'),
vscode.workspace.createFileSystemWatcher('**/*.gni'),
],
},
outputChannel: output,
};
async function startLanguageServer(
context: vscode.ExtensionContext,
output: vscode.OutputChannel
): Promise<void> {
const clientOptions: LanguageClientOptions = {
documentSelector: [
{scheme: 'file', pattern: '**/*.gn'},
{scheme: 'file', pattern: '**/*.gni'},
],
synchronize: {
fileEvents: [
vscode.workspace.createFileSystemWatcher('**/*.gn'),
vscode.workspace.createFileSystemWatcher('**/*.gni'),
],
},
outputChannel: output,
};
const extensionDir = context.extensionPath;
const serverOptions: ServerOptions = {
transport: TransportKind.stdio,
command: path.join(extensionDir, 'dist/gn-language-server' + EXECUTABLE_SUFFIX),
options: {
cwd: extensionDir,
env: {
RUST_BACKTRACE: '1',
},
},
};
const extensionDir = context.extensionPath;
const serverOptions: ServerOptions = {
transport: TransportKind.stdio,
command: path.join(
extensionDir,
'dist/gn-language-server' + EXECUTABLE_SUFFIX
),
options: {
cwd: extensionDir,
env: {
RUST_BACKTRACE: '1',
},
},
};
const client = new LanguageClient(
'gn',
'GN',
serverOptions,
clientOptions
);
context.subscriptions.push(client);
const client = new LanguageClient('gn', 'GN', serverOptions, clientOptions);
context.subscriptions.push(client);
await client.start();
await client.start();
}
export async function activate(context: vscode.ExtensionContext): Promise<void> {
const output = vscode.window.createOutputChannel('GN');
context.subscriptions.push(output);
export async function activate(
context: vscode.ExtensionContext
): Promise<void> {
const output = vscode.window.createOutputChannel('GN');
context.subscriptions.push(output);
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(updateActiveEditorContext));
await updateActiveEditorContext();
context.subscriptions.push(
vscode.window.onDidChangeActiveTextEditor(updateActiveEditorContext)
);
await updateActiveEditorContext();
context.subscriptions.push(
vscode.commands.registerCommand('gn.openBuildFile', openBuildFile)
);
context.subscriptions.push(
vscode.commands.registerCommand('gn.openBuildFile', openBuildFile)
);
await startLanguageServer(context, output);
await startLanguageServer(context, output);
}

View file

@ -38,11 +38,11 @@ module.exports = {
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
loader: 'ts-loader',
},
],
},
],
},
devtool: 'nosources-source-map',
};