workspace.ts ×27

Frontier kind: Code frontier

unlabeled · c_e1e76e9334a0

2140 tests · 6247 LOC · 32 files · introduces 0 tests · 322 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
27 ranges322 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
874 ranges6247 lines · 32 files · Browse complete extent
All tests (intent)
2140 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 322 introduced LOC across 27 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/workspace/common/workspace.ts 322 introduced LOC · 27 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- workspace.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { localize } from '../../../nls.js';
7 > import { Event } from '../../../base/common/event.js';
8 > import { basename, extname } from '../../../base/common/path.js';
9 > import { TernarySearchTree } from '../../../base/common/ternarySearchTree.js';
10 > import { extname as resourceExtname, basenameOrAuthority, joinPath, extUriBiasedIgnorePathCase } from '../../../base/common/resources.js';
11 > import { URI, UriComponents } from '../../../base/common/uri.js';
12 > import { createDecorator } from '../../instantiation/common/instantiation.js';
13 > import { IEnvironmentService } from '../../environment/common/environment.js';
14 > import { Schemas } from '../../../base/common/network.js';
15 >
16 > export const IWorkspaceContextService = createDecorator<IWorkspaceContextService>('contextService');
17 >
18 > export interface IWorkspaceContextService {
19 >
20 > readonly _serviceBrand: undefined;
21 >
22 > /**
23 > * An event which fires on workbench state changes.
24 > */
25 > readonly onDidChangeWorkbenchState: Event<WorkbenchState>;
26 >
27 > /**
28 > * An event which fires on workspace name changes.
29 > */
30 > readonly onDidChangeWorkspaceName: Event<void>;
31 >
32 > /**
33 > * An event which fires before workspace folders change.
34 > */
35 > readonly onWillChangeWorkspaceFolders: Event<IWorkspaceFoldersWillChangeEvent>;
36 >
37 > /**
38 > * An event which fires on workspace folders change.
39 > */
40 > readonly onDidChangeWorkspaceFolders: Event<IWorkspaceFoldersChangeEvent>;
41 >
42 > /**
43 > * Provides access to the complete workspace object.
44 > */
45 > getCompleteWorkspace(): Promise<IWorkspace>;
46 >
47 > /**
48 > * Provides access to the workspace object the window is running with.
49 > * Use `getCompleteWorkspace` to get complete workspace object.
50 > */
51 > getWorkspace(): IWorkspace;
52 >
53 > /**
54 > * Return the state of the workbench.
55 > *
56 > * WorkbenchState.EMPTY - if the workbench was opened with empty window or file
57 > * WorkbenchState.FOLDER - if the workbench was opened with a folder
58 > * WorkbenchState.WORKSPACE - if the workbench was opened with a workspace
59 > */
60 > getWorkbenchState(): WorkbenchState;
61 >
62 > /**
63 > * Returns the folder for the given resource from the workspace.
64 > * Can be null if there is no workspace or the resource is not inside the workspace.
65 > */
66 > getWorkspaceFolder(resource: URI): IWorkspaceFolder | null;
67 >
68 > /**
69 > * Return `true` if the current workspace has the given identifier or root URI otherwise `false`.
70 > */
71 > isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean;
72 >
73 > /**
74 > * Returns if the provided resource is inside the workspace or not.
75 > */
76 > isInsideWorkspace(resource: URI): boolean;
77 >
78 > /**
79 > * Return `true` if the current workspace has data (e.g. folders or a workspace configuration) that can be sent to the extension host, otherwise `false`.
80 > */
81 > hasWorkspaceData(): boolean;
82 > }
83 >
84 > export interface IResolvedWorkspace extends IWorkspaceIdentifier, IBaseWorkspace {
85 > readonly folders: IWorkspaceFolder[];
86 > }
87 >
88 > export interface IBaseWorkspace {
89 >
90 > /**
91 > * If present, marks the window that opens the workspace
92 > * as a remote window with the given authority.
93 > */
94 > readonly remoteAuthority?: string;
95 >
96 > /**
97 > * Transient workspaces are meant to go away after being used
98 > * once, e.g. a window reload of a transient workspace will
99 > * open an empty window.
100 > *
101 > * See: https://github.com/microsoft/vscode/issues/119695
102 > */
103 > readonly transient?: boolean;
104 > }
105 >
106 > export interface IBaseWorkspaceIdentifier {
107 >
108 > /**
109 > * Every workspace (multi-root, single folder or empty)
110 > * has a unique identifier. It is not possible to open
111 > * a workspace with the same `id` in multiple windows
112 > */
113 > readonly id: string;
114 > }
115 >
116 > /**
117 > * A single folder workspace identifier is a path to a folder + id.
118 > */
119 > export interface ISingleFolderWorkspaceIdentifier extends IBaseWorkspaceIdentifier {
120 >
121 > /**
122 > * Folder path as `URI`.
123 > */
124 > readonly uri: URI;
125 > }
126 >
127 > /**
128 > * A multi-root workspace identifier is a path to a workspace file + id.
129 > */
130 > export interface IWorkspaceIdentifier extends IBaseWorkspaceIdentifier {
131 >
132 > /**
133 > * Workspace config file path as `URI`.
134 > */
135 > configPath: URI;
136 > }
137 >
138 > export interface IEmptyWorkspaceIdentifier extends IBaseWorkspaceIdentifier { }
139 >
140 > export type IAnyWorkspaceIdentifier = IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier;
141 >
142 > export function isSingleFolderWorkspaceIdentifier(obj: unknown): obj is ISingleFolderWorkspaceIdentifier {
143 const singleFolderIdentifier = obj as ISingleFolderWorkspaceIdentifier | undefined;
144
145 return typeof singleFolderIdentifier?.id === 'string' && URI.isUri(singleFolderIdentifier.uri);
146 }
147 > workspace.ts
148 > export function isEmptyWorkspaceIdentifier(obj: unknown): obj is IEmptyWorkspaceIdentifier {
149 const emptyWorkspaceIdentifier = obj as IEmptyWorkspaceIdentifier | undefined;
150 return typeof emptyWorkspaceIdentifier?.id === 'string'
152 && !isWorkspaceIdentifier(obj);
153 }
154 > workspace.ts
155 > export const EXTENSION_DEVELOPMENT_EMPTY_WINDOW_WORKSPACE: IEmptyWorkspaceIdentifier = { id: 'ext-dev' };
156 > export const UNKNOWN_EMPTY_WINDOW_WORKSPACE: IEmptyWorkspaceIdentifier = { id: 'empty-window' };
157 >
158 > export function toWorkspaceIdentifier(workspace: IWorkspace): IAnyWorkspaceIdentifier;
159 > export function toWorkspaceIdentifier(backupPath: string | undefined, isExtensionDevelopment: boolean): IEmptyWorkspaceIdentifier;
160 > export function toWorkspaceIdentifier(arg0: IWorkspace | string | undefined, isExtensionDevelopment?: boolean): IAnyWorkspaceIdentifier {
161
162 // Empty workspace
202 };
203 }
204 > workspace.ts
205 > export function isWorkspaceIdentifier(obj: unknown): obj is IWorkspaceIdentifier {
206 const workspaceIdentifier = obj as IWorkspaceIdentifier | undefined;
207
208 return typeof workspaceIdentifier?.id === 'string' && URI.isUri(workspaceIdentifier.configPath);
209 }
210 > workspace.ts
211 > export interface ISerializedSingleFolderWorkspaceIdentifier extends IBaseWorkspaceIdentifier {
212 > readonly uri: UriComponents;
213 > }
214 >
215 > export interface ISerializedWorkspaceIdentifier extends IBaseWorkspaceIdentifier {
216 > readonly configPath: UriComponents;
217 > }
218 >
219 > export function reviveIdentifier(identifier: undefined): undefined;
220 > export function reviveIdentifier(identifier: ISerializedWorkspaceIdentifier): IWorkspaceIdentifier;
221 > export function reviveIdentifier(identifier: ISerializedSingleFolderWorkspaceIdentifier): ISingleFolderWorkspaceIdentifier;
222 > export function reviveIdentifier(identifier: IEmptyWorkspaceIdentifier): IEmptyWorkspaceIdentifier;
223 > export function reviveIdentifier(identifier: ISerializedWorkspaceIdentifier | ISerializedSingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier | undefined): IAnyWorkspaceIdentifier | undefined;
224 > export function reviveIdentifier(identifier: ISerializedWorkspaceIdentifier | ISerializedSingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier | undefined): IAnyWorkspaceIdentifier | undefined {
225
226 // Single Folder
243 return undefined;
244 }
245 > workspace.ts
246 > export const enum WorkbenchState {
247 > EMPTY = 1,
248 > FOLDER,
249 > WORKSPACE
250 > }
251 >
252 > export interface IWorkspaceFoldersWillChangeEvent {
253 >
254 > readonly changes: IWorkspaceFoldersChangeEvent;
255 > readonly fromCache: boolean;
256 >
257 > join(promise: Promise<void>): void;
258 > }
259 >
260 > export interface IWorkspaceFoldersChangeEvent {
261 > added: IWorkspaceFolder[];
262 > removed: IWorkspaceFolder[];
263 > changed: IWorkspaceFolder[];
264 > }
265 >
266 > export interface IWorkspace {
267 >
268 > /**
269 > * the unique identifier of the workspace.
270 > */
271 > readonly id: string;
272 >
273 > /**
274 > * Folders in the workspace.
275 > */
276 > readonly folders: IWorkspaceFolder[];
277 >
278 > /**
279 > * Transient workspaces are meant to go away after being used
280 > * once, e.g. a window reload of a transient workspace will
281 > * open an empty window.
282 > */
283 > readonly transient?: boolean;
284 >
285 > /**
286 > * the location of the workspace configuration
287 > */
288 > readonly configuration?: URI | null;
289 >
290 > /**
291 > * Optional display name for the workspace.
292 > */
293 > readonly name?: string;
294 >
295 > }
296 >
297 > export function isWorkspace(thing: unknown): thing is IWorkspace {
298 const candidate = thing as IWorkspace | undefined;
299
302 && Array.isArray(candidate.folders));
303 }
304 > workspace.ts
305 > export interface IWorkspaceFolderData {
306 >
307 > /**
308 > * The associated URI for this workspace folder.
309 > */
310 > readonly uri: URI;
311 >
312 > /**
313 > * The name of this workspace folder. Defaults to
314 > * the basename of its [uri-path](#Uri.path)
315 > */
316 > readonly name: string;
317 >
318 > /**
319 > * The ordinal number of this workspace folder.
320 > */
321 > readonly index: number;
322 > }
323 >
324 > export interface IWorkspaceFolder extends IWorkspaceFolderData {
325 >
326 > /**
327 > * Given workspace folder relative path, returns the resource with the absolute path.
328 > */
329 > toResource: (relativePath: string) => URI;
330 > }
331 >
332 > export function isWorkspaceFolder(thing: unknown): thing is IWorkspaceFolder {
333 const candidate = thing as IWorkspaceFolder;
334
338 && typeof candidate.toResource === 'function');
339 }
340 > workspace.ts
341 > export class Workspace implements IWorkspace {
342 >
343 > private foldersMap: TernarySearchTree<URI, WorkspaceFolder>;
344 >
345 > private _folders!: WorkspaceFolder[];
346 > get folders(): WorkspaceFolder[] { return this._folders; }
347 > set folders(folders: WorkspaceFolder[]) {
348 this._folders = folders;
349 this.updateFoldersMap();
350 }
351 > workspace.ts
352 > constructor(
353 private _id: string,
354 folders: WorkspaceFolder[],
361 this.folders = folders;
362 }
363 > workspace.ts
364 > update(workspace: Workspace) {
365 this._id = workspace.id;
366 this._configuration = workspace.configuration;
370 this.folders = workspace.folders;
371 }
372 > workspace.ts
373 > get id(): string {
374 return this._id;
375 }
376 > workspace.ts
377 > get transient(): boolean {
378 return this._transient;
379 }
380 > workspace.ts
381 > get configuration(): URI | null {
382 return this._configuration;
383 }
384 > workspace.ts
385 > set configuration(configuration: URI | null) {
386 this._configuration = configuration;
387 }
388 > workspace.ts
389 > get name(): string | undefined {
390 return this._workspaceName;
391 }
392 > workspace.ts
393 > getFolder(resource: URI): IWorkspaceFolder | null {
394 if (!resource) {
395 return null;
398 return this.foldersMap.findSubstr(resource) || null;
399 }
400 > workspace.ts
401 > private updateFoldersMap(): void {
402 this.foldersMap = TernarySearchTree.forUris<WorkspaceFolder>(this.ignorePathCasing, () => true);
403 for (const folder of this.folders) {
405 }
406 }
407 > workspace.ts
408 > toJSON(): IWorkspace {
409 return { id: this.id, folders: this.folders, transient: this.transient, configuration: this.configuration, name: this.name };
410 }
411 > } workspace.ts
412 >
413 > export interface IRawFileWorkspaceFolder {
414 > readonly path: string;
415 > name?: string;
416 > }
417 >
418 > export interface IRawUriWorkspaceFolder {
419 > readonly uri: string;
420 > name?: string;
421 > }
422 >
423 > export class WorkspaceFolder implements IWorkspaceFolder {
424 >
425 > readonly uri: URI;
426 > readonly name: string;
427 > readonly index: number;
428 >
429 > constructor(
430 data: IWorkspaceFolderData,
431 /**
442 this.name = data.name;
443 }
444 > workspace.ts
445 > toResource(relativePath: string): URI {
446 return joinPath(this.uri, relativePath);
447 }
448 > workspace.ts
449 > toJSON(): IWorkspaceFolderData {
450 return { uri: this.uri, name: this.name, index: this.index };
451 }
452 > } workspace.ts
453 >
454 > export function toWorkspaceFolder(resource: URI): WorkspaceFolder {
455 return new WorkspaceFolder({ uri: resource, index: 0, name: basenameOrAuthority(resource) }, { uri: resource.toString() });
456 }
457 > workspace.ts
458 > export const WORKSPACE_EXTENSION = 'code-workspace';
459 > export const WORKSPACE_SUFFIX = `.${WORKSPACE_EXTENSION}`;
460 > export const WORKSPACE_FILTER = [{ name: localize('codeWorkspace', "Code Workspace"), extensions: [WORKSPACE_EXTENSION] }];
461 > export const UNTITLED_WORKSPACE_NAME = 'workspace.json';
462 >
463 > export function isUntitledWorkspace(path: URI, environmentService: IEnvironmentService): boolean {
464 return extUriBiasedIgnorePathCase.isEqualOrParent(path, environmentService.untitledWorkspacesHome);
465 }
466 > workspace.ts
467 > export function isTemporaryWorkspace(workspace: IWorkspace): boolean;
468 > export function isTemporaryWorkspace(path: URI): boolean;
469 > export function isTemporaryWorkspace(arg1: IWorkspace | URI): boolean {
470 let path: URI | null | undefined;
471 if (URI.isUri(arg1)) {
477 return path?.scheme === Schemas.tmp;
478 }
479 > workspace.ts
480 > export const STANDALONE_EDITOR_WORKSPACE_ID = '4064f6ec-cb38-4ad0-af64-ee6467e63c82';
481 > export function isStandaloneEditorWorkspace(workspace: IWorkspace): boolean {
482 return workspace.id === STANDALONE_EDITOR_WORKSPACE_ID;
483 }
484 > workspace.ts
485 > export function isSavedWorkspace(path: URI, environmentService: IEnvironmentService): boolean {
486 return !isUntitledWorkspace(path, environmentService) && !isTemporaryWorkspace(path);
487 }
488 > workspace.ts
489 > export function hasWorkspaceFileExtension(path: string | URI) {
490 const ext = (typeof path === 'string') ? extname(path) : resourceExtname(path);
491