From 4fe434707fba8d8be7a4805a433895f5ef870b5e Mon Sep 17 00:00:00 2001 From: Michel Nemnom Date: Thu, 22 Mar 2018 17:04:34 +0100 Subject: [PATCH] Search and use the nearest usable flow binary. fixes #7 --- .gitignore | 2 +- .vscode/settings.json | 6 ++- FlowType.sublime-settings | 6 ++- README.md | 1 + flowtype/commands/autocomplete.py | 5 ++- flowtype/commands/base.py | 7 +++- flowtype/commands/check_contents.py | 5 ++- flowtype/commands/coverage.py | 5 ++- flowtype/commands/goto_definition.py | 5 ++- flowtype/commands/suggest_annotations.py | 5 ++- flowtype/commands/view_errors.py | 5 ++- flowtype/commands/view_type.py | 5 ++- flowtype/helpers.py | 49 ++++++++++++++++++------ messages.json | 3 +- messages/1.1.0.txt | 8 ++++ 15 files changed, 85 insertions(+), 32 deletions(-) create mode 100644 messages/1.1.0.txt diff --git a/.gitignore b/.gitignore index 17338f2..c753a5f 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,4 @@ ENV/ .ropeproject # Fixtures node_modules -node_modules \ No newline at end of file +node_modules diff --git a/.vscode/settings.json b/.vscode/settings.json index 0b6b3ab..45be54b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -148,5 +148,9 @@ ".ropeproject": true, "# Fixtures node_modules": true, "node_modules": true - } + }, + "python.pythonPath": "/home/pegase/.pyenv/versions/2.7/bin/python", + "python.linting.pylintEnabled": true, + "python.linting.flake8Enabled": false, + "python.linting.enabled": true } \ No newline at end of file diff --git a/FlowType.sublime-settings b/FlowType.sublime-settings index 4d07d98..d3734e3 100644 --- a/FlowType.sublime-settings +++ b/FlowType.sublime-settings @@ -9,7 +9,9 @@ "log_level": "info", // Path to flow binary - "flow_bin_path": "/usr/bin/flow", + // If not mentioned it will search for a flow binary executable + // steps: local -> system + "flow_bin_path": "", // Allow completions of Flow built-in types "complete_with_builtintypes": true, @@ -22,4 +24,4 @@ // Check contents for Flow errors on save "check_contents_on_save": false -} \ No newline at end of file +} diff --git a/README.md b/README.md index 7c865ee..210c6bd 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![GitHub (pre-)release](https://img.shields.io/github/release/Pegase745/sublime-flowtype/all.svg)](https://github.com/Pegase745/sublime-flowtype/releases) [![Build Status](https://travis-ci.org/Pegase745/sublime-flowtype.svg?branch=master)](https://travis-ci.org/Pegase745/sublime-flowtype) [![Build status](https://ci.appveyor.com/api/projects/status/jofwwwr30ub7f8r2/branch/master?svg=true)](https://ci.appveyor.com/project/Pegase745/sublime-flowtype) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9433d6745ed54193bb6d2204ee7c6172)](https://www.codacy.com/app/Pegase745/sublime-flowtype?utm_source=github.com&utm_medium=referral&utm_content=Pegase745/sublime-flowtype&utm_campaign=Badge_Grade) [![Package Control](https://img.shields.io/packagecontrol/dt/FlowType.svg)](https://packagecontrol.io/packages/FlowType) diff --git a/flowtype/commands/autocomplete.py b/flowtype/commands/autocomplete.py index dc052a0..55ca47c 100644 --- a/flowtype/commands/autocomplete.py +++ b/flowtype/commands/autocomplete.py @@ -1,7 +1,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments, get_settings +from ..helpers import prepare_arguments, get_settings from ..listeners.builtintypes import print_type_format from ..listeners import FLOW_SUGGESTIONS @@ -33,7 +33,8 @@ class FlowtypeAutocomplete(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('autocomplete %s' % e) return diff --git a/flowtype/commands/base.py b/flowtype/commands/base.py index 79e94e8..ecd6221 100644 --- a/flowtype/commands/base.py +++ b/flowtype/commands/base.py @@ -1,7 +1,7 @@ import sublime import sublime_plugin -from ..helpers import is_js_source, find_in_parent_folders +from ..helpers import is_js_source, find_in_parent_folders, get_flow_bin class BaseCommand(sublime_plugin.TextCommand): @@ -16,6 +16,11 @@ def get_project_root(self): file_path = self.active_window.extract_variables()['file_path'] return find_in_parent_folders('.flowconfig', file_path) + def get_flow_bin(self): + """Return the flow binary to use.""" + file_path = self.active_window.extract_variables()['file_path'] + return get_flow_bin(file_path) + def get_content(self): """Return file content.""" return self.view.substr(sublime.Region(0, self.view.size())) diff --git a/flowtype/commands/check_contents.py b/flowtype/commands/check_contents.py index 195822b..6362165 100644 --- a/flowtype/commands/check_contents.py +++ b/flowtype/commands/check_contents.py @@ -4,7 +4,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments, FLOWTYPE +from ..helpers import prepare_arguments, FLOWTYPE logger = Logger() @@ -15,7 +15,8 @@ class FlowtypeCheckContents(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('check_contents %s' % e) return diff --git a/flowtype/commands/coverage.py b/flowtype/commands/coverage.py index 4a3f06f..d376394 100644 --- a/flowtype/commands/coverage.py +++ b/flowtype/commands/coverage.py @@ -3,7 +3,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments +from ..helpers import prepare_arguments logger = Logger() @@ -14,7 +14,8 @@ class FlowtypeCoverage(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('coverage %s' % e) return diff --git a/flowtype/commands/goto_definition.py b/flowtype/commands/goto_definition.py index 92489a7..1df38de 100644 --- a/flowtype/commands/goto_definition.py +++ b/flowtype/commands/goto_definition.py @@ -3,7 +3,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments +from ..helpers import prepare_arguments logger = Logger() @@ -14,7 +14,8 @@ class FlowtypeGotoDefinition(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('get_def %s' % e) return diff --git a/flowtype/commands/suggest_annotations.py b/flowtype/commands/suggest_annotations.py index 0346a61..7ef7402 100644 --- a/flowtype/commands/suggest_annotations.py +++ b/flowtype/commands/suggest_annotations.py @@ -1,7 +1,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments, apply_patch +from ..helpers import prepare_arguments, apply_patch logger = Logger() @@ -12,7 +12,8 @@ class FlowtypeSuggestAnnotations(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('suggest %s' % e) return diff --git a/flowtype/commands/view_errors.py b/flowtype/commands/view_errors.py index 3456f32..0239b09 100644 --- a/flowtype/commands/view_errors.py +++ b/flowtype/commands/view_errors.py @@ -3,7 +3,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments +from ..helpers import prepare_arguments logger = Logger() @@ -14,7 +14,8 @@ class FlowtypeViewErrors(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('check_contents %s' % e) return diff --git a/flowtype/commands/view_type.py b/flowtype/commands/view_type.py index d4e1a53..027821b 100644 --- a/flowtype/commands/view_type.py +++ b/flowtype/commands/view_type.py @@ -1,7 +1,7 @@ from .base import BaseCommand from .exec_flow import ExecFlowCommand from ..logger import Logger -from ..helpers import get_flow_bin, prepare_arguments +from ..helpers import prepare_arguments logger = Logger() @@ -12,7 +12,8 @@ class FlowtypeViewType(BaseCommand): def get_cmd(self): """Construct cli command.""" try: - flow_bin = get_flow_bin() + flow_bin = self.get_flow_bin() + logger.logger.debug('using flow-bin %s' % flow_bin) except ValueError as e: logger.logger.error('type-at-pos %s' % e) return diff --git a/flowtype/helpers.py b/flowtype/helpers.py index 2536204..8b70ebd 100644 --- a/flowtype/helpers.py +++ b/flowtype/helpers.py @@ -45,16 +45,6 @@ def get_settings(setting, default=None): return settings.get(setting, default) -def get_flow_bin(): - """Return the full path for the Flow binary.""" - flow_bin = get_settings('flow_bin_path', None) - - if not flow_bin: - raise ValueError('Path value is missing for flow_bin_path setting') - - return flow_bin - - def prepare_arguments(view): """Prepare arguments to be sent to the Flow binary.""" file_name = view.file_name() @@ -103,19 +93,54 @@ def find_in_parent_folders(file_name, current_dir): file_list = os.listdir(current_dir) parent_dir = os.path.dirname(current_dir) if file_name in file_list: - file_path = "%s/%s" % (current_dir, file_name) + file_path = current_dir break else: if current_dir == parent_dir: raise ValueError( "No %s was found in any parent folder" % file_name) - break else: current_dir = parent_dir return file_path +def find_executable(name, file_path): + """ + Return the path of an executable + :param name: name of the executable we're searching for + """ + result = None + paths = list(filter(None, list(reversed(os.defpath.split(os.pathsep))))) + node_module_path = find_in_parent_folders("package.json", file_path) + + paths.insert(0, "%s/node_modules/.bin" % (node_module_path)) + + for outerpath in paths: + for innerpath, _, _ in os.walk(outerpath): + path = os.path.join(innerpath, name) + if os.access(path, os.X_OK): + result = os.path.normpath(path) + break + else: + continue + break + + return result + + +def get_flow_bin(file_path): + """Return the full path for the Flow binary.""" + flow_bin = get_settings('flow_bin_path', None) + + if not flow_bin: + flow_bin = find_executable("flow", file_path) + if not flow_bin: + raise ValueError('Path value is missing for flow_bin_path setting') + + return flow_bin + + _hdr_pat = re.compile("^@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@$") diff --git a/messages.json b/messages.json index 091fcf6..b66d9b7 100644 --- a/messages.json +++ b/messages.json @@ -3,5 +3,6 @@ "1.0.2": "messages/1.0.2.txt", "1.0.3": "messages/1.0.3.txt", "1.0.4": "messages/1.0.4.txt", - "1.0.5": "messages/1.0.5.txt" + "1.0.5": "messages/1.0.5.txt", + "1.1.0": "messages/1.1.0.txt" } diff --git a/messages/1.1.0.txt b/messages/1.1.0.txt new file mode 100644 index 0000000..c62f77a --- /dev/null +++ b/messages/1.1.0.txt @@ -0,0 +1,8 @@ +FlowType 1.1.0 +============== + +## Changed + * Search and use the nearest usable flow binary. + The value of "flow_bin_path" in the settings is now optional. + If it's set, it will be used. If not, the plugin will search for a local project's flow binary, + or else use the system global one in your PATH.