diff --git a/src/vs/code/electron-main/log.ts b/src/vs/code/common/log.ts similarity index 96% rename from src/vs/code/electron-main/log.ts rename to src/vs/code/common/log.ts index caa630d6ad2..c9908624211 100644 --- a/src/vs/code/electron-main/log.ts +++ b/src/vs/code/common/log.ts @@ -12,6 +12,7 @@ export const ILogService = createDecorator('logService'); export interface ILogService { _serviceBrand: any; + log(...args: any[]): void; } @@ -22,7 +23,7 @@ export class MainLogService implements ILogService { constructor( @IEnvironmentService private environmentService: IEnvironmentService) { } - log(...args: any[]): void { + public log(...args: any[]): void { if (this.environmentService.verbose) { console.log(`\x1b[93m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, ...args); } diff --git a/src/vs/code/common/windows.ts b/src/vs/code/common/windows.ts index 96ca219e07f..43c5fba2864 100644 --- a/src/vs/code/common/windows.ts +++ b/src/vs/code/common/windows.ts @@ -36,7 +36,6 @@ export interface IWindowEventService { } export class ActiveWindowManager implements IDisposable { - private disposables: IDisposable[] = []; private _activeWindowId: number; @@ -49,11 +48,11 @@ export class ActiveWindowManager implements IDisposable { this._activeWindowId = windowId; } - get activeClientId(): string { + public get activeClientId(): string { return `window:${this._activeWindowId}`; } - dispose() { + public dispose() { this.disposables = dispose(this.disposables); } } \ No newline at end of file diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index f15971a75de..435423de2c2 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -14,7 +14,7 @@ import { WindowsChannel } from 'vs/platform/windows/common/windowsIpc'; import { WindowsService } from 'vs/platform/windows/electron-main/windowsService'; import { ILifecycleService } from 'vs/code/electron-main/lifecycle'; import { VSCodeMenu } from 'vs/code/electron-main/menus'; -import { getShellEnvironment } from 'vs/code/electron-main/shellEnv'; +import { getShellEnvironment } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; import { UpdateChannel } from 'vs/platform/update/common/updateIpc'; import { UpdateService } from 'vs/platform/update/electron-main/updateService'; @@ -26,8 +26,8 @@ import { LaunchService, LaunchChannel, ILaunchService } from './launch'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { ILogService } from 'vs/code/electron-main/log'; -import { IStorageService } from 'vs/code/electron-main/storage'; +import { ILogService } from 'vs/code/common/log'; +import { IStorageService } from 'vs/code/node/storage'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { BackupChannel } from 'vs/platform/backup/common/backupIpc'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -146,8 +146,7 @@ export class VSCodeApplication { // Spawn shared process this.sharedProcess = new SharedProcess(this.environmentService, this.userEnv); this.toDispose.push(this.sharedProcess); - this.sharedProcessClient = this.sharedProcess.whenReady() - .then(() => connect(this.environmentService.sharedIPCHandle, 'main')); + this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main')); // Services const appInstantiationService = this.initServices(); diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index e69f31b9363..c8a6347a9de 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -10,7 +10,7 @@ import { IWindowsMainService } from 'vs/code/electron-main/windows'; import { VSCodeWindow } from 'vs/code/electron-main/window'; import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { ILogService } from 'vs/code/electron-main/log'; +import { ILogService } from 'vs/code/common/log'; import { IURLService } from 'vs/platform/url/common/url'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; @@ -41,7 +41,7 @@ export class LaunchChannel implements ILaunchChannel { constructor(private service: ILaunchService) { } - call(command: string, arg: any): TPromise { + public call(command: string, arg: any): TPromise { switch (command) { case 'start': const { args, userEnv } = arg as IStartArguments; @@ -50,6 +50,7 @@ export class LaunchChannel implements ILaunchChannel { case 'get-main-process-id': return this.service.getMainProcessId(); } + return undefined; } } @@ -60,11 +61,11 @@ export class LaunchChannelClient implements ILaunchService { constructor(private channel: ILaunchChannel) { } - start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise { + public start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise { return this.channel.call('start', { args, userEnv }); } - getMainProcessId(): TPromise { + public getMainProcessId(): TPromise { return this.channel.call('get-main-process-id', null); } } @@ -79,19 +80,20 @@ export class LaunchService implements ILaunchService { @IURLService private urlService: IURLService ) { } - start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise { + public start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise { this.logService.log('Received data from other instance: ', args, userEnv); + // Check early for open-url which is handled in URL service const openUrlArg = args['open-url'] || []; const openUrl = typeof openUrlArg === 'string' ? [openUrlArg] : openUrlArg; - const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; - if (openUrl.length > 0) { openUrl.forEach(url => this.urlService.open(url)); + return TPromise.as(null); } // Otherwise handle in windows service + const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; let usedWindows: VSCodeWindow[]; if (!!args.extensionDevelopmentPath) { this.windowsService.openExtensionDevelopmentHostWindow({ context, cli: args, userEnv }); @@ -129,8 +131,9 @@ export class LaunchService implements ILaunchService { return TPromise.as(null); } - getMainProcessId(): TPromise { + public getMainProcessId(): TPromise { this.logService.log('Received request for process ID from other instance.'); + return TPromise.as(process.pid); } } \ No newline at end of file diff --git a/src/vs/code/electron-main/lifecycle.ts b/src/vs/code/electron-main/lifecycle.ts index 895f8b05684..fbeb9a85472 100644 --- a/src/vs/code/electron-main/lifecycle.ts +++ b/src/vs/code/electron-main/lifecycle.ts @@ -9,8 +9,8 @@ import { ipcMain as ipc, app } from 'electron'; import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; import { ReadyState, VSCodeWindow } from 'vs/code/electron-main/window'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ILogService } from 'vs/code/electron-main/log'; -import { IStorageService } from 'vs/code/electron-main/storage'; +import { ILogService } from 'vs/code/common/log'; +import { IStorageService } from 'vs/code/node/storage'; import Event, { Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 8294cc1f22b..41bb32a7c01 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -10,7 +10,7 @@ import { assign } from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import { parseMainProcessArgv } from 'vs/platform/environment/node/argv'; import { mkdirp } from 'vs/base/node/pfs'; -import { validatePaths } from 'vs/code/electron-main/paths'; +import { validatePaths } from 'vs/code/node/paths'; import { LifecycleService, ILifecycleService } from 'vs/code/electron-main/lifecycle'; import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -19,8 +19,8 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { ILogService, MainLogService } from 'vs/code/electron-main/log'; -import { IStorageService, StorageService } from 'vs/code/electron-main/storage'; +import { ILogService, MainLogService } from 'vs/code/common/log'; +import { IStorageService, StorageService } from 'vs/code/node/storage'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index fe14d6cf223..f267b326372 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -14,7 +14,7 @@ import { OpenContext } from 'vs/code/common/windows'; import { IWindowsMainService } from 'vs/code/electron-main/windows'; import { VSCodeWindow } from 'vs/code/electron-main/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IStorageService } from 'vs/code/electron-main/storage'; +import { IStorageService } from 'vs/code/node/storage'; import { IFilesConfiguration, AutoSaveConfiguration } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index c70ce1239f6..5004700f7eb 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -14,6 +14,8 @@ import { PromiseSource } from 'vs/base/common/async'; export class SharedProcess { + private spawnPromiseSource: PromiseSource; + private window: Electron.BrowserWindow; private disposables: IDisposable[] = []; @@ -41,6 +43,7 @@ export class SharedProcess { this.disposables.push(toDisposable(() => this.window.removeListener('close', onClose))); this.disposables.push(toDisposable(() => { + // Electron seems to crash on Windows without this setTimeout :| setTimeout(() => { try { @@ -65,8 +68,6 @@ export class SharedProcess { }); } - private spawnPromiseSource: PromiseSource; - constructor( private environmentService: IEnvironmentService, private userEnv: IProcessEnvironment @@ -74,15 +75,15 @@ export class SharedProcess { this.spawnPromiseSource = new PromiseSource(); } - spawn(): void { + public spawn(): void { this.spawnPromiseSource.complete(); } - whenReady(): TPromise { + public whenReady(): TPromise { return this.spawnPromiseSource.value.then(() => this._whenReady); } - toggle(): void { + public toggle(): void { if (this.window.isVisible()) { this.hide(); } else { @@ -90,17 +91,17 @@ export class SharedProcess { } } - show(): void { + public show(): void { this.window.show(); this.window.webContents.openDevTools(); } - hide(): void { + public hide(): void { this.window.webContents.closeDevTools(); this.window.hide(); } - dispose(): void { + public dispose(): void { this.disposables = dispose(this.disposables); } } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 9d40c049ad7..58f27e2a355 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -9,11 +9,11 @@ import * as path from 'path'; import * as objects from 'vs/base/common/objects'; import { stopProfiling } from 'vs/base/node/profiler'; import nls = require('vs/nls'); -import { IStorageService } from 'vs/code/electron-main/storage'; +import { IStorageService } from 'vs/code/node/storage'; import { shell, screen, BrowserWindow, systemPreferences, app } from 'electron'; import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; -import { ILogService } from 'vs/code/electron-main/log'; +import { ILogService } from 'vs/code/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { parseArgs } from 'vs/platform/environment/node/argv'; @@ -78,9 +78,6 @@ export interface IWindowConfiguration extends ParsedArgs { userEnv: IProcessEnvironment; - /** - * The physical keyboard is of ISO type (on OSX). - */ isISOKeyboard?: boolean; zoomLevel?: number; @@ -128,12 +125,6 @@ export enum ReadyState { READY } -interface IConfiguration { - window: { - menuBarVisibility: MenuBarVisibility; - }; -} - export class VSCodeWindow { public static themeStorageKey = 'theme'; @@ -153,7 +144,6 @@ export class VSCodeWindow { private _isExtensionTestHost: boolean; private windowState: IWindowState; private currentMenuBarVisibility: MenuBarVisibility; - private currentWindowMode: WindowMode; private toDispose: IDisposable[]; private representedFilename: string; @@ -177,11 +167,27 @@ export class VSCodeWindow { this.whenReadyCallbacks = []; this.toDispose = []; + // create browser window + this.createBrowserWindow(config); + + // respect configured menu bar visibility + this.onConfigurationUpdated(); + + // TODO@joao: hook this up to some initialization routine this causes a race between setting the headers and doing + // a request that needs them. chances are low + this.setCommonHTTPHeaders(); + + // Eventing + this.registerListeners(); + } + + private createBrowserWindow(config: IWindowCreationOptions): void { + // Load window state - this.restoreWindowState(config.state); + this.windowState = this.restoreWindowState(config.state); // in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below) - const isFullscreenOrMaximized = (this.currentWindowMode === WindowMode.Maximized || this.currentWindowMode === WindowMode.Fullscreen); + const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen); const options: Electron.BrowserWindowOptions = { width: this.windowState.width, @@ -248,7 +254,7 @@ export class VSCodeWindow { if (isFullscreenOrMaximized) { this._win.maximize(); - if (this.currentWindowMode === WindowMode.Fullscreen) { + if (this.windowState.mode === WindowMode.Fullscreen) { this._win.setFullScreen(true); } @@ -258,16 +264,6 @@ export class VSCodeWindow { } this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too - - // respect configured menu bar visibility - this.onConfigurationUpdated(); - - // TODO@joao: hook this up to some initialization routine this causes a race between setting the headers and doing - // a request that needs them. chances are low - this.setCommonHTTPHeaders(); - - // Eventing - this.registerListeners(); } private setCommonHTTPHeaders(): void { @@ -376,20 +372,6 @@ export class VSCodeWindow { return this._readyState; } - private registerNavigationListenerOn(command: 'swipe' | 'app-command', back: 'left' | 'browser-backward', forward: 'right' | 'browser-forward', acrossEditors: boolean) { - this._win.on(command, (e, cmd) => { - if (this.readyState !== ReadyState.READY) { - return; // window must be ready - } - - if (cmd === back) { - this.send('vscode:runAction', acrossEditors ? 'workbench.action.openPreviousRecentlyUsedEditor' : 'workbench.action.navigateBack'); - } else if (cmd === forward) { - this.send('vscode:runAction', acrossEditors ? 'workbench.action.openNextRecentlyUsedEditor' : 'workbench.action.navigateForward'); - } - }); - } - private registerListeners(): void { // Remember that we loaded @@ -405,7 +387,7 @@ export class VSCodeWindow { // To prevent flashing, we set the window visible after the page has finished to load but before VSCode is loaded if (!this._win.isVisible()) { - if (this.currentWindowMode === WindowMode.Maximized) { + if (this.windowState.mode === WindowMode.Maximized) { this._win.maximize(); } @@ -487,6 +469,20 @@ export class VSCodeWindow { } }; + private registerNavigationListenerOn(command: 'swipe' | 'app-command', back: 'left' | 'browser-backward', forward: 'right' | 'browser-forward', acrossEditors: boolean) { + this._win.on(command, (e, cmd) => { + if (this.readyState !== ReadyState.READY) { + return; // window must be ready + } + + if (cmd === back) { + this.send('vscode:runAction', acrossEditors ? 'workbench.action.openPreviousRecentlyUsedEditor' : 'workbench.action.navigateBack'); + } else if (cmd === forward) { + this.send('vscode:runAction', acrossEditors ? 'workbench.action.openNextRecentlyUsedEditor' : 'workbench.action.navigateForward'); + } + }); + } + public load(config: IWindowConfiguration): void { // If this is the first time the window is loaded, we associate the paths @@ -527,8 +523,7 @@ export class VSCodeWindow { // (--prof-startup) save profile to disk const { profileStartup } = this.environmentService; if (profileStartup) { - stopProfiling(profileStartup.dir, profileStartup.prefix) - .done(undefined, err => console.error(err)); + stopProfiling(profileStartup.dir, profileStartup.prefix).done(undefined, err => console.error(err)); } } @@ -556,7 +551,6 @@ export class VSCodeWindow { } private getUrl(windowConfiguration: IWindowConfiguration): string { - let url = require.toUrl('vs/workbench/electron-browser/bootstrap/index.html'); // Set zoomlevel const windowConfig = this.configurationService.getConfiguration('window'); @@ -593,16 +587,16 @@ export class VSCodeWindow { } } - url += '?config=' + encodeURIComponent(JSON.stringify(config)); - - return url; + return `${require.toUrl('vs/workbench/electron-browser/bootstrap/index.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; } private getBaseTheme(): string { if (isWindows && systemPreferences.isInvertedColorScheme()) { return 'hc-black'; } + const theme = this.storageService.getItem(VSCodeWindow.themeStorageKey, 'vs-dark'); + return theme.split(' ')[0]; } @@ -611,9 +605,10 @@ export class VSCodeWindow { return '#000000'; } - let background = this.storageService.getItem(VSCodeWindow.themeBackgroundStorageKey, null); + const background = this.storageService.getItem(VSCodeWindow.themeBackgroundStorageKey, null); if (!background) { - let baseTheme = this.getBaseTheme(); + const baseTheme = this.getBaseTheme(); + return baseTheme === 'hc-black' ? '#000000' : (baseTheme === 'vs' ? '#FFFFFF' : (isMacintosh ? '#171717' : '#1E1E1E')); // https://github.com/electron/electron/issues/5150 } @@ -668,7 +663,7 @@ export class VSCodeWindow { return state; } - private restoreWindowState(state?: IWindowState): void { + private restoreWindowState(state?: IWindowState): IWindowState { if (state) { try { state = this.validateWindowState(state); @@ -681,8 +676,7 @@ export class VSCodeWindow { state = defaultWindowState(); } - this.windowState = state; - this.currentWindowMode = this.windowState.mode; + return state; } private validateWindowState(state: IWindowState): IWindowState { diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index cc0800f25e6..75b6792e95d 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -15,13 +15,13 @@ import { assign, mixin } from 'vs/base/common/objects'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { trim } from 'vs/base/common/strings'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; -import { IStorageService } from 'vs/code/electron-main/storage'; +import { IStorageService } from 'vs/code/node/storage'; import { IPath, VSCodeWindow, IWindowConfiguration, IWindowState as ISingleWindowState, defaultWindowState, WindowMode } from 'vs/code/electron-main/window'; import { ipcMain as ipc, app, screen, BrowserWindow, dialog } from 'electron'; -import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/electron-main/paths'; +import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths'; import { ILifecycleService, UnloadReason } from 'vs/code/electron-main/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ILogService } from 'vs/code/electron-main/log'; +import { ILogService } from 'vs/code/common/log'; import { getPathLabel } from 'vs/base/common/labels'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWindowSettings } from 'vs/platform/windows/common/windows'; diff --git a/src/vs/code/electron-main/paths.ts b/src/vs/code/node/paths.ts similarity index 100% rename from src/vs/code/electron-main/paths.ts rename to src/vs/code/node/paths.ts diff --git a/src/vs/code/electron-main/shellEnv.ts b/src/vs/code/node/shellEnv.ts similarity index 100% rename from src/vs/code/electron-main/shellEnv.ts rename to src/vs/code/node/shellEnv.ts index 2afa773a341..92c146fefae 100644 --- a/src/vs/code/electron-main/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -11,7 +11,6 @@ import { generateUuid } from 'vs/base/common/uuid'; import { TPromise } from 'vs/base/common/winjs.base'; import { isWindows } from 'vs/base/common/platform'; - function getUnixShellEnvironment(): TPromise { const promise = new TPromise((c, e) => { const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; @@ -88,5 +87,6 @@ export function getShellEnvironment(): TPromise { _shellEnv = getUnixShellEnvironment(); } } + return _shellEnv; } diff --git a/src/vs/code/electron-main/storage.ts b/src/vs/code/node/storage.ts similarity index 94% rename from src/vs/code/electron-main/storage.ts rename to src/vs/code/node/storage.ts index d3f1351b6cc..438a7af5b8d 100644 --- a/src/vs/code/electron-main/storage.ts +++ b/src/vs/code/node/storage.ts @@ -30,7 +30,7 @@ export class StorageService implements IStorageService { this.dbPath = path.join(environmentService.userDataPath, 'storage.json'); } - getItem(key: string, defaultValue?: T): T { + public getItem(key: string, defaultValue?: T): T { if (!this.database) { this.database = this.load(); } @@ -43,7 +43,7 @@ export class StorageService implements IStorageService { return this.database[key]; } - setItem(key: string, data: any): void { + public setItem(key: string, data: any): void { if (!this.database) { this.database = this.load(); } @@ -59,7 +59,7 @@ export class StorageService implements IStorageService { this.save(); } - removeItem(key: string): void { + public removeItem(key: string): void { if (!this.database) { this.database = this.load(); } diff --git a/src/vs/code/node/windowsUtils.ts b/src/vs/code/node/windowsUtils.ts index 31a4f00b354..a46c1d96168 100644 --- a/src/vs/code/node/windowsUtils.ts +++ b/src/vs/code/node/windowsUtils.ts @@ -43,6 +43,7 @@ export function findBestWindowOrFolder({ win } else if (bestFolder) { return bestFolder; } + return !newWindow ? getLastActiveWindow(windows) : null; } @@ -51,6 +52,7 @@ function findBestWindow(windows: WINDOW[], filePat if (containers.length) { return containers.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0]; } + return null; } @@ -60,6 +62,7 @@ function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: stri if (!platform.isLinux) { homeFolder = homeFolder && homeFolder.toLowerCase(); } + let previous = null; try { while (folder !== previous) { @@ -72,22 +75,23 @@ function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: stri } catch (err) { // assume impossible to access } + return null; } function isProjectFolder(folder: string, normalizedUserHome?: string, vscodeFolder = '.vscode') { try { if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) { - // ~/.vscode/extensions is used for extensions - return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile(); - } else { - return fs.statSync(path.join(folder, vscodeFolder)).isDirectory(); + return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions } + + return fs.statSync(path.join(folder, vscodeFolder)).isDirectory(); } catch (err) { if (!(err && err.code === 'ENOENT')) { throw err; } } + return false; }