mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-24 09:21:35 +01:00
Merge branch 'main' into fix-path-prefix-in-shell-integrations
This commit is contained in:
+2
-1
@@ -755,7 +755,8 @@
|
||||
"vs/base/~",
|
||||
"vs/base/parts/*/~",
|
||||
"vs/platform/*/~",
|
||||
"vs/editor/~"
|
||||
"vs/editor/~",
|
||||
"@vscode/tree-sitter-wasm" // node module allowed even in /common/
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ vscode-textmate/webpack.config.js
|
||||
|
||||
# This makes sure the model is included in the package
|
||||
!@vscode/vscode-languagedetection/model/**
|
||||
!@vscode/tree-sitter-wasm/wasm/**
|
||||
|
||||
# Ensure only the required telemetry pieces are loaded in web to reduce bundle size
|
||||
@microsoft/1ds-core-js/**
|
||||
|
||||
@@ -180,6 +180,11 @@
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"disableAutomaticConfiguration": {
|
||||
"type": "boolean",
|
||||
"description": "Disables the setup that is automatically run in a codespace if no `postCreateCommand` is specified.",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ import { registerBaseCommands } from './commands/index';
|
||||
import { TypeScriptServiceConfiguration } from './configuration/configuration';
|
||||
import { BrowserServiceConfigurationProvider } from './configuration/configuration.browser';
|
||||
import { ExperimentationTelemetryReporter, IExperimentationTelemetryReporter } from './experimentTelemetryReporter';
|
||||
import { AutoInstallerFs } from './filesystems/autoInstallerFs';
|
||||
import { MemFs } from './filesystems/memFs';
|
||||
import { registerAtaSupport } from './filesystems/ata';
|
||||
import { createLazyClientHost, lazilyActivateClient } from './lazyClientHost';
|
||||
import { Logger } from './logging/logger';
|
||||
import RemoteRepositories from './remoteRepositories.browser';
|
||||
@@ -25,7 +24,7 @@ import { ITypeScriptVersionProvider, TypeScriptVersion, TypeScriptVersionSource
|
||||
import { ActiveJsTsEditorTracker } from './ui/activeJsTsEditorTracker';
|
||||
import { Disposable } from './utils/dispose';
|
||||
import { getPackageInfo } from './utils/packageInfo';
|
||||
import { isWebAndHasSharedArrayBuffers, supportsReadableByteStreams } from './utils/platform';
|
||||
import { isWebAndHasSharedArrayBuffers } from './utils/platform';
|
||||
|
||||
class StaticVersionProvider implements ITypeScriptVersionProvider {
|
||||
|
||||
@@ -102,16 +101,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
|
||||
await startPreloadWorkspaceContentsIfNeeded(context, logger);
|
||||
}));
|
||||
|
||||
if (supportsReadableByteStreams()) {
|
||||
context.subscriptions.push(vscode.workspace.registerFileSystemProvider('vscode-global-typings', new MemFs(), {
|
||||
isCaseSensitive: true,
|
||||
isReadonly: false
|
||||
}));
|
||||
context.subscriptions.push(vscode.workspace.registerFileSystemProvider('vscode-node-modules', new AutoInstallerFs(), {
|
||||
isCaseSensitive: true,
|
||||
isReadonly: false
|
||||
}));
|
||||
}
|
||||
context.subscriptions.push(registerAtaSupport());
|
||||
|
||||
return getExtensionApi(onCompletionAccepted.event, pluginManager);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { conditionalRegistration, requireGlobalConfiguration } from '../languageFeatures/util/dependentRegistration';
|
||||
import { supportsReadableByteStreams } from '../utils/platform';
|
||||
import { AutoInstallerFs } from './autoInstallerFs';
|
||||
import { MemFs } from './memFs';
|
||||
|
||||
export function registerAtaSupport(): vscode.Disposable {
|
||||
if (!supportsReadableByteStreams()) {
|
||||
return vscode.Disposable.from();
|
||||
}
|
||||
|
||||
return conditionalRegistration([
|
||||
requireGlobalConfiguration('typescript', 'tsserver.web.typeAcquisition.enabled'),
|
||||
], () => {
|
||||
return vscode.Disposable.from(
|
||||
vscode.workspace.registerFileSystemProvider('vscode-global-typings', new MemFs(), {
|
||||
isCaseSensitive: true,
|
||||
isReadonly: false
|
||||
}),
|
||||
vscode.workspace.registerFileSystemProvider('vscode-node-modules', new AutoInstallerFs(), {
|
||||
isCaseSensitive: true,
|
||||
isReadonly: false
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export class WorkerServerProcessFactory implements TsServerProcessFactory {
|
||||
version: TypeScriptVersion,
|
||||
args: readonly string[],
|
||||
kind: TsServerProcessKind,
|
||||
_configuration: TypeScriptServiceConfiguration,
|
||||
configuration: TypeScriptServiceConfiguration,
|
||||
_versionManager: TypeScriptVersionManager,
|
||||
_nodeVersionManager: NodeVersionManager,
|
||||
tsServerLog: TsServerLog | undefined,
|
||||
@@ -50,10 +50,10 @@ export class WorkerServerProcessFactory implements TsServerProcessFactory {
|
||||
...args,
|
||||
// Explicitly give TS Server its path so it can load local resources
|
||||
'--executingFilePath', tsServerPath,
|
||||
// Enable/disable web type acquisition
|
||||
(configuration.webTypeAcquisitionEnabled && supportsReadableByteStreams() ? '--experimentalTypeAcquisition' : '--disableAutomaticTypingAcquisition'),
|
||||
];
|
||||
if (_configuration.webTypeAcquisitionEnabled && supportsReadableByteStreams()) {
|
||||
launchArgs.push('--experimentalTypeAcquisition');
|
||||
}
|
||||
|
||||
return new WorkerServerProcess(kind, tsServerPath, this._extensionUri, launchArgs, tsServerLog, this._logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"@vscode/spdlog": "^0.15.0",
|
||||
"@vscode/sqlite3": "5.1.6-vscode",
|
||||
"@vscode/sudo-prompt": "9.3.1",
|
||||
"@vscode/tree-sitter-wasm": "^0.0.1",
|
||||
"@vscode/vscode-languagedetection": "1.0.21",
|
||||
"@vscode/windows-mutex": "^0.5.0",
|
||||
"@vscode/windows-process-tree": "^0.6.0",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"@vscode/proxy-agent": "^0.22.0",
|
||||
"@vscode/ripgrep": "^1.15.9",
|
||||
"@vscode/spdlog": "^0.15.0",
|
||||
"@vscode/tree-sitter-wasm": "^0.0.1",
|
||||
"@vscode/vscode-languagedetection": "1.0.21",
|
||||
"@vscode/windows-process-tree": "^0.6.0",
|
||||
"@vscode/windows-registry": "^1.1.0",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"@microsoft/1ds-core-js": "^3.2.13",
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@vscode/iconv-lite-umd": "0.7.0",
|
||||
"@vscode/tree-sitter-wasm": "^0.0.1",
|
||||
"@vscode/vscode-languagedetection": "1.0.21",
|
||||
"@xterm/addon-clipboard": "0.2.0-beta.34",
|
||||
"@xterm/addon-image": "0.9.0-beta.51",
|
||||
|
||||
@@ -43,6 +43,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48"
|
||||
integrity sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==
|
||||
|
||||
"@vscode/tree-sitter-wasm@^0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.0.1.tgz#ffb2e295a416698f4c77cbffeca3b28567d6754b"
|
||||
integrity sha512-m0GKnQ3BxWnVd+20KLGwr1+Qvt/RiiaJmKAqHNU35pNydDtduUzyBm7ETz/T0vOVKoeIAaiYsJOA1aKWs7Y1tA==
|
||||
|
||||
"@vscode/vscode-languagedetection@1.0.21":
|
||||
version "1.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3"
|
||||
|
||||
@@ -98,6 +98,11 @@
|
||||
mkdirp "^1.0.4"
|
||||
node-addon-api "7.1.0"
|
||||
|
||||
"@vscode/tree-sitter-wasm@^0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.0.1.tgz#ffb2e295a416698f4c77cbffeca3b28567d6754b"
|
||||
integrity sha512-m0GKnQ3BxWnVd+20KLGwr1+Qvt/RiiaJmKAqHNU35pNydDtduUzyBm7ETz/T0vOVKoeIAaiYsJOA1aKWs7Y1tA==
|
||||
|
||||
"@vscode/vscode-languagedetection@1.0.21":
|
||||
version "1.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3"
|
||||
|
||||
Vendored
+1
@@ -197,6 +197,7 @@ const isESM = false;
|
||||
// using a fallback such as node.js require which does not exist in sandbox
|
||||
const baseNodeModulesPath = isDev ? '../node_modules' : '../node_modules.asar';
|
||||
loaderConfig.paths = {
|
||||
'@vscode/tree-sitter-wasm': `${baseNodeModulesPath}/@vscode/tree-sitter-wasm/wasm/tree-sitter.js`,
|
||||
'vscode-textmate': `${baseNodeModulesPath}/vscode-textmate/release/main.js`,
|
||||
'vscode-oniguruma': `${baseNodeModulesPath}/vscode-oniguruma/release/main.js`,
|
||||
'vsda': `${baseNodeModulesPath}/vsda/index.js`,
|
||||
|
||||
@@ -190,6 +190,16 @@ export function validateConstraint(arg: unknown, constraint: TypeConstraint | un
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper type assertion that safely upcasts a type to a supertype.
|
||||
*
|
||||
* This can be used to make sure the argument correctly conforms to the subtype while still being able to pass it
|
||||
* to contexts that expects the supertype.
|
||||
*/
|
||||
export function upcast<Base, Sub extends Base>(x: Sub): Base {
|
||||
return x;
|
||||
}
|
||||
|
||||
type AddFirstParameterToFunction<T, TargetFunctionsReturnType, FirstParameter> = T extends (...args: any[]) => TargetFunctionsReturnType ?
|
||||
// Function: add param to function
|
||||
(firstArg: FirstParameter, ...args: Parameters<T>) => ReturnType<T> :
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TreeSitterTokenizationRegistry } from 'vs/editor/common/languages';
|
||||
import type { Parser } from '@vscode/tree-sitter-wasm';
|
||||
import { AppResourcePath, FileAccess, nodeModulesPath } from 'vs/base/common/network';
|
||||
import { ITreeSitterParserService } from 'vs/editor/common/services/treeSitterParserService';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { Disposable, DisposableMap, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IModelContentChangedEvent } from 'vs/editor/common/textModelEvents';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { setTimeout0 } from 'vs/base/common/platform';
|
||||
import { importAMDNodeModule } from 'vs/amdX';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { cancelOnDispose } from 'vs/base/common/cancellation';
|
||||
|
||||
const EDITOR_EXPERIMENTAL_PREFER_TREESITTER = 'editor.experimental.preferTreeSitter';
|
||||
const moduleLocationTreeSitter: AppResourcePath = `${nodeModulesPath}/@vscode/tree-sitter-wasm/wasm`;
|
||||
const moduleLocationTreeSitterWasm: AppResourcePath = `${moduleLocationTreeSitter}/tree-sitter.wasm`;
|
||||
|
||||
export class TextModelTreeSitter extends Disposable {
|
||||
private _treeSitterTree: TreeSitterTree | undefined;
|
||||
|
||||
// Not currently used since we just get telemetry, but later this will be needed.
|
||||
get tree() { return this._treeSitterTree; }
|
||||
|
||||
constructor(readonly model: ITextModel,
|
||||
private readonly _treeSitterParser: TreeSitterLanguages,
|
||||
private readonly _treeSitterImporter: TreeSitterImporter,
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _telemetryService: ITelemetryService
|
||||
) {
|
||||
super();
|
||||
this._register(Event.runAndSubscribe(this.model.onDidChangeLanguage, (e => this._onDidChangeLanguage(e ? e.newLanguage : this.model.getLanguageId()))));
|
||||
}
|
||||
|
||||
private readonly _languageSessionDisposables = this._register(new DisposableStore());
|
||||
/**
|
||||
* Be very careful when making changes to this method as it is easy to introduce race conditions.
|
||||
*/
|
||||
private async _onDidChangeLanguage(languageId: string) {
|
||||
this._languageSessionDisposables.clear();
|
||||
this._treeSitterTree = undefined;
|
||||
|
||||
const token = cancelOnDispose(this._languageSessionDisposables);
|
||||
const language = await this._treeSitterParser.getLanguage(languageId);
|
||||
if (!language || token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Parser = await this._treeSitterImporter.getParserClass();
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
const treeSitterTree = this._languageSessionDisposables.add(new TreeSitterTree(new Parser(), language, this._logService, this._telemetryService));
|
||||
this._languageSessionDisposables.add(this.model.onDidChangeContent(e => this._onDidChangeContent(treeSitterTree, e)));
|
||||
await this._onDidChangeContent(treeSitterTree);
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._treeSitterTree = treeSitterTree;
|
||||
}
|
||||
|
||||
private async _onDidChangeContent(treeSitterTree: TreeSitterTree, e?: IModelContentChangedEvent) {
|
||||
return treeSitterTree.onDidChangeContent(this.model, e);
|
||||
}
|
||||
}
|
||||
|
||||
export class TreeSitterTree implements IDisposable {
|
||||
private _tree: Parser.Tree | undefined;
|
||||
private _isDisposed: boolean = false;
|
||||
constructor(public readonly parser: Parser,
|
||||
public /** exposed for tests **/ readonly language: Parser.Language,
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _telemetryService: ITelemetryService) {
|
||||
this.parser.setTimeoutMicros(50 * 1000); // 50 ms
|
||||
this.parser.setLanguage(language);
|
||||
}
|
||||
dispose(): void {
|
||||
this._isDisposed = true;
|
||||
this._tree?.delete();
|
||||
this.parser?.delete();
|
||||
}
|
||||
get tree() { return this._tree; }
|
||||
set tree(newTree: Parser.Tree | undefined) {
|
||||
this._tree?.delete();
|
||||
this._tree = newTree;
|
||||
}
|
||||
get isDisposed() { return this._isDisposed; }
|
||||
|
||||
private _onDidChangeContentQueue: Promise<void> = Promise.resolve();
|
||||
public async onDidChangeContent(model: ITextModel, e?: IModelContentChangedEvent) {
|
||||
this._onDidChangeContentQueue = this._onDidChangeContentQueue.then(() => {
|
||||
if (this.isDisposed) {
|
||||
// No need to continue the queue if we are disposed
|
||||
return;
|
||||
}
|
||||
return this._onDidChangeContent(model, e);
|
||||
}).catch((e) => {
|
||||
this._logService.error('Error parsing tree-sitter tree', e);
|
||||
});
|
||||
return this._onDidChangeContentQueue;
|
||||
}
|
||||
|
||||
private async _onDidChangeContent(model: ITextModel, e?: IModelContentChangedEvent) {
|
||||
if (e) {
|
||||
for (const change of e.changes) {
|
||||
const newEndOffset = change.rangeOffset + change.text.length;
|
||||
const newEndPosition = model.getPositionAt(newEndOffset);
|
||||
|
||||
this.tree?.edit({
|
||||
startIndex: change.rangeOffset,
|
||||
oldEndIndex: change.rangeOffset + change.rangeLength,
|
||||
newEndIndex: change.rangeOffset + change.text.length,
|
||||
startPosition: { row: change.range.startLineNumber - 1, column: change.range.startColumn - 1 },
|
||||
oldEndPosition: { row: change.range.endLineNumber - 1, column: change.range.endColumn - 1 },
|
||||
newEndPosition: { row: newEndPosition.lineNumber - 1, column: newEndPosition.column - 1 }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.tree = await this.parse(model);
|
||||
}
|
||||
|
||||
private parse(model: ITextModel): Promise<Parser.Tree | undefined> {
|
||||
let telemetryTag: string;
|
||||
if (this.tree) {
|
||||
telemetryTag = 'incrementalParse';
|
||||
} else {
|
||||
telemetryTag = 'fullParse';
|
||||
}
|
||||
return this._parseAndYield(model, telemetryTag);
|
||||
}
|
||||
|
||||
private async _parseAndYield(model: ITextModel, telemetryTag: string): Promise<Parser.Tree | undefined> {
|
||||
const language = model.getLanguageId();
|
||||
let tree: Parser.Tree | undefined;
|
||||
let time: number = 0;
|
||||
let passes: number = 0;
|
||||
do {
|
||||
const timer = performance.now();
|
||||
try {
|
||||
tree = this.parser.parse((index: number, position?: Parser.Point) => this._parseCallback(model, index), this.tree);
|
||||
} catch (e) {
|
||||
// parsing can fail when the timeout is reached, will resume upon next loop
|
||||
} finally {
|
||||
time += performance.now() - timer;
|
||||
passes++;
|
||||
}
|
||||
|
||||
// Even if the model changes and edits are applied, the tree parsing will continue correctly after the await.
|
||||
await new Promise<void>(resolve => setTimeout0(resolve));
|
||||
|
||||
if (model.isDisposed() || this.isDisposed) {
|
||||
return;
|
||||
}
|
||||
} while (!tree);
|
||||
this.sendParseTimeTelemetry(telemetryTag, language, time, passes);
|
||||
return tree;
|
||||
}
|
||||
|
||||
private _parseCallback(textModel: ITextModel, index: number): string | null {
|
||||
return textModel.getTextBuffer().getNearestChunk(index);
|
||||
}
|
||||
|
||||
private sendParseTimeTelemetry(eventName: string, languageId: string, time: number, passes: number): void {
|
||||
this._logService.debug(`Tree parsing (${eventName}) took ${time} ms and ${passes} passes.`);
|
||||
type ParseTimeClassification = {
|
||||
owner: 'alros';
|
||||
comment: 'Used to understand how long it takes to parse a tree-sitter tree';
|
||||
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The programming language ID.' };
|
||||
time: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ms it took to parse' };
|
||||
passes: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of passes it took to parse' };
|
||||
};
|
||||
this._telemetryService.publicLog2<{ languageId: string; time: number; passes: number }, ParseTimeClassification>(`treeSitter.${eventName}`, { languageId, time, passes });
|
||||
}
|
||||
}
|
||||
|
||||
export class TreeSitterLanguages extends Disposable {
|
||||
private _languages: Map<string, Parser.Language> = new Map();
|
||||
|
||||
constructor(private readonly _treeSitterImporter: TreeSitterImporter,
|
||||
private readonly _fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public async getLanguage(languageId: string): Promise<Parser.Language | undefined> {
|
||||
let language = this._languages.get(languageId);
|
||||
if (!language) {
|
||||
language = await this._fetchLanguage(languageId);
|
||||
if (!language) {
|
||||
return undefined;
|
||||
}
|
||||
this._languages.set(languageId, language);
|
||||
}
|
||||
return language;
|
||||
}
|
||||
|
||||
private async _fetchLanguage(languageId: string): Promise<Parser.Language | undefined> {
|
||||
const grammarName = TreeSitterTokenizationRegistry.get(languageId);
|
||||
const languageLocation = this._getLanguageLocation(languageId);
|
||||
if (!grammarName || !languageLocation) {
|
||||
return undefined;
|
||||
}
|
||||
const wasmPath: AppResourcePath = `${languageLocation}/${grammarName.name}.wasm`;
|
||||
const languageFile = await (this._fileService.readFile(FileAccess.asFileUri(wasmPath)));
|
||||
const Parser = await this._treeSitterImporter.getParserClass();
|
||||
return Parser.Language.load(languageFile.value.buffer);
|
||||
}
|
||||
|
||||
private _getLanguageLocation(languageId: string): AppResourcePath | undefined {
|
||||
const grammarName = TreeSitterTokenizationRegistry.get(languageId);
|
||||
if (!grammarName) {
|
||||
return undefined;
|
||||
}
|
||||
return moduleLocationTreeSitter;
|
||||
}
|
||||
}
|
||||
|
||||
export class TreeSitterImporter {
|
||||
private _treeSitterImport: typeof import('@vscode/tree-sitter-wasm') | undefined;
|
||||
private async _getTreeSitterImport() {
|
||||
if (!this._treeSitterImport) {
|
||||
this._treeSitterImport = await importAMDNodeModule<typeof import('@vscode/tree-sitter-wasm')>('@vscode/tree-sitter-wasm', 'wasm/tree-sitter.js');
|
||||
}
|
||||
return this._treeSitterImport;
|
||||
}
|
||||
|
||||
private _parserClass: typeof Parser | undefined;
|
||||
public async getParserClass() {
|
||||
if (!this._parserClass) {
|
||||
this._parserClass = (await this._getTreeSitterImport()).Parser;
|
||||
}
|
||||
return this._parserClass;
|
||||
}
|
||||
}
|
||||
|
||||
export class TreeSitterTextModelService extends Disposable implements ITreeSitterParserService {
|
||||
readonly _serviceBrand: undefined;
|
||||
private _init!: Promise<boolean>;
|
||||
private _textModelTreeSitters: DisposableMap<ITextModel, TextModelTreeSitter> = this._register(new DisposableMap());
|
||||
private _registeredLanguages: DisposableMap<string, IDisposable> = this._register(new DisposableMap());
|
||||
private readonly _treeSitterImporter: TreeSitterImporter = new TreeSitterImporter();
|
||||
private readonly _treeSitterParser: TreeSitterLanguages;
|
||||
|
||||
constructor(@IModelService private readonly _modelService: IModelService,
|
||||
@IFileService fileService: IFileService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this._treeSitterParser = this._register(new TreeSitterLanguages(this._treeSitterImporter, fileService));
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(EDITOR_EXPERIMENTAL_PREFER_TREESITTER)) {
|
||||
this._supportedLanguagesChanged();
|
||||
}
|
||||
}));
|
||||
this._supportedLanguagesChanged();
|
||||
}
|
||||
|
||||
private async _doInitParser() {
|
||||
const Parser = await this._treeSitterImporter.getParserClass();
|
||||
await Parser.init({
|
||||
locateFile(_file: string, _folder: string) {
|
||||
return FileAccess.asBrowserUri(moduleLocationTreeSitterWasm).toString(true);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private _hasInit: boolean = false;
|
||||
private async _initParser(hasLanguages: boolean): Promise<boolean> {
|
||||
if (this._hasInit) {
|
||||
return this._init;
|
||||
}
|
||||
|
||||
if (hasLanguages) {
|
||||
this._hasInit = true;
|
||||
this._init = this._doInitParser();
|
||||
|
||||
// New init, we need to deal with all the existing text models and set up listeners
|
||||
this._init.then(() => this._registerModelServiceListeners());
|
||||
} else {
|
||||
this._init = Promise.resolve(false);
|
||||
}
|
||||
return this._init;
|
||||
}
|
||||
|
||||
private async _supportedLanguagesChanged() {
|
||||
const setting = this._getSetting();
|
||||
|
||||
let hasLanguages = true;
|
||||
if (setting.length === 0) {
|
||||
hasLanguages = false;
|
||||
}
|
||||
|
||||
if (await this._initParser(hasLanguages)) {
|
||||
// Eventually, this should actually use an extension point to add tree sitter grammars, but for now they are hard coded in core
|
||||
if (setting.includes('typescript')) {
|
||||
this._addGrammar('typescript', 'tree-sitter-typescript');
|
||||
} else {
|
||||
this._removeGrammar('typescript');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _getSetting(): string[] {
|
||||
return this._configurationService.getValue<string[]>(EDITOR_EXPERIMENTAL_PREFER_TREESITTER) || [];
|
||||
}
|
||||
|
||||
private async _registerModelServiceListeners() {
|
||||
this._register(this._modelService.onModelAdded(model => {
|
||||
this._createTextModelTreeSitter(model);
|
||||
}));
|
||||
this._register(this._modelService.onModelRemoved(model => {
|
||||
this._textModelTreeSitters.deleteAndDispose(model);
|
||||
}));
|
||||
this._modelService.getModels().forEach(model => this._createTextModelTreeSitter(model));
|
||||
}
|
||||
|
||||
private _createTextModelTreeSitter(model: ITextModel) {
|
||||
const textModelTreeSitter = new TextModelTreeSitter(model, this._treeSitterParser, this._treeSitterImporter, this._logService, this._telemetryService);
|
||||
this._textModelTreeSitters.set(model, textModelTreeSitter);
|
||||
}
|
||||
|
||||
private _addGrammar(languageId: string, grammarName: string) {
|
||||
if (!TreeSitterTokenizationRegistry.get(languageId)) {
|
||||
this._registeredLanguages.set(languageId, TreeSitterTokenizationRegistry.register(languageId, { name: grammarName }));
|
||||
}
|
||||
}
|
||||
|
||||
private _removeGrammar(languageId: string) {
|
||||
if (this._registeredLanguages.has(languageId)) {
|
||||
this._registeredLanguages.deleteAndDispose('typescript');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,14 @@ export class EncodedTokenizationResult {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An intermediate interface for scaffolding the new tree sitter tokenization support. Not final.
|
||||
* @internal
|
||||
*/
|
||||
export interface ITreeSitterTokenizationSupport {
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -2106,14 +2114,14 @@ export interface ITokenizationSupportChangedEvent {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ILazyTokenizationSupport {
|
||||
get tokenizationSupport(): Promise<ITokenizationSupport | null>;
|
||||
export interface ILazyTokenizationSupport<TSupport> {
|
||||
get tokenizationSupport(): Promise<TSupport | null>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class LazyTokenizationSupport implements IDisposable, ILazyTokenizationSupport {
|
||||
export class LazyTokenizationSupport implements IDisposable, ILazyTokenizationSupport<ITokenizationSupport> {
|
||||
private _tokenizationSupport: Promise<ITokenizationSupport & IDisposable | null> | null = null;
|
||||
|
||||
constructor(private readonly createSupport: () => Promise<ITokenizationSupport & IDisposable | null>) {
|
||||
@@ -2140,7 +2148,7 @@ export class LazyTokenizationSupport implements IDisposable, ILazyTokenizationSu
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ITokenizationRegistry {
|
||||
export interface ITokenizationRegistry<TSupport> {
|
||||
|
||||
/**
|
||||
* An event triggered when:
|
||||
@@ -2158,24 +2166,24 @@ export interface ITokenizationRegistry {
|
||||
/**
|
||||
* Register a tokenization support.
|
||||
*/
|
||||
register(languageId: string, support: ITokenizationSupport): IDisposable;
|
||||
register(languageId: string, support: TSupport): IDisposable;
|
||||
|
||||
/**
|
||||
* Register a tokenization support factory.
|
||||
*/
|
||||
registerFactory(languageId: string, factory: ILazyTokenizationSupport): IDisposable;
|
||||
registerFactory(languageId: string, factory: ILazyTokenizationSupport<TSupport>): IDisposable;
|
||||
|
||||
/**
|
||||
* Get or create the tokenization support for a language.
|
||||
* Returns `null` if not found.
|
||||
*/
|
||||
getOrCreate(languageId: string): Promise<ITokenizationSupport | null>;
|
||||
getOrCreate(languageId: string): Promise<TSupport | null>;
|
||||
|
||||
/**
|
||||
* Get the tokenization support for a language.
|
||||
* Returns `null` if not found.
|
||||
*/
|
||||
get(languageId: string): ITokenizationSupport | null;
|
||||
get(languageId: string): TSupport | null;
|
||||
|
||||
/**
|
||||
* Returns false if a factory is still pending.
|
||||
@@ -2195,8 +2203,12 @@ export interface ITokenizationRegistry {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const TokenizationRegistry: ITokenizationRegistry = new TokenizationRegistryImpl();
|
||||
export const TokenizationRegistry: ITokenizationRegistry<ITokenizationSupport> = new TokenizationRegistryImpl();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const TreeSitterTokenizationRegistry: ITokenizationRegistry<ITreeSitterTokenizationSupport> = new TokenizationRegistryImpl();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
||||
@@ -43,6 +43,7 @@ import { IBracketPairsTextModelPart } from 'vs/editor/common/textModelBracketPai
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelOptionsChangedEvent, InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawChange, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/textModelEvents';
|
||||
import { IGuidesTextModelPart } from 'vs/editor/common/textModelGuides';
|
||||
import { ITokenizationTextModelPart } from 'vs/editor/common/tokenizationTextModelPart';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||
import { IUndoRedoService, ResourceEditStackSnapshot, UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
|
||||
@@ -299,6 +300,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -327,13 +329,11 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
|
||||
this._bracketPairs = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));
|
||||
this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));
|
||||
this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));
|
||||
this._tokenizationTextModelPart = new TokenizationTextModelPart(
|
||||
this._languageService,
|
||||
this._languageConfigurationService,
|
||||
this._tokenizationTextModelPart = this.instantiationService.createInstance(TokenizationTextModelPart,
|
||||
this,
|
||||
this._bracketPairs,
|
||||
languageId,
|
||||
this._attachedViews,
|
||||
this._attachedViews
|
||||
);
|
||||
|
||||
const bufferLineCount = this._buffer.getLineCount();
|
||||
|
||||
@@ -47,12 +47,12 @@ export class TokenizationTextModelPart extends TextModelPart implements ITokeniz
|
||||
private readonly grammarTokens = this._register(new GrammarTokens(this._languageService.languageIdCodec, this._textModel, () => this._languageId, this._attachedViews));
|
||||
|
||||
constructor(
|
||||
private readonly _languageService: ILanguageService,
|
||||
private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
private readonly _textModel: TextModel,
|
||||
private readonly _bracketPairsTextModelPart: BracketPairsTextModelPart,
|
||||
private _languageId: string,
|
||||
private readonly _attachedViews: AttachedViews,
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
|
||||
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';
|
||||
import { IModelLanguageChangedEvent } from 'vs/editor/common/textModelEvents';
|
||||
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
|
||||
import { ILanguageSelection, ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { ILanguageSelection } from 'vs/editor/common/languages/language';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration';
|
||||
import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -23,7 +23,7 @@ import { StringSHA1 } from 'vs/base/common/hash';
|
||||
import { isEditStackElement } from 'vs/editor/common/model/editStack';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
function MODEL_ID(resource: URI): string {
|
||||
return resource.toString();
|
||||
@@ -107,8 +107,7 @@ export class ModelService extends Disposable implements IModelService {
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService private readonly _resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
|
||||
@@ -314,14 +313,11 @@ export class ModelService extends Disposable implements IModelService {
|
||||
private _createModelData(value: string | ITextBufferFactory, languageIdOrSelection: string | ILanguageSelection, resource: URI | undefined, isForSimpleWidget: boolean): ModelData {
|
||||
// create & save the model
|
||||
const options = this.getCreationOptions(languageIdOrSelection, resource, isForSimpleWidget);
|
||||
const model: TextModel = new TextModel(
|
||||
const model: TextModel = this._instantiationService.createInstance(TextModel,
|
||||
value,
|
||||
languageIdOrSelection,
|
||||
options,
|
||||
resource,
|
||||
this._undoRedoService,
|
||||
this._languageService,
|
||||
this._languageConfigurationService,
|
||||
resource
|
||||
);
|
||||
if (resource && this._disposedModels.has(MODEL_ID(resource))) {
|
||||
const disposedModelData = this._removeDisposedModel(resource)!;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const ITreeSitterParserService = createDecorator<ITreeSitterParserService>('treeSitterParserService');
|
||||
|
||||
/**
|
||||
* Currently this service just logs telemetry about how long it takes to parse files.
|
||||
* Actual API will come later as we add features like syntax highlighting.
|
||||
*/
|
||||
export interface ITreeSitterParserService {
|
||||
readonly _serviceBrand: undefined;
|
||||
}
|
||||
@@ -55,6 +55,9 @@ export interface IModelContentChange {
|
||||
* An event describing a change in the text of a model.
|
||||
*/
|
||||
export interface IModelContentChangedEvent {
|
||||
/**
|
||||
* The changes are ordered from the end of the document to the beginning, so they should be safe to apply in sequence.
|
||||
*/
|
||||
readonly changes: IModelContentChange[];
|
||||
/**
|
||||
* The (new) end-of-line character.
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent, ILazyTokenizationSupport } from 'vs/editor/common/languages';
|
||||
import { ITokenizationRegistry, ITokenizationSupportChangedEvent, ILazyTokenizationSupport } from 'vs/editor/common/languages';
|
||||
import { ColorId } from 'vs/editor/common/encodedTokenAttributes';
|
||||
|
||||
export class TokenizationRegistry implements ITokenizationRegistry {
|
||||
export class TokenizationRegistry<TSupport> implements ITokenizationRegistry<TSupport> {
|
||||
|
||||
private readonly _tokenizationSupports = new Map<string, ITokenizationSupport>();
|
||||
private readonly _factories = new Map<string, TokenizationSupportFactoryData>();
|
||||
private readonly _tokenizationSupports = new Map<string, TSupport>();
|
||||
private readonly _factories = new Map<string, TokenizationSupportFactoryData<TSupport>>();
|
||||
|
||||
private readonly _onDidChange = new Emitter<ITokenizationSupportChangedEvent>();
|
||||
public readonly onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event;
|
||||
@@ -30,7 +30,7 @@ export class TokenizationRegistry implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public register(languageId: string, support: ITokenizationSupport): IDisposable {
|
||||
public register(languageId: string, support: TSupport): IDisposable {
|
||||
this._tokenizationSupports.set(languageId, support);
|
||||
this.handleChange([languageId]);
|
||||
return toDisposable(() => {
|
||||
@@ -42,11 +42,11 @@ export class TokenizationRegistry implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public get(languageId: string): ITokenizationSupport | null {
|
||||
public get(languageId: string): TSupport | null {
|
||||
return this._tokenizationSupports.get(languageId) || null;
|
||||
}
|
||||
|
||||
public registerFactory(languageId: string, factory: ILazyTokenizationSupport): IDisposable {
|
||||
public registerFactory(languageId: string, factory: ILazyTokenizationSupport<TSupport>): IDisposable {
|
||||
this._factories.get(languageId)?.dispose();
|
||||
const myData = new TokenizationSupportFactoryData(this, languageId, factory);
|
||||
this._factories.set(languageId, myData);
|
||||
@@ -60,7 +60,7 @@ export class TokenizationRegistry implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public async getOrCreate(languageId: string): Promise<ITokenizationSupport | null> {
|
||||
public async getOrCreate(languageId: string): Promise<TSupport | null> {
|
||||
// check first if the support is already set
|
||||
const tokenizationSupport = this.get(languageId);
|
||||
if (tokenizationSupport) {
|
||||
@@ -112,7 +112,7 @@ export class TokenizationRegistry implements ITokenizationRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
class TokenizationSupportFactoryData extends Disposable {
|
||||
class TokenizationSupportFactoryData<TSupport> extends Disposable {
|
||||
|
||||
private _isDisposed: boolean = false;
|
||||
private _resolvePromise: Promise<void> | null = null;
|
||||
@@ -123,9 +123,9 @@ class TokenizationSupportFactoryData extends Disposable {
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly _registry: TokenizationRegistry,
|
||||
private readonly _registry: TokenizationRegistry<TSupport>,
|
||||
private readonly _languageId: string,
|
||||
private readonly _factory: ILazyTokenizationSupport,
|
||||
private readonly _factory: ILazyTokenizationSupport<TSupport>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@ import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import { ModelDecorationOptions, TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { Location } from 'vs/editor/common/languages';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { AccessibilityProvider, DataSource, Delegate, FileReferencesRenderer, IdentityProvider, OneReferenceRenderer, StringRepresentationProvider, TreeElement } from 'vs/editor/contrib/gotoSymbol/browser/peek/referencesTree';
|
||||
import * as peekView from 'vs/editor/contrib/peekView/browser/peekView';
|
||||
@@ -35,7 +33,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IWorkbenchAsyncDataTreeOptions, WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { FileReferences, OneReference, ReferencesModel } from '../referencesModel';
|
||||
|
||||
class DecorationsManager implements IDisposable {
|
||||
@@ -224,10 +221,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@peekView.IPeekViewService private readonly _peekViewService: peekView.IPeekViewService,
|
||||
@ILabelService private readonly _uriLabel: ILabelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
) {
|
||||
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true, supportOnTitleClick: true }, _instantiationService);
|
||||
|
||||
@@ -315,7 +309,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
||||
};
|
||||
this._preview = this._instantiationService.createInstance(EmbeddedCodeEditorWidget, this._previewContainer, options, {}, this.editor);
|
||||
dom.hide(this._previewContainer);
|
||||
this._previewNotAvailableMessage = new TextModel(nls.localize('missingPreviewMessage', "no preview available"), PLAINTEXT_LANGUAGE_ID, TextModel.DEFAULT_CREATION_OPTIONS, null, this._undoRedoService, this._languageService, this._languageConfigurationService);
|
||||
this._previewNotAvailableMessage = this._instantiationService.createInstance(TextModel, nls.localize('missingPreviewMessage', "no preview available"), PLAINTEXT_LANGUAGE_ID, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
|
||||
// tree
|
||||
this._treeContainer = dom.append(containerElement, dom.$('div.ref-tree.inline'));
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/uti
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/languages';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce';
|
||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||
@@ -29,6 +30,7 @@ import { TestTextResourcePropertiesService } from 'vs/editor/test/common/service
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { ColorScheme } from 'vs/platform/theme/common/theme';
|
||||
@@ -50,12 +52,14 @@ suite('ModelSemanticColoring', () => {
|
||||
languageFeaturesService = new LanguageFeaturesService();
|
||||
languageService = disposables.add(new LanguageService(false));
|
||||
const semanticTokensStylingService = disposables.add(new SemanticTokensStylingService(themeService, logService, languageService));
|
||||
const instantiationService = new TestInstantiationService();
|
||||
instantiationService.set(ILanguageService, languageService);
|
||||
instantiationService.set(ILanguageConfigurationService, new TestLanguageConfigurationService());
|
||||
modelService = disposables.add(new ModelService(
|
||||
configService,
|
||||
new TestTextResourcePropertiesService(configService),
|
||||
new UndoRedoService(new TestDialogService(), new TestNotificationService()),
|
||||
languageService,
|
||||
new TestLanguageConfigurationService(),
|
||||
instantiationService
|
||||
));
|
||||
const envService = new class extends mock<IEnvironmentService>() {
|
||||
override isBuilt: boolean = true;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AppResourcePath } from 'vs/base/common/network';
|
||||
import type { Parser } from '@vscode/tree-sitter-wasm';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { ITreeSitterParserService } from 'vs/editor/common/services/treeSitterParserService';
|
||||
|
||||
export class TestTreeSitterParserService implements ITreeSitterParserService {
|
||||
getLanguage(model: ITextModel): Parser.Language | undefined {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getLanguageLocation(languageId: string): AppResourcePath {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
public initTreeSitter(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public getTree(_model: ITextModel): Parser.Tree | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import assert from 'assert';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
import { TextModelTreeSitter, TreeSitterImporter, TreeSitterLanguages } from 'vs/editor/browser/services/treeSitter/treeSitterParserService';
|
||||
import type { Parser } from '@vscode/tree-sitter-wasm';
|
||||
import { createTextModel } from 'vs/editor/test/common/testTextModel';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ConsoleMainLogger, ILogService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
|
||||
class MockParser implements Parser {
|
||||
static async init(): Promise<void> { }
|
||||
delete(): void { }
|
||||
parse(input: string | Parser.Input, oldTree?: Parser.Tree, options?: Parser.Options): Parser.Tree {
|
||||
return new MockTree();
|
||||
}
|
||||
getIncludedRanges(): Parser.Range[] {
|
||||
return [];
|
||||
}
|
||||
getTimeoutMicros(): number { return 0; }
|
||||
setTimeoutMicros(timeout: number): void { }
|
||||
reset(): void { }
|
||||
getLanguage(): Parser.Language { return {} as any; }
|
||||
setLanguage(): void { }
|
||||
getLogger(): Parser.Logger {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setLogger(logFunc?: Parser.Logger | false | null): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
class MockTreeSitterImporter extends TreeSitterImporter {
|
||||
public override async getParserClass(): Promise<typeof Parser> {
|
||||
return MockParser as any;
|
||||
}
|
||||
}
|
||||
|
||||
class MockTree implements Parser.Tree {
|
||||
editorLanguage: string = '';
|
||||
editorContents: string = '';
|
||||
rootNode: Parser.SyntaxNode = {} as any;
|
||||
rootNodeWithOffset(offsetBytes: number, offsetExtent: Parser.Point): Parser.SyntaxNode {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
copy(): Parser.Tree {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
delete(): void { }
|
||||
edit(edit: Parser.Edit): Parser.Tree {
|
||||
return this;
|
||||
}
|
||||
walk(): Parser.TreeCursor {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getChangedRanges(other: Parser.Tree): Parser.Range[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getIncludedRanges(): Parser.Range[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getEditedRange(other: Parser.Tree): Parser.Range {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getLanguage(): Parser.Language {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
class MockLanguage implements Parser.Language {
|
||||
version: number = 0;
|
||||
fieldCount: number = 0;
|
||||
stateCount: number = 0;
|
||||
nodeTypeCount: number = 0;
|
||||
fieldNameForId(fieldId: number): string | null {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
fieldIdForName(fieldName: string): number | null {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
idForNodeType(type: string, named: boolean): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
nodeTypeForId(typeId: number): string | null {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
nodeTypeIsNamed(typeId: number): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
nodeTypeIsVisible(typeId: number): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
nextState(stateId: number, typeId: number): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
query(source: string): Parser.Query {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
lookaheadIterator(stateId: number): Parser.LookaheadIterable | null {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
languageId: string = '';
|
||||
}
|
||||
|
||||
suite('TreeSitterParserService', function () {
|
||||
const treeSitterImporter: TreeSitterImporter = new MockTreeSitterImporter();
|
||||
let logService: ILogService;
|
||||
let telemetryService: ITelemetryService;
|
||||
setup(function () {
|
||||
logService = new LogService(new ConsoleMainLogger());
|
||||
telemetryService = new class extends mock<ITelemetryService>() {
|
||||
override async publicLog2() {
|
||||
//
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('TextModelTreeSitter race condition: first language is slow to load', async function () {
|
||||
class MockTreeSitterParser extends TreeSitterLanguages {
|
||||
public override async getLanguage(languageId: string): Promise<Parser.Language | undefined> {
|
||||
if (languageId === 'javascript') {
|
||||
await timeout(200);
|
||||
}
|
||||
const language = new MockLanguage();
|
||||
language.languageId = languageId;
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
const treeSitterParser: TreeSitterLanguages = store.add(new MockTreeSitterParser(treeSitterImporter, {} as any));
|
||||
const textModel = store.add(createTextModel('console.log("Hello, world!");', 'javascript'));
|
||||
const textModelTreeSitter = store.add(new TextModelTreeSitter(textModel, treeSitterParser, treeSitterImporter, logService, telemetryService));
|
||||
textModel.setLanguage('typescript');
|
||||
await timeout(300);
|
||||
assert.strictEqual((textModelTreeSitter.tree?.language as MockLanguage).languageId, 'typescript');
|
||||
});
|
||||
});
|
||||
Vendored
+3
@@ -2919,6 +2919,9 @@ declare namespace monaco.editor {
|
||||
* An event describing a change in the text of a model.
|
||||
*/
|
||||
export interface IModelContentChangedEvent {
|
||||
/**
|
||||
* The changes are ordered from the end of the document to the beginning, so they should be safe to apply in sequence.
|
||||
*/
|
||||
readonly changes: IModelContentChange[];
|
||||
/**
|
||||
* The (new) end-of-line character.
|
||||
|
||||
@@ -18,6 +18,7 @@ import { removeDangerousEnvVariables } from 'vs/base/common/processes';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { isUNCAccessRestrictionsDisabled, getUNCHostAllowlist } from 'vs/base/node/unc';
|
||||
import { upcast } from 'vs/base/common/types';
|
||||
|
||||
export interface IUtilityProcessConfiguration {
|
||||
|
||||
@@ -249,7 +250,10 @@ export class UtilityProcess extends Disposable {
|
||||
this.log('creating new...', Severity.Info);
|
||||
|
||||
// Fork utility process
|
||||
this.process = utilityProcess.fork(modulePath, args, {
|
||||
this.process = utilityProcess.fork(modulePath, args, upcast<ForkOptions, ForkOptions & {
|
||||
forceAllocationsToV8Sandbox?: boolean;
|
||||
respondToAuthRequestsFromMainProcess?: boolean;
|
||||
}>({
|
||||
serviceName,
|
||||
env,
|
||||
execArgv,
|
||||
@@ -257,10 +261,7 @@ export class UtilityProcess extends Disposable {
|
||||
forceAllocationsToV8Sandbox,
|
||||
respondToAuthRequestsFromMainProcess,
|
||||
stdio
|
||||
} as ForkOptions & {
|
||||
forceAllocationsToV8Sandbox?: Boolean;
|
||||
respondToAuthRequestsFromMainProcess?: boolean;
|
||||
});
|
||||
}));
|
||||
|
||||
// Register to events
|
||||
this.registerListeners(this.process, this.configuration, serviceName);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AsyncIterableObject } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas, matchesScheme } from 'vs/base/common/network';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -1206,17 +1206,17 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
},
|
||||
registerFileSearchProviderNew: (scheme: string, provider: vscode.FileSearchProviderNew) => {
|
||||
checkProposedApiEnabled(extension, 'fileSearchProviderNew');
|
||||
return <IDisposable>{ dispose: () => { } };
|
||||
return { dispose: () => { } };
|
||||
},
|
||||
registerTextSearchProviderNew: (scheme: string, provider: vscode.TextSearchProviderNew) => {
|
||||
checkProposedApiEnabled(extension, 'textSearchProviderNew');
|
||||
return <IDisposable>{ dispose: () => { } };
|
||||
return { dispose: () => { } };
|
||||
},
|
||||
registerAITextSearchProviderNew: (scheme: string, provider: vscode.AITextSearchProviderNew) => {
|
||||
// there are some dependencies on textSearchProvider, so we need to check for both
|
||||
checkProposedApiEnabled(extension, 'aiTextSearchProviderNew');
|
||||
checkProposedApiEnabled(extension, 'textSearchProviderNew');
|
||||
return <IDisposable>{ dispose: () => { } };
|
||||
return { dispose: () => { } };
|
||||
},
|
||||
registerRemoteAuthorityResolver: (authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver) => {
|
||||
checkProposedApiEnabled(extension, 'resolvers');
|
||||
|
||||
@@ -787,7 +787,7 @@ export namespace SymbolTag {
|
||||
|
||||
export namespace WorkspaceSymbol {
|
||||
export function from(info: vscode.SymbolInformation): search.IWorkspaceSymbol {
|
||||
return <search.IWorkspaceSymbol>{
|
||||
return {
|
||||
name: info.name,
|
||||
kind: SymbolKind.from(info.kind),
|
||||
tags: info.tags && info.tags.map(SymbolTag.from),
|
||||
@@ -966,7 +966,7 @@ export namespace Hover {
|
||||
|
||||
export namespace EvaluatableExpression {
|
||||
export function from(expression: vscode.EvaluatableExpression): languages.EvaluatableExpression {
|
||||
return <languages.EvaluatableExpression>{
|
||||
return {
|
||||
range: Range.from(expression.range),
|
||||
expression: expression.expression
|
||||
};
|
||||
@@ -980,24 +980,24 @@ export namespace EvaluatableExpression {
|
||||
export namespace InlineValue {
|
||||
export function from(inlineValue: vscode.InlineValue): languages.InlineValue {
|
||||
if (inlineValue instanceof types.InlineValueText) {
|
||||
return <languages.InlineValueText>{
|
||||
return {
|
||||
type: 'text',
|
||||
range: Range.from(inlineValue.range),
|
||||
text: inlineValue.text
|
||||
};
|
||||
} satisfies languages.InlineValueText;
|
||||
} else if (inlineValue instanceof types.InlineValueVariableLookup) {
|
||||
return <languages.InlineValueVariableLookup>{
|
||||
return {
|
||||
type: 'variable',
|
||||
range: Range.from(inlineValue.range),
|
||||
variableName: inlineValue.variableName,
|
||||
caseSensitiveLookup: inlineValue.caseSensitiveLookup
|
||||
};
|
||||
} satisfies languages.InlineValueVariableLookup;
|
||||
} else if (inlineValue instanceof types.InlineValueEvaluatableExpression) {
|
||||
return <languages.InlineValueExpression>{
|
||||
return {
|
||||
type: 'expression',
|
||||
range: Range.from(inlineValue.range),
|
||||
expression: inlineValue.expression
|
||||
};
|
||||
} satisfies languages.InlineValueExpression;
|
||||
} else {
|
||||
throw new Error(`Unknown 'InlineValue' type`);
|
||||
}
|
||||
@@ -1006,28 +1006,28 @@ export namespace InlineValue {
|
||||
export function to(inlineValue: languages.InlineValue): vscode.InlineValue {
|
||||
switch (inlineValue.type) {
|
||||
case 'text':
|
||||
return <vscode.InlineValueText>{
|
||||
return {
|
||||
range: Range.to(inlineValue.range),
|
||||
text: inlineValue.text
|
||||
};
|
||||
} satisfies vscode.InlineValueText;
|
||||
case 'variable':
|
||||
return <vscode.InlineValueVariableLookup>{
|
||||
return {
|
||||
range: Range.to(inlineValue.range),
|
||||
variableName: inlineValue.variableName,
|
||||
caseSensitiveLookup: inlineValue.caseSensitiveLookup
|
||||
};
|
||||
} satisfies vscode.InlineValueVariableLookup;
|
||||
case 'expression':
|
||||
return <vscode.InlineValueEvaluatableExpression>{
|
||||
return {
|
||||
range: Range.to(inlineValue.range),
|
||||
expression: inlineValue.expression
|
||||
};
|
||||
} satisfies vscode.InlineValueEvaluatableExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace InlineValueContext {
|
||||
export function from(inlineValueContext: vscode.InlineValueContext): extHostProtocol.IInlineValueContextDto {
|
||||
return <extHostProtocol.IInlineValueContextDto>{
|
||||
return {
|
||||
frameId: inlineValueContext.frameId,
|
||||
stoppedLocation: Range.from(inlineValueContext.stoppedLocation)
|
||||
};
|
||||
|
||||
@@ -27,11 +27,15 @@ import { TestTextResourcePropertiesService, TestWorkingCopyFileService } from 'v
|
||||
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { LanguageService } from 'vs/editor/common/services/languageService';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { LanguageService } from 'vs/editor/common/services/languageService';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
|
||||
suite('MainThreadDocumentsAndEditors', () => {
|
||||
|
||||
@@ -61,12 +65,15 @@ suite('MainThreadDocumentsAndEditors', () => {
|
||||
const notificationService = new TestNotificationService();
|
||||
const undoRedoService = new UndoRedoService(dialogService, notificationService);
|
||||
const themeService = new TestThemeService();
|
||||
const instantiationService = new TestInstantiationService();
|
||||
instantiationService.set(ILanguageService, disposables.add(new LanguageService()));
|
||||
instantiationService.set(ILanguageConfigurationService, new TestLanguageConfigurationService());
|
||||
instantiationService.set(IUndoRedoService, undoRedoService);
|
||||
modelService = new ModelService(
|
||||
configService,
|
||||
new TestTextResourcePropertiesService(configService),
|
||||
undoRedoService,
|
||||
disposables.add(new LanguageService()),
|
||||
new TestLanguageConfigurationService(),
|
||||
instantiationService
|
||||
);
|
||||
codeEditorService = new TestCodeEditorService(themeService);
|
||||
textFileService = new class extends mock<ITextFileService>() {
|
||||
|
||||
@@ -16,12 +16,10 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
|
||||
import { LanguageService } from 'vs/editor/common/services/languageService';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { ModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
|
||||
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
@@ -57,6 +55,10 @@ import { ICopyOperation, ICreateFileOperation, ICreateOperation, IDeleteOperatio
|
||||
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { TestEditorGroupsService, TestEditorService, TestEnvironmentService, TestFileService, TestLifecycleService, TestWorkingCopyService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestContextService, TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { LanguageService } from 'vs/editor/common/services/languageService';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
|
||||
|
||||
suite('MainThreadEditors', () => {
|
||||
|
||||
@@ -80,19 +82,11 @@ suite('MainThreadEditors', () => {
|
||||
createdResources.clear();
|
||||
deletedResources.clear();
|
||||
|
||||
|
||||
const configService = new TestConfigurationService();
|
||||
const dialogService = new TestDialogService();
|
||||
const notificationService = new TestNotificationService();
|
||||
const undoRedoService = new UndoRedoService(dialogService, notificationService);
|
||||
const themeService = new TestThemeService();
|
||||
modelService = new ModelService(
|
||||
configService,
|
||||
new TestTextResourcePropertiesService(configService),
|
||||
undoRedoService,
|
||||
disposables.add(new LanguageService()),
|
||||
new TestLanguageConfigurationService(),
|
||||
);
|
||||
|
||||
const services = new ServiceCollection();
|
||||
services.set(IBulkEditService, new SyncDescriptor(BulkEditService));
|
||||
@@ -178,8 +172,18 @@ suite('MainThreadEditors', () => {
|
||||
}
|
||||
});
|
||||
|
||||
services.set(ILanguageService, disposables.add(new LanguageService()));
|
||||
services.set(ILanguageConfigurationService, new TestLanguageConfigurationService());
|
||||
|
||||
const instaService = new InstantiationService(services);
|
||||
|
||||
modelService = new ModelService(
|
||||
configService,
|
||||
new TestTextResourcePropertiesService(configService),
|
||||
undoRedoService,
|
||||
instaService
|
||||
);
|
||||
|
||||
bulkEdits = instaService.createInstance(MainThreadBulkEdits, SingleProxyRPCProtocol(null));
|
||||
});
|
||||
|
||||
|
||||
@@ -25,13 +25,11 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
|
||||
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
|
||||
import { AriaRole } from 'vs/base/browser/ui/aria/aria';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
// --- VIEW MODEL
|
||||
|
||||
@@ -202,9 +200,7 @@ export class BulkEditDataSource implements IAsyncDataSource<BulkFileOperations,
|
||||
|
||||
constructor(
|
||||
@ITextModelService private readonly _textModelService: ITextModelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) { }
|
||||
|
||||
hasChildren(element: BulkFileOperations | BulkEditElement): boolean {
|
||||
@@ -241,7 +237,7 @@ export class BulkEditDataSource implements IAsyncDataSource<BulkFileOperations,
|
||||
textModel = ref.object.textEditorModel;
|
||||
textModelDisposable = ref;
|
||||
} catch {
|
||||
textModel = new TextModel('', PLAINTEXT_LANGUAGE_ID, TextModel.DEFAULT_CREATION_OPTIONS, null, this._undoRedoService, this._languageService, this._languageConfigurationService);
|
||||
textModel = this._instantiationService.createInstance(TextModel, '', PLAINTEXT_LANGUAGE_ID, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
textModelDisposable = textModel;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,18 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { EditorType } from 'vs/editor/common/editorCommon';
|
||||
import { Command } from 'vs/editor/common/languages';
|
||||
import { AbstractGotoSymbolQuickAccessProvider, IGotoSymbolQuickPickItem } from 'vs/editor/contrib/quickAccess/browser/gotoSymbolQuickAccess';
|
||||
import { localize, localize2 } from 'vs/nls';
|
||||
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { AnythingQuickAccessProviderRunOptions } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
@@ -27,13 +30,10 @@ import { CONTEXT_CHAT_LOCATION, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_QUICK_CHAT } f
|
||||
import { IChatRequestVariableEntry } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { ChatRequestAgentPart } from 'vs/workbench/contrib/chat/common/chatParserTypes';
|
||||
import { IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVariables';
|
||||
import { ILanguageModelToolsService } from 'vs/workbench/contrib/chat/common/languageModelToolsService';
|
||||
import { AnythingQuickAccessProvider } from 'vs/workbench/contrib/search/browser/anythingQuickAccess';
|
||||
import { ISymbolQuickPickItem, SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorType } from 'vs/editor/common/editorCommon';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { ILanguageModelToolsService } from 'vs/workbench/contrib/chat/common/languageModelToolsService';
|
||||
|
||||
export function registerChatContextActions() {
|
||||
registerAction2(AttachContextAction);
|
||||
@@ -107,7 +107,7 @@ class AttachFileAction extends Action2 {
|
||||
const textEditorService = accessor.get(IEditorService);
|
||||
|
||||
const activeUri = textEditorService.activeEditor?.resource;
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote].includes(activeUri.scheme)) {
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote, Schemas.untitled].includes(activeUri.scheme)) {
|
||||
variablesService.attachContext('file', activeUri, ChatAgentLocation.Panel);
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ class AttachSelectionAction extends Action2 {
|
||||
|
||||
const activeEditor = textEditorService.activeTextEditorControl;
|
||||
const activeUri = textEditorService.activeEditor?.resource;
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote].includes(activeUri.scheme)) {
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote, Schemas.untitled].includes(activeUri.scheme)) {
|
||||
const selection = activeEditor?.getSelection();
|
||||
if (selection) {
|
||||
variablesService.attachContext('file', { uri: activeUri, range: selection }, ChatAgentLocation.Panel);
|
||||
|
||||
@@ -164,8 +164,7 @@ export class ChatVariablesService implements IChatVariablesService {
|
||||
return;
|
||||
}
|
||||
|
||||
await showChatView(this.viewsService);
|
||||
const widget = this.chatWidgetService.lastFocusedWidget;
|
||||
const widget = await showChatView(this.viewsService);
|
||||
if (!widget || !widget.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,26 +4,24 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { ModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export class WorkbenchModelService extends ModelService {
|
||||
constructor(
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IUndoRedoService undoRedoService: IUndoRedoService,
|
||||
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
|
||||
@ILanguageService languageService: ILanguageService,
|
||||
@IPathService private readonly _pathService: IPathService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
super(configurationService, resourcePropertiesService, undoRedoService, languageService, languageConfigurationService);
|
||||
super(configurationService, resourcePropertiesService, undoRedoService, instantiationService);
|
||||
}
|
||||
|
||||
protected override _schemaShouldMaintainUndoRedoElements(resource: URI) {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerSingleton, InstantiationType } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions';
|
||||
import { TreeSitterTextModelService } from 'vs/editor/browser/services/treeSitter/treeSitterParserService';
|
||||
import { ITreeSitterParserService } from 'vs/editor/common/services/treeSitterParserService';
|
||||
|
||||
/**
|
||||
* Makes sure the ITreeSitterTokenizationService is instantiated
|
||||
*/
|
||||
class TreeSitterTokenizationInstantiator implements IWorkbenchContribution {
|
||||
|
||||
static readonly ID = 'workbench.contrib.treeSitterTokenizationInstantiator';
|
||||
|
||||
constructor(
|
||||
@ITreeSitterParserService _treeSitterTokenizationService: ITreeSitterParserService
|
||||
) { }
|
||||
}
|
||||
|
||||
registerSingleton(ITreeSitterParserService, TreeSitterTextModelService, InstantiationType.Eager);
|
||||
|
||||
registerWorkbenchContribution2(TreeSitterTokenizationInstantiator.ID, TreeSitterTokenizationInstantiator, WorkbenchPhase.BlockRestore);
|
||||
@@ -123,7 +123,7 @@ import { IEnterWorkspaceResult, IRecent, IRecentlyOpened, IWorkspaceFolderCreati
|
||||
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { IExtensionTerminalProfile, IShellLaunchConfig, ITerminalBackend, ITerminalLogService, ITerminalProfile, TerminalIcon, TerminalLocation, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { ICreateTerminalOptions, IDeserializedTerminalEditorInput, ITerminalConfigurationService, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { assertIsDefined, upcast } from 'vs/base/common/types';
|
||||
import { IRegisterContributedProfileArgs, IShellLaunchConfigResolveOptions, ITerminalProfileProvider, ITerminalProfileResolverService, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { EditorResolverService } from 'vs/workbench/services/editor/browser/editorResolverService';
|
||||
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
|
||||
@@ -211,12 +211,7 @@ export class TestTextFileEditor extends TextFileEditor {
|
||||
}
|
||||
|
||||
setSelection(selection: Selection | undefined, reason: EditorPaneSelectionChangeReason): void {
|
||||
if (selection) {
|
||||
const options: ITextEditorOptions = { selection };
|
||||
this._options = options;
|
||||
} else {
|
||||
this._options = undefined;
|
||||
}
|
||||
this._options = selection ? upcast<IEditorOptions, ITextEditorOptions>({ selection }) : undefined;
|
||||
|
||||
this._onDidChangeSelection.fire({ reason });
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ import 'vs/editor/common/services/languageFeaturesService';
|
||||
import 'vs/editor/common/services/semanticTokensStylingService';
|
||||
import 'vs/editor/common/services/treeViewsDndService';
|
||||
import 'vs/workbench/services/textMate/browser/textMateTokenizationFeature.contribution';
|
||||
import 'vs/workbench/services/treeSitter/browser/treeSitterTokenizationFeature.contribution';
|
||||
import 'vs/workbench/services/userActivity/common/userActivityService';
|
||||
import 'vs/workbench/services/userActivity/browser/userActivityBrowser';
|
||||
import 'vs/workbench/services/editor/browser/editorPaneService';
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
'sinon-test': new URL('../../../node_modules/sinon-test/dist/sinon-test.js', baseUrl).href,
|
||||
'@xterm/xterm': new URL('../../../node_modules/@xterm/xterm/lib/xterm.js', baseUrl).href,
|
||||
'@vscode/iconv-lite-umd': new URL('../../../node_modules/@vscode/iconv-lite-umd/lib/iconv-lite-umd.js', baseUrl).href,
|
||||
'@vscode/tree-sitter-wasm': new URL('../../../node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js', baseUrl).href,
|
||||
jschardet: new URL('../../../node_modules/jschardet/dist/jschardet.min.js', baseUrl).href
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1666,6 +1666,11 @@
|
||||
tar-fs "^3.0.6"
|
||||
vscode-uri "^3.0.8"
|
||||
|
||||
"@vscode/tree-sitter-wasm@^0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.0.1.tgz#ffb2e295a416698f4c77cbffeca3b28567d6754b"
|
||||
integrity sha512-m0GKnQ3BxWnVd+20KLGwr1+Qvt/RiiaJmKAqHNU35pNydDtduUzyBm7ETz/T0vOVKoeIAaiYsJOA1aKWs7Y1tA==
|
||||
|
||||
"@vscode/v8-heap-parser@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/v8-heap-parser/-/v8-heap-parser-0.1.0.tgz#f3fe61ce954cc3dd78ed42e09f865450685e351f"
|
||||
|
||||
Reference in New Issue
Block a user