Skip to content
This repository has been archived by the owner on Dec 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #53 from orta/master
Browse files Browse the repository at this point in the history
Support automatically checking for the node_modules version of Flow
  • Loading branch information
gabelevi authored Dec 6, 2016
2 parents 8d39b5c + a529b32 commit dceceae
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 16 deletions.
8 changes: 8 additions & 0 deletions lib/flowMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {DeclarationSupport} from './flowDeclaration';
import {setupDiagnostics} from './flowDiagnostics';

import {checkNode, checkFlow, isFlowEnabled} from './utils'
import {clearWorkspaceCaches} from './pkg/flow-base/lib/FlowHelpers'

import {setupLogging} from "./flowLogging"

type Context = {
Expand All @@ -36,9 +38,11 @@ export function activate(context: Context): void {
return
}
global.vscode = vscode

setupLogging()
checkNode()
checkFlow()

// Language features
languages.forEach(lang => {
context.subscriptions.push(vscode.languages.registerHoverProvider(lang, new HoverSupport));
Expand All @@ -50,3 +54,7 @@ export function activate(context: Context): void {
// Diagnostics
setupDiagnostics(context.subscriptions);
}

vscode.workspace.onDidChangeConfiguration(params => {
clearWorkspaceCaches();
});
48 changes: 42 additions & 6 deletions lib/pkg/flow-base/lib/FlowHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,14 @@ function isOptional(param: string): boolean {
return lastChar === '?';
}

function clearWorkspaceCaches() {
flowPathCache.reset();
flowConfigDirCache.reset();
global.cachedPathToFlowBin = undefined;
}

async function isFlowInstalled(): Promise<boolean> {
const flowPath = getPathToFlow();
const flowPath = await getPathToFlow();
if (!flowPathCache.has(flowPath)) {
flowPathCache.set(flowPath, await canFindFlow(flowPath));
}
Expand All @@ -144,12 +150,41 @@ async function canFindFlow(flowPath: string): Promise<boolean> {
}

/**
* @return The path to Flow on the user's machine. It is recommended not to cache the result of this
* function in case the user updates his or her preferences in Atom, in which case the return
* value will be stale.
* @return The path to Flow on the user's machine. First using the the user's
* config, then looking into the node_modules for the project.
*
* It is cached, so it is expected that changing the users settings will
* trigger a call to `clearWorkspaceCaches`.
*/

async function getPathToFlow(): Promise<string> {
if (global.cachedPathToFlowBin) { return global.cachedPathToFlowBin }

const config = global.vscode.workspace.getConfiguration('flow');
const shouldUseNodeModule = config.get('useNPMPackagedFlow');

if (shouldUseNodeModule && await canFindFlow(nodeModuleFlowLocation())){
global.cachedPathToFlowBin = nodeModuleFlowLocation();
return global.cachedPathToFlowBin
}

const userPath = config.get('pathToFlow');
if (await canFindFlow(userPath)) {
global.cachedPathToFlowBin = userPath
return global.cachedPathToFlowBin
}

// Final fallback, mainly so we complete the promise<string> implmentation
return "flow"
}

/**
* @returnThe potential path to Flow on the user's machine if they are using NPM/Yarn to manage
* their installs of flow.
*/
function getPathToFlow(): string {
return global.vscode.workspace.getConfiguration('flow').get('pathToFlow')
function nodeModuleFlowLocation(): string {
const flowBin = process.platform === 'win32' ? 'flow.cmd' : 'flow'
return `${global.vscode.workspace.rootPath}/node_modules/.bin/${flowBin}`
}

function getStopFlowOnExit(): boolean {
Expand Down Expand Up @@ -192,4 +227,5 @@ module.exports = {
processAutocompleteItem,
groupParamNames,
flowCoordsToAtomCoords,
clearWorkspaceCaches
};
7 changes: 4 additions & 3 deletions lib/pkg/flow-base/lib/FlowProcess.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ export class FlowProcess {
// don't want to log because it just means the server is busy and we don't want to wait.
if (!couldRetry && !suppressErrors) {
// not sure what happened, but we'll let the caller deal with it
logger.error(`Flow failed: flow ${args.join(' ')}. Error: ${JSON.stringify(e)}`);
const pathToFlow = await getPathToFlow();
logger.error(`Flow failed: ${pathToFlow} ${args.join(' ')}. Error: ${JSON.stringify(e)}`);
}
throw e;
}
Expand All @@ -153,7 +154,7 @@ export class FlowProcess {

/** Starts a Flow server in the current root */
async _startFlowServer(): Promise<void> {
const pathToFlow = getPathToFlow();
const pathToFlow = await getPathToFlow();
// `flow server` will start a server in the foreground. asyncExecute
// will not resolve the promise until the process exits, which in this
// case is never. We need to use spawn directly to get access to the
Expand Down Expand Up @@ -342,7 +343,7 @@ export class FlowProcess {
...args,
'--from', 'nuclide',
];
const pathToFlow = getPathToFlow();
const pathToFlow = await getPathToFlow();
const ret = await asyncExecute(pathToFlow, args, options);
if (ret.exitCode !== 0) {
// TODO: bubble up the exit code via return value instead
Expand Down
10 changes: 4 additions & 6 deletions lib/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

import spawn from 'cross-spawn';
import {window, workspace} from 'vscode'
import {getPathToFlow} from "../pkg/flow-base/lib/FlowHelpers"

const NODE_NOT_FOUND = '[Flow] Cannot find node in PATH. The simpliest way to resolve it is install node globally'
const FLOW_NOT_FOUND = '[Flow] Cannot find flow in PATH. Try to install it by npm install flow-bin -g'

function getPathToFlow(): string {
return workspace.getConfiguration('flow').get('pathToFlow')
}

export function isFlowEnabled() {
return workspace.getConfiguration('flow').get('enabled')
}
Expand All @@ -36,9 +33,10 @@ export function checkNode() {
}
}

export function checkFlow() {
export async function checkFlow() {
const path = await getPathToFlow()
try {
const check = spawn(process.platform === 'win32' ? 'where' : 'which', [getPathToFlow()])
const check = spawn(process.platform === 'win32' ? 'where' : 'which', [path])
let
flowOutput = "",
flowOutputError = ""
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
"type": "boolean",
"default": true,
"description": "Stop Flow on Exit"
},
"flow.useNPMPackagedFlow": {
"type": "boolean",
"default": false,
"description": "Support using flow through your node_modules folder, WARNING: Checking this box is a security risk. When you open a project we will immediately run code contained within it."
}
}
}
Expand Down Expand Up @@ -77,4 +82,4 @@
"bugs": {
"url": "https://github.com/flowtype/flow-for-vscode/issues"
}
}
}

0 comments on commit dceceae

Please sign in to comment.