In Eclipse, you work within a clearly defined project tree with fixed workspace boundaries. VSCode takes a more flexible approach using workspace folders, which can represent individual directories or collections of multiple project folders. A VSCode workspace can be empty (only single files opened), contain a single folder, or represent a multi-root workspace with multiple independent project folders.
This flexibility requires explicit handling in extensions. Unlike Eclipse plugins, which automatically receive a project context, VSCode extensions must check whether a workspace is available at all and possibly handle multiple workspace folders.
Access is done via the static array
vscode.workspace.workspaceFolders. This array can have
three states: undefined (no workspace), one element
(single-root), or multiple elements (multi-root):
function getActiveWorkspace(): vscode.WorkspaceFolder | undefined {
const folders = vscode.workspace.workspaceFolders;
// Checking for undefined is mandatory
if (!folders || folders.length === 0) {
return undefined;
}
// For multi-root use the first folder as default
return folders[0];
}
async function demonstrateWorkspaceAccess(): Promise<void> {
const workspace = getActiveWorkspace();
if (!workspace) {
vscode.window.showInformationMessage('No workspace opened');
return;
}
console.log(`Workspace name: ${workspace.name}`);
console.log(`Workspace URI: ${workspace.uri.toString()}`);
console.log(`Filesystem path: ${workspace.uri.fsPath}`);
}The WorkspaceFolder interface provides three properties:
uri as platform-independent resource address,
name as display name, and index for the
position in multi-root workspaces.
Navigation within a workspace is done exclusively using
vscode.Uri.joinPath(), which ensures cross-platform path
construction. Never use string concatenation for paths:
async function navigateWorkspaceStructure(workspace: vscode.WorkspaceFolder): Promise<void> {
// Correct path construction using Uri.joinPath
const srcFolder = vscode.Uri.joinPath(workspace.uri, 'src');
const configFile = vscode.Uri.joinPath(workspace.uri, 'config', 'settings.json');
const testFolder = vscode.Uri.joinPath(workspace.uri, 'test', 'unit');
try {
// List directory contents
const entries = await vscode.workspace.fs.readDirectory(workspace.uri);
console.log(`Workspace contains ${entries.length} entries`);
// Open specific file if present
await vscode.workspace.fs.stat(configFile);
const document = await vscode.workspace.openTextDocument(configFile);
console.log(`Configuration file loaded: ${document.fileName}`);
} catch (error) {
console.log(`File not found or unreadable: ${error}`);
}
}
async function createWorkspaceStructure(workspace: vscode.WorkspaceFolder): Promise<void> {
const directories = ['src', 'test', 'config', 'docs'];
for (const dir of directories) {
const dirUri = vscode.Uri.joinPath(workspace.uri, dir);
try {
await vscode.workspace.fs.createDirectory(dirUri);
console.log(`Directory created: ${dir}`);
} catch {
console.log(`Directory already exists: ${dir}`);
}
}
}VSCode differentiates between workspace contents and extension-specific storage locations. Workspace folders contain project files, while extensions should store their own data in separate directories:
function demonstrateStorageLocations(
workspace: vscode.WorkspaceFolder,
context: vscode.ExtensionContext
): void {
// Workspace files: project-specific content
const projectFile = vscode.Uri.joinPath(workspace.uri, 'src', 'main.ts');
// Global storage: extension data for all workspaces
const globalConfig = vscode.Uri.joinPath(
context.globalStorageUri,
'extension-settings.json'
);
// Workspace storage: extension data only for this workspace
const workspaceConfig = vscode.Uri.joinPath(
context.storageUri!,
'workspace-cache.json'
);
console.log(`Project file: ${projectFile.fsPath}`);
console.log(`Global extension data: ${globalConfig.fsPath}`);
console.log(`Workspace-specific extension data: ${workspaceConfig.fsPath}`);
}The difference between workspace.uri and
context.storageUri is fundamental: workspace URIs point to
user content, storage URIs to extension-internal data.
The Uri.joinPath() method is the only reliable method
for path construction in VSCode extensions. It automatically handles
platform differences and remote workspaces:
function demonstratePathOperations(workspace: vscode.WorkspaceFolder): void {
// Multiple path components in one call
const deepPath = vscode.Uri.joinPath(
workspace.uri,
'src', 'main', 'typescript', 'controllers'
);
// Dynamic path construction
const moduleName = 'UserService';
const moduleFile = vscode.Uri.joinPath(
workspace.uri,
'src',
`${moduleName}.ts`
);
// WRONG: avoid string concatenation
// const wrongPath = workspace.uri.fsPath + '/src/main.ts';
// CORRECT: always use Uri.joinPath
const correctPath = vscode.Uri.joinPath(workspace.uri, 'src', 'main.ts');
console.log(`Deep path: ${deepPath.fsPath}`);
console.log(`Module file: ${moduleFile.fsPath}`);
console.log(`Correct path: ${correctPath.fsPath}`);
}Robust extensions must gracefully handle the absence of a workspace. Either provide reduced functionality or guide the user to create a workspace:
async function requireWorkspaceOperation(): Promise<boolean> {
const workspace = getActiveWorkspace();
if (!workspace) {
const action = await vscode.window.showInformationMessage(
'This function requires an open workspace',
'Open Folder'
);
if (action === 'Open Folder') {
await vscode.commands.executeCommand('workbench.action.files.openFolder');
}
return false;
}
return true;
}Always use Uri.joinPath() for path operations, even on
known operating systems. Check the existence of
workspaceFolders before each access. Separate extension
data from workspace content by using context.storageUri and
context.globalStorageUri. In multi-root workspaces, either
process all folders or let the user choose. Cache workspace information
only temporarily, as workspaces can change at runtime.
Hier ist die präzise 1:1-Übersetzung, ohne Veränderung der Markdown-Struktur oder Codeblöcke: