Skip to content

Commit

Permalink
Add workspace support (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
kosz78 committed Dec 1, 2018
1 parent 41f14e5 commit 805d3f1
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 46 deletions.
27 changes: 14 additions & 13 deletions src/nimBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import vscode = require('vscode');
import cp = require('child_process');
import os = require('os');
import { isWorkspaceFile, getNimExecPath, getProjectFile, getProjects, isProjectMode } from './nimUtils';
import { isWorkspaceFile, getNimExecPath, getProjectFileInfo, getProjects, isProjectMode, ProjectFileInfo, toLocalFile } from './nimUtils';
import { execNimSuggest, NimSuggestType, NimSuggestResult } from './nimSuggestExec';

export interface ICheckResult {
Expand All @@ -21,24 +21,24 @@ export interface ICheckResult {

let executors: { [project: string]: { initialized: boolean, process?: cp.ChildProcess } } = {};

function nimExec(project: string, command: string, args: string[], useStdErr: boolean, callback: (lines: string[]) => any) {
function nimExec(project: ProjectFileInfo, command: string, args: string[], useStdErr: boolean, callback: (lines: string[]) => any) {
return new Promise((resolve, reject) => {
if (!getNimExecPath()) {
return resolve([]);
}
var cwd = vscode.workspace.rootPath;
if (executors[project] && executors[project].initialized) {
let ps = executors[project].process;
executors[project] = { initialized: false, process: undefined };
let projectPath = toLocalFile(project);
if (executors[projectPath] && executors[projectPath].initialized) {
let ps = executors[projectPath].process;
executors[projectPath] = { initialized: false, process: undefined };
if (ps) {
ps.kill('SIGKILL');
}
} else {
executors[project] = { initialized: false, process: undefined };
executors[projectPath] = { initialized: false, process: undefined };
}
let executor = cp.spawn(getNimExecPath(), [command, ...args], { cwd: cwd });
executors[project].process = executor;
executors[project].initialized = true;
let executor = cp.spawn(getNimExecPath(), [command, ...args], { cwd: project.wsFolder.uri.fsPath });
executors[projectPath].process = executor;
executors[projectPath].initialized = true;
executor.on('error', (err) => {
if (err && (<any>err).code === 'ENOENT') {
vscode.window.showInformationMessage('No \'nim\' binary could be found in PATH: \'' + process.env['PATH'] + '\'');
Expand All @@ -51,7 +51,7 @@ function nimExec(project: string, command: string, args: string[], useStdErr: bo
if (signal === 'SIGKILL') {
reject([]);
} else {
executors[project] = { initialized: false, process: undefined };
executors[projectPath] = { initialized: false, process: undefined };
try {
let split = out.split(os.EOL);
if (split.length === 1) {
Expand Down Expand Up @@ -148,10 +148,11 @@ export function check(filename: string, nimConfig: vscode.WorkspaceConfiguration
}));
} else {
if (!isProjectMode()) {
runningToolsPromises.push(nimExec(getProjectFile(filename), 'check', ['--listFullPaths', getProjectFile(filename)], true, parseErrors));
let project = getProjectFileInfo(filename);
runningToolsPromises.push(nimExec(project, 'check', ['--listFullPaths', project.filePath], true, parseErrors));
} else {
getProjects().forEach(project => {
runningToolsPromises.push(nimExec(project, 'check', ['--listFullPaths', project], true, parseErrors));
runningToolsPromises.push(nimExec(project, 'check', ['--listFullPaths', project.filePath], true, parseErrors));
});
}
}
Expand Down
41 changes: 23 additions & 18 deletions src/nimSuggestExec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import cp = require('child_process');
import path = require('path');
import fs = require('fs');
import elrpc = require('./elrpc/elrpc');
import { prepareConfig, getProjectFile, isProjectMode, getNimExecPath, correctBinname } from './nimUtils';
import { prepareConfig, getProjectFileInfo, isProjectMode, getNimExecPath, correctBinname, ProjectFileInfo, toLocalFile } from './nimUtils';

class NimSuggestProcessDescription {
process?: cp.ChildProcess;
Expand Down Expand Up @@ -162,9 +162,13 @@ export function initNimSuggest(ctx: vscode.ExtensionContext) {
vscode.workspace.onDidChangeConfiguration(prepareConfig);
}

function trace(pid: number, projectFile: string, msg: any): void {
function trace(pid: number, projectFile: ProjectFileInfo | string, msg: any): void {
if (!!vscode.workspace.getConfiguration('nim').get('logNimsuggest')) {
console.log('[' + pid + ':' + projectFile + ']');
if (typeof projectFile === 'string') {
console.log('[' + pid + ':' + projectFile + ']');
} else {
console.log('[' + pid + ':' + projectFile.wsFolder.name + ':' + projectFile.wsFolder.uri.fsPath + ':' + projectFile.filePath + ']');
}
console.log(msg);
}
}
Expand All @@ -183,8 +187,8 @@ export async function execNimSuggest(suggestType: NimSuggestType, filename: stri
return [];
}

let projectFile = getProjectFileInfo(filename);
try {
let projectFile = getProjectFile(filename);
let normalizedFilename = filename.replace(/\\+/g, '/');
let desc = await getNimSuggestProcess(projectFile);
let suggestCmd = NimSuggestType[suggestType];
Expand All @@ -196,7 +200,7 @@ export async function execNimSuggest(suggestType: NimSuggestType, filename: stri
let ret = await desc.rpc.callMethod(suggestCmd, { kind: 'string', str: normalizedFilename }, { kind: 'number', n: line }, { kind: 'number', n: column }, { kind: 'string', str: dirtyFile as string });

if (desc.process) {
trace(desc.process.pid, projectFile + '=' + suggestCmd + ' ' + normalizedFilename, ret);
trace(desc.process.pid, toLocalFile(projectFile) + '=' + suggestCmd + ' ' + normalizedFilename, ret);
}

if (ret != null) {
Expand Down Expand Up @@ -224,7 +228,7 @@ export async function execNimSuggest(suggestType: NimSuggestType, filename: stri
}
} else if (ret === 'EPC Connection closed') {
console.error(ret);
await closeNimSuggestProcess(filename);
await closeNimSuggestProcess(projectFile);
} else {
var res = new NimSuggestResult();
res.suggest = '' + ret;
Expand All @@ -234,12 +238,12 @@ export async function execNimSuggest(suggestType: NimSuggestType, filename: stri
}
if (!isProjectMode() &&
vscode.window.visibleTextEditors.every((value, index, array) => { return value.document.uri.fsPath !== filename; })) {
await closeNimSuggestProcess(filename);
await closeNimSuggestProcess(projectFile);
}
return result;
} catch (e) {
console.error(e);
await closeNimSuggestProcess(filename);
await closeNimSuggestProcess(projectFile);
}
}

Expand All @@ -259,8 +263,8 @@ export async function closeAllNimSuggestProcesses(): Promise<void> {
nimSuggestProcessCache = {};
}

export async function closeNimSuggestProcess(filename: string): Promise<void> {
var file = getProjectFile(filename);
export async function closeNimSuggestProcess(project: ProjectFileInfo): Promise<void> {
var file = toLocalFile(project);
if (nimSuggestProcessCache[file]) {
let desc = await nimSuggestProcessCache[file];
if (desc) {
Expand All @@ -275,9 +279,10 @@ export async function closeNimSuggestProcess(filename: string): Promise<void> {
}
}

async function getNimSuggestProcess(nimProject: string): Promise<NimSuggestProcessDescription | undefined> {
if (!nimSuggestProcessCache[nimProject]) {
nimSuggestProcessCache[nimProject] = new Promise<NimSuggestProcessDescription>((resolve, reject) => {
async function getNimSuggestProcess(nimProject: ProjectFileInfo): Promise<NimSuggestProcessDescription | undefined> {
let projectPath = toLocalFile(nimProject);
if (!nimSuggestProcessCache[projectPath]) {
nimSuggestProcessCache[projectPath] = new Promise<NimSuggestProcessDescription>((resolve, reject) => {
let nimConfig = vscode.workspace.getConfiguration('nim');
var args = ['--epc', '--v2'];
if (!!nimConfig['logNimsuggest']) {
Expand All @@ -287,8 +292,8 @@ async function getNimSuggestProcess(nimProject: string): Promise<NimSuggestProce
args.push('--refresh:on');
}

args.push(nimProject);
let process = cp.spawn(getNimSuggestPath(), args, { cwd: vscode.workspace.rootPath });
args.push(nimProject.filePath);
let process = cp.spawn(getNimSuggestPath(), args, { cwd: nimProject.wsFolder.uri.fsPath });
process.stdout.once('data', (data) => {
let dataStr = data.toString();
let portNumber = parseInt(dataStr);
Expand All @@ -310,8 +315,8 @@ async function getNimSuggestProcess(nimProject: string): Promise<NimSuggestProce
if (code !== 0) {
console.error('nimsuggest closed with code: ' + code + ', signal: ' + signal);
}
if (nimSuggestProcessCache[nimProject]) {
(<Promise<NimSuggestProcessDescription>> nimSuggestProcessCache[nimProject]).then((desc) => {
if (nimSuggestProcessCache[projectPath]) {
(<Promise<NimSuggestProcessDescription>> nimSuggestProcessCache[projectPath]).then((desc) => {
if (desc && desc.rpc) {
desc.rpc.stop();
}
Expand All @@ -321,5 +326,5 @@ async function getNimSuggestProcess(nimProject: string): Promise<NimSuggestProce
});
});
}
return nimSuggestProcessCache[nimProject];
return nimSuggestProcessCache[projectPath];
}
69 changes: 54 additions & 15 deletions src/nimUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ import os = require('os');
import cp = require('child_process');
import vscode = require('vscode');

export interface ProjectFileInfo {
wsFolder: vscode.WorkspaceFolder;
filePath: string;
}

let _pathesCache: { [tool: string]: string; } = {};
var _projects: string[] = [];
var _projects: ProjectFileInfo[] = [];

export function getNimExecPath(): string {
let path = getBinPath('nim');
Expand Down Expand Up @@ -40,18 +45,50 @@ export function isWorkspaceFile(filePath: string): boolean {
}

/**
* Return filesystem file path.
* Return project info from file path.
*
* @param filePath relative or absolite file path
*/
export function toLocalFile(filePath: string): string {
if (!path.isAbsolute(filePath)) {
export function toProjectInfo(filePath: string): ProjectFileInfo {
if (path.isAbsolute(filePath)) {
let workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath));
if (workspaceFolder) {
return workspaceFolder.uri.with({path: workspaceFolder.uri.path + '/' + filePath}).fsPath;
return { wsFolder: workspaceFolder, filePath: vscode.workspace.asRelativePath(filePath, false) };
}
} else {
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
if (vscode.workspace.workspaceFolders.length === 1) {
return { wsFolder: vscode.workspace.workspaceFolders[0], filePath: filePath };
} else {
let parsedPath = filePath.split('/');
if (parsedPath.length > 1) {
for (const folder of vscode.workspace.workspaceFolders) {
if (parsedPath[0] === folder.name) {
return { wsFolder: folder, filePath: filePath.substr(parsedPath[0].length + 1) };
}
}
}
}
}
}
return filePath;
let parsedPath = path.parse(filePath);
return {
wsFolder: {
uri: vscode.Uri.file(parsedPath.dir),
name: 'root',
index: 0
},
filePath: parsedPath.base
};
}

/**
* Return project file in filesystem.
*
* @param project project file info
*/
export function toLocalFile(project: ProjectFileInfo): string {
return project.wsFolder.uri.with({path: project.wsFolder.uri.path + '/' + project.filePath}).fsPath;
}

/**
Expand All @@ -70,14 +107,12 @@ export function getNimPrettyExecPath(): string {
return _pathesCache[toolname];
}

export function getProjectFile(filename: string) {
filename = vscode.workspace.asRelativePath(filename);
export function getProjectFileInfo(filename: string): ProjectFileInfo {
if (!isProjectMode()) {
return filename;
return toProjectInfo(filename);
}
for (var i = 0; i < _projects.length; i++) {
let project = _projects[i];
if (filename.startsWith(path.dirname(project))) {
for (const project of _projects) {
if (filename.startsWith(path.dirname(toLocalFile(project)))) {
return project;
}
}
Expand All @@ -97,7 +132,7 @@ export function isProjectMode(): boolean {
return _projects.length > 0;
}

export function getProjects(): string[] {
export function getProjects(): ProjectFileInfo[] {
return _projects;
}

Expand All @@ -108,10 +143,14 @@ export function prepareConfig(): void {
if (projects) {
if (projects instanceof Array) {
projects.forEach((project) => {
_projects.push(toLocalFile(project));
_projects.push(toProjectInfo(project));
});
} else {
_projects.push(toLocalFile(projects));
vscode.workspace.findFiles(projects).then(result => {
if (result && result.length > 0) {
_projects.push(toProjectInfo(result[0].fsPath));
}
});
}
}
}
Expand Down

0 comments on commit 805d3f1

Please sign in to comment.