add existing project to workspace feature (#12249)

* add existing project to workspace feature

* update file name

* new test and use URI

* handle workspace with no folder

* add more validation

* and more tests

* use forward slash
This commit is contained in:
Alan Ren
2020-09-14 15:43:29 -07:00
committed by GitHub
parent 7a524d7a35
commit 23c16ebfb3
13 changed files with 530 additions and 30 deletions

View File

@@ -8,14 +8,44 @@ import * as dataworkspace from 'dataworkspace';
import * as path from 'path';
import { IWorkspaceService } from '../common/interfaces';
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
import * as nls from 'vscode-nls';
import Logger from '../common/logger';
import { ExtensionActivationErrorMessage } from '../common/constants';
const localize = nls.loadMessageBundle();
const WorkspaceConfigurationName = 'dataworkspace';
const ProjectsConfigurationName = 'projects';
export class WorkspaceService implements IWorkspaceService {
async addProjectsToWorkspace(projectFiles: vscode.Uri[]): Promise<void> {
if (vscode.workspace.workspaceFile) {
const currentProjects: vscode.Uri[] = await this.getProjectsInWorkspace();
const newWorkspaceFolders: string[] = [];
let newProjectFileAdded = false;
for (const projectFile of projectFiles) {
if (currentProjects.findIndex((p: vscode.Uri) => p.fsPath === projectFile.fsPath) === -1) {
currentProjects.push(projectFile);
newProjectFileAdded = true;
// if the relativePath and the original path is the same, that means the project file is not under
// any workspace folders, we should add the parent folder of the project file to the workspace
const relativePath = vscode.workspace.asRelativePath(projectFile, false);
if (vscode.Uri.file(relativePath).fsPath === projectFile.fsPath) {
newWorkspaceFolders.push(path.dirname(projectFile.path));
}
}
}
if (newProjectFileAdded) {
// Save the new set of projects to the workspace configuration.
await this.setWorkspaceConfigurationValue(ProjectsConfigurationName, currentProjects.map(project => this.toRelativePath(project)));
}
if (newWorkspaceFolders.length > 0) {
// second parameter is null means don't remove any workspace folders
vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders!.length, null, ...(newWorkspaceFolders.map(folder => ({ uri: vscode.Uri.file(folder) }))));
}
}
}
async getAllProjectTypes(): Promise<dataworkspace.IProjectType[]> {
await this.ensureProviderExtensionLoaded();
const projectTypes: dataworkspace.IProjectType[] = [];
@@ -25,16 +55,12 @@ export class WorkspaceService implements IWorkspaceService {
return projectTypes;
}
async getProjectsInWorkspace(): Promise<string[]> {
if (vscode.workspace.workspaceFile) {
const projects = <string[]>vscode.workspace.getConfiguration(WorkspaceConfigurationName).get(ProjectsConfigurationName);
return projects.map(project => path.isAbsolute(project) ? project : path.join(vscode.workspace.rootPath!, project));
}
return [];
async getProjectsInWorkspace(): Promise<vscode.Uri[]> {
return vscode.workspace.workspaceFile ? this.getWorkspaceConfigurationValue<string[]>(ProjectsConfigurationName).map(project => this.toUri(project)) : [];
}
async getProjectProvider(projectFilePath: string): Promise<dataworkspace.IProjectProvider | undefined> {
const projectType = path.extname(projectFilePath).replace(/\./g, '');
async getProjectProvider(projectFile: vscode.Uri): Promise<dataworkspace.IProjectProvider | undefined> {
const projectType = path.extname(projectFile.path).replace(/\./g, '');
let provider = ProjectProviderRegistry.getProviderByProjectType(projectType);
if (!provider) {
await this.ensureProviderExtensionLoaded(projectType);
@@ -70,7 +96,32 @@ export class WorkspaceService implements IWorkspaceService {
try {
await extension.activate();
} catch (err) {
Logger.error(localize('activateExtensionFailed', "Failed to load the project provider extension '{0}'. Error message: {1}", extension.id, err.message ?? err));
Logger.error(ExtensionActivationErrorMessage(extension.id, err));
}
}
getWorkspaceConfigurationValue<T>(configurationName: string): T {
return vscode.workspace.getConfiguration(WorkspaceConfigurationName).get(configurationName) as T;
}
async setWorkspaceConfigurationValue(configurationName: string, value: any): Promise<void> {
await vscode.workspace.getConfiguration(WorkspaceConfigurationName).update(configurationName, value, vscode.ConfigurationTarget.Workspace);
}
/**
* Gets the relative path to the workspace file
* @param filePath the absolute path
*/
private toRelativePath(filePath: vscode.Uri): string {
return path.relative(path.dirname(vscode.workspace.workspaceFile!.path!), filePath.path);
}
/**
* Gets the Uri of the given relative path
* @param relativePath the relative path
*/
private toUri(relativePath: string): vscode.Uri {
const fullPath = path.join(path.dirname(vscode.workspace.workspaceFile!.path!), relativePath);
return vscode.Uri.file(fullPath);
}
}