示例#1
0
    def Start(self, configuration=None):
        self._configuration = None
        self._adapter = None

        launch_config_file = utils.PathToConfigFile('.vimspector.json')

        if not launch_config_file:
            utils.UserMessage(
                'Unable to find .vimspector.json. You need to tell '
                'vimspector how to launch your application')
            return

        with open(launch_config_file, 'r') as f:
            database = json.load(f)

        launch_config = database.get('configurations')
        adapters = database.get('adapters')

        if not configuration:
            if len(launch_config) == 1:
                configuration = next(iter(launch_config.keys()))
            else:
                configuration = utils.SelectFromList(
                    'Which launch configuration?', list(launch_config.keys()))

        if not configuration:
            return

        utils.ExpandReferencesInDict(
            launch_config[configuration],
            {'workspaceRoot': os.path.dirname(launch_config_file)})

        adapter = launch_config[configuration].get('adapter')
        if isinstance(adapter, str):
            adapter = adapters.get(adapter)
            utils.ExpandReferencesInDict(
                adapter,
                {'workspaceRoot': os.path.dirname(launch_config_file)})

        self._StartWithConfiguration(launch_config[configuration], adapter)
    def Start(self, launch_variables=None):
        # We mutate launch_variables, so don't mutate the default argument.
        # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
        if launch_variables is None:
            launch_variables = {}

        self._logger.info("User requested start debug session with %s",
                          launch_variables)
        self._configuration = None
        self._adapter = None

        current_file = utils.GetBufferFilepath(vim.current.buffer)
        filetypes = utils.GetBufferFiletypes(vim.current.buffer)
        configurations = {}
        adapters = {}

        glob.glob(install.GetGadgetDir(VIMSPECTOR_HOME, install.GetOS()))
        for gadget_config_file in PathsToAllGadgetConfigs(
                VIMSPECTOR_HOME, current_file):
            self._logger.debug(f'Reading gadget config: {gadget_config_file}')
            if not gadget_config_file or not os.path.exists(
                    gadget_config_file):
                continue

            with open(gadget_config_file, 'r') as f:
                adapters.update(json.load(f).get('adapters') or {})

        for launch_config_file in PathsToAllConfigFiles(
                VIMSPECTOR_HOME, current_file, filetypes):
            self._logger.debug(
                f'Reading configurations from: {launch_config_file}')
            if not launch_config_file or not os.path.exists(
                    launch_config_file):
                continue

            with open(launch_config_file, 'r') as f:
                database = json.load(f)
                adapters.update(database.get('adapters') or {})
                configurations.update(database.get('configurations' or {}))

        if not configurations:
            utils.UserMessage('Unable to find any debug configurations. '
                              'You need to tell vimspector how to launch your '
                              'application.')
            return

        if 'configuration' in launch_variables:
            configuration_name = launch_variables.pop('configuration')
        elif len(configurations) == 1:
            configuration_name = next(iter(configurations.keys()))
        else:
            configuration_name = utils.SelectFromList(
                'Which launch configuration?', sorted(configurations.keys()))

        if not configuration_name or configuration_name not in configurations:
            return

        if launch_config_file:
            self._workspace_root = os.path.dirname(launch_config_file)
        else:
            self._workspace_root = os.path.dirname(current_file)

        configuration = configurations[configuration_name]
        adapter = configuration.get('adapter')
        if isinstance(adapter, str):
            adapter = adapters.get(adapter)

        # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
        # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
        # way to load .vimspector.local.json which just sets variables
        #
        # Additional vars as defined by VSCode:
        #
        # ${workspaceFolder} - the path of the folder opened in VS Code
        # ${workspaceFolderBasename} - the name of the folder opened in VS Code
        #                              without any slashes (/)
        # ${file} - the current opened file
        # ${relativeFile} - the current opened file relative to workspaceFolder
        # ${fileBasename} - the current opened file's basename
        # ${fileBasenameNoExtension} - the current opened file's basename with no
        #                              file extension
        # ${fileDirname} - the current opened file's dirname
        # ${fileExtname} - the current opened file's extension
        # ${cwd} - the task runner's current working directory on startup
        # ${lineNumber} - the current selected line number in the active file
        # ${selectedText} - the current selected text in the active file
        # ${execPath} - the path to the running VS Code executable

        def relpath(p, relative_to):
            if not p:
                return ''
            return os.path.relpath(p, relative_to)

        def splitext(p):
            if not p:
                return ['', '']
            return os.path.splitext(p)

        self._variables = {
            'dollar': '$',  # HACK. Hote '$$' also works.
            'workspaceRoot': self._workspace_root,
            'workspaceFolder': self._workspace_root,
            'gadgetDir': install.GetGadgetDir(VIMSPECTOR_HOME,
                                              install.GetOS()),
            'file': current_file,
            'relativeFile': relpath(current_file, self._workspace_root),
            'fileBasename': os.path.basename(current_file),
            'fileBasenameNoExtension':
            splitext(os.path.basename(current_file))[0],
            'fileDirname': os.path.dirname(current_file),
            'fileExtname': splitext(os.path.basename(current_file))[1],
            # NOTE: this is the window-local cwd for the current window, *not* Vim's
            # working directory.
            'cwd': os.getcwd(),
        }

        # Pretend that vars passed to the launch command were typed in by the user
        # (they may have been in theory)
        USER_CHOICES.update(launch_variables)
        self._variables.update(launch_variables)

        self._variables.update(
            utils.ParseVariables(adapter.get('variables', {}), self._variables,
                                 USER_CHOICES))
        self._variables.update(
            utils.ParseVariables(configuration.get('variables', {}),
                                 self._variables, USER_CHOICES))

        utils.ExpandReferencesInDict(configuration, self._variables,
                                     USER_CHOICES)
        utils.ExpandReferencesInDict(adapter, self._variables, USER_CHOICES)

        if not adapter:
            utils.UserMessage(
                'No adapter configured for {}'.format(configuration_name),
                persist=True)
            return

        self._StartWithConfiguration(configuration, adapter)
示例#3
0
    def Start(self, launch_variables=None):
        # We mutate launch_variables, so don't mutate the default argument.
        # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
        if launch_variables is None:
            launch_variables = {}

        self._logger.info("User requested start debug session with %s",
                          launch_variables)
        self._configuration = None
        self._adapter = None

        current_file = utils.GetBufferFilepath(vim.current.buffer)
        filetypes = utils.GetBufferFiletypes(vim.current.buffer)
        configurations = {}
        adapters = {}

        glob.glob(install.GetGadgetDir(VIMSPECTOR_HOME))
        for gadget_config_file in PathsToAllGadgetConfigs(
                VIMSPECTOR_HOME, current_file):
            self._logger.debug(f'Reading gadget config: {gadget_config_file}')
            if not gadget_config_file or not os.path.exists(
                    gadget_config_file):
                continue

            with open(gadget_config_file, 'r') as f:
                a = json.loads(minify(f.read())).get('adapters') or {}
                adapters.update(a)

        for launch_config_file in PathsToAllConfigFiles(
                VIMSPECTOR_HOME, current_file, filetypes):
            self._logger.debug(
                f'Reading configurations from: {launch_config_file}')
            if not launch_config_file or not os.path.exists(
                    launch_config_file):
                continue

            with open(launch_config_file, 'r') as f:
                database = json.loads(minify(f.read()))
                adapters.update(database.get('adapters') or {})
                configurations.update(database.get('configurations' or {}))

        if not configurations:
            utils.UserMessage('Unable to find any debug configurations. '
                              'You need to tell vimspector how to launch your '
                              'application.')
            return

        if 'configuration' in launch_variables:
            configuration_name = launch_variables.pop('configuration')
        elif (len(configurations) == 1
              and next(iter(configurations.values())).get("autoselect", True)):
            configuration_name = next(iter(configurations.keys()))
        else:
            # Find a single configuration with 'default' True and autoselect not False
            defaults = {
                n: c
                for n, c in configurations.items()
                if c.get('default', False) is True
                and c.get('autoselect', True) is not False
            }

            if len(defaults) == 1:
                configuration_name = next(iter(defaults.keys()))
            else:
                configuration_name = utils.SelectFromList(
                    'Which launch configuration?',
                    sorted(configurations.keys()))

        if not configuration_name or configuration_name not in configurations:
            return

        if launch_config_file:
            self._workspace_root = os.path.dirname(launch_config_file)
        else:
            self._workspace_root = os.path.dirname(current_file)

        configuration = configurations[configuration_name]
        adapter = configuration.get('adapter')
        if isinstance(adapter, str):
            adapter_dict = adapters.get(adapter)

            if adapter_dict is None:
                suggested_gadgets = installer.FindGadgetForAdapter(adapter)
                if suggested_gadgets:
                    response = utils.AskForInput(
                        f"The specified adapter '{adapter}' is not "
                        "installed. Would you like to install the following gadgets? ",
                        ' '.join(suggested_gadgets))
                    if response:
                        new_launch_variables = dict(launch_variables)
                        new_launch_variables[
                            'configuration'] = configuration_name

                        installer.RunInstaller(
                            self._api_prefix,
                            False,  # Don't leave open
                            *shlex.split(response),
                            then=lambda: self.Start(new_launch_variables))
                        return
                    elif response is None:
                        return

                utils.UserMessage(
                    f"The specified adapter '{adapter}' is not "
                    "available. Did you forget to run "
                    "'install_gadget.py'?",
                    persist=True,
                    error=True)
                return

            adapter = adapter_dict

        # Additional vars as defined by VSCode:
        #
        # ${workspaceFolder} - the path of the folder opened in VS Code
        # ${workspaceFolderBasename} - the name of the folder opened in VS Code
        #                              without any slashes (/)
        # ${file} - the current opened file
        # ${relativeFile} - the current opened file relative to workspaceFolder
        # ${fileBasename} - the current opened file's basename
        # ${fileBasenameNoExtension} - the current opened file's basename with no
        #                              file extension
        # ${fileDirname} - the current opened file's dirname
        # ${fileExtname} - the current opened file's extension
        # ${cwd} - the task runner's current working directory on startup
        # ${lineNumber} - the current selected line number in the active file
        # ${selectedText} - the current selected text in the active file
        # ${execPath} - the path to the running VS Code executable

        def relpath(p, relative_to):
            if not p:
                return ''
            return os.path.relpath(p, relative_to)

        def splitext(p):
            if not p:
                return ['', '']
            return os.path.splitext(p)

        variables = {
            'dollar': '$',  # HACK. Hote '$$' also works.
            'workspaceRoot': self._workspace_root,
            'workspaceFolder': self._workspace_root,
            'gadgetDir': install.GetGadgetDir(VIMSPECTOR_HOME),
            'file': current_file,
        }

        calculus = {
            'relativeFile':
            lambda: relpath(current_file, self._workspace_root),
            'fileBasename':
            lambda: os.path.basename(current_file),
            'fileBasenameNoExtension':
            lambda: splitext(os.path.basename(current_file))[0],
            'fileDirname':
            lambda: os.path.dirname(current_file),
            'fileExtname':
            lambda: splitext(os.path.basename(current_file))[1],
            # NOTE: this is the window-local cwd for the current window, *not* Vim's
            # working directory.
            'cwd':
            os.getcwd,
            'unusedLocalPort':
            utils.GetUnusedLocalPort,
        }

        # Pretend that vars passed to the launch command were typed in by the user
        # (they may have been in theory)
        USER_CHOICES.update(launch_variables)
        variables.update(launch_variables)

        try:
            variables.update(
                utils.ParseVariables(adapter.get('variables', {}), variables,
                                     calculus, USER_CHOICES))
            variables.update(
                utils.ParseVariables(configuration.get('variables', {}),
                                     variables, calculus, USER_CHOICES))

            utils.ExpandReferencesInDict(configuration, variables, calculus,
                                         USER_CHOICES)
            utils.ExpandReferencesInDict(adapter, variables, calculus,
                                         USER_CHOICES)
        except KeyboardInterrupt:
            self._Reset()
            return

        if not adapter:
            utils.UserMessage(
                'No adapter configured for {}'.format(configuration_name),
                persist=True)
            return

        self._StartWithConfiguration(configuration, adapter)
示例#4
0
    def Start(self, launch_variables={}):
        self._configuration = None
        self._adapter = None

        launch_config_file = utils.PathToConfigFile('.vimspector.json')

        if not launch_config_file:
            utils.UserMessage(
                'Unable to find .vimspector.json. You need to tell '
                'vimspector how to launch your application')
            return

        with open(launch_config_file, 'r') as f:
            database = json.load(f)

        configurations = database.get('configurations')
        adapters = {}

        for gadget_config_file in [
                install.GetGadgetConfigFile(VIMSPECTOR_HOME),
                utils.PathToConfigFile('.gadgets.json')
        ]:
            if gadget_config_file and os.path.exists(gadget_config_file):
                with open(gadget_config_file, 'r') as f:
                    adapters.update(json.load(f).get('adapters') or {})

        adapters.update(database.get('adapters') or {})

        if len(configurations) == 1:
            configuration_name = next(iter(configurations.keys()))
        else:
            configuration_name = utils.SelectFromList(
                'Which launch configuration?',
                sorted(list(configurations.keys())))

        if not configuration_name or configuration_name not in configurations:
            return

        self._workspace_root = os.path.dirname(launch_config_file)

        configuration = configurations[configuration_name]
        adapter = configuration.get('adapter')
        if isinstance(adapter, str):
            adapter = adapters.get(adapter)

        # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
        # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
        # way to load .vimspector.local.json which just sets variables
        self._variables = {
            'dollar': '$',  # HACK. Hote '$$' also works.
            'workspaceRoot': self._workspace_root,
            'gadgetDir': install.GetGadgetDir(VIMSPECTOR_HOME, install.GetOS())
        }
        self._variables.update(
            utils.ParseVariables(adapter.get('variables', {})))
        self._variables.update(
            utils.ParseVariables(configuration.get('variables', {})))
        self._variables.update(launch_variables)

        utils.ExpandReferencesInDict(configuration, self._variables)
        utils.ExpandReferencesInDict(adapter, self._variables)

        if not adapter:
            utils.UserMessage(
                'No adapter configured for {}'.format(configuration_name),
                persist=True)
            return

        self._StartWithConfiguration(configuration, adapter)
示例#5
0
    def test_ExpandReferencesInDict(self):
        mapping = {
            'one': 'one',
            'two': 'TWO',
            'bool': True,
            'words': 'these are some words'
        }
        calculus = {
            'three': lambda: 1 + 2,
        }
        CHOICES = {'five': '5ive!'}

        def AskForInput(prompt, default_value=None):
            if default_value is not None:
                return default_value

            return 'typed text'

        d = {
            'dollar': '$$',
            'not_a_var': '$${test}',
            'one': '${one}',
            'two': '${one} and ${two}',
            'three': '${three}',
            'three_with_default':
            '${three_with_default:${three\\}}',  # uses calculus
            'four': '${four}',
            'five': '${five}',
            'list': ['*${words}'],
            'list1': ['start', '*${words}', 'end'],
            'list2': ['*${words}', '${three}'],
            'list3': ['${one}', '*${words}', 'three'],
            'dict#json': '{ "key": "value" }',
            'bool#json': 'false',
            'one_default': '${one_default:one}',
            'two_default': '${two_default_1:one} and ${two_default_2:two}',
            'one_default2': '${one_default2:${one\\}}',
            'two_default2':
            '${two_default2_1:${one\\}} and ${two_default2_2:${two\\}}',
            'unlikely_name#json#s': 'true',
            'empty_splice': ['*${empty:}'],
        }

        e = {
            'dollar': '$',
            'not_a_var': '${test}',
            'one': 'one',
            'two': 'one and TWO',
            'three': '3',
            'three_with_default': '3',
            'four': 'typed text',
            'five': '5ive!',
            'list': ['these', 'are', 'some', 'words'],
            'list1': ['start', 'these', 'are', 'some', 'words', 'end'],
            'list2': ['these', 'are', 'some', 'words', '3'],
            'list3': ['one', 'these', 'are', 'some', 'words', 'three'],
            'dict': {
                'key': 'value',
            },
            'bool': False,
            'one_default': 'one',
            'two_default': 'one and two',
            'one_default2': 'one',
            'two_default2': 'one and TWO',
            'unlikely_name#json': 'true',
            'empty_splice': [],
        }

        with patch('vimspector.utils.AskForInput', side_effect=AskForInput):
            utils.ExpandReferencesInDict(d, mapping, calculus, CHOICES)

        self.assertDictEqual(d, e)
示例#6
0
  def Start( self, launch_variables = {} ):
    self._logger.info( "User requested start debug session with %s",
                       launch_variables )
    self._configuration = None
    self._adapter = None

    launch_config_file = utils.PathToConfigFile( '.vimspector.json' )

    if not launch_config_file:
      utils.UserMessage( 'Unable to find .vimspector.json. You need to tell '
                         'vimspector how to launch your application' )
      return

    with open( launch_config_file, 'r' ) as f:
      database = json.load( f )

    configurations = database.get( 'configurations' )
    adapters = {}

    for gadget_config_file in [ install.GetGadgetConfigFile( VIMSPECTOR_HOME ),
                                utils.PathToConfigFile( '.gadgets.json' ) ]:
      if gadget_config_file and os.path.exists( gadget_config_file ):
        with open( gadget_config_file, 'r' ) as f:
          adapters.update( json.load( f ).get( 'adapters' ) or {} )

    adapters.update( database.get( 'adapters' ) or {} )

    if len( configurations ) == 1:
      configuration_name = next( iter( configurations.keys() ) )
    else:
      configuration_name = utils.SelectFromList(
        'Which launch configuration?',
        sorted( list( configurations.keys() ) ) )

    if not configuration_name or configuration_name not in configurations:
      return

    self._workspace_root = os.path.dirname( launch_config_file )

    configuration = configurations[ configuration_name ]
    adapter = configuration.get( 'adapter' )
    if isinstance( adapter, str ):
      adapter = adapters.get( adapter )

    # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
    # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
    # way to load .vimspector.local.json which just sets variables
    #
    # Additional vars as defined by VSCode:
    #
    # ${workspaceFolder} - the path of the folder opened in VS Code
    # ${workspaceFolderBasename} - the name of the folder opened in VS Code
    #                              without any slashes (/)
    # ${file} - the current opened file
    # ${relativeFile} - the current opened file relative to workspaceFolder
    # ${fileBasename} - the current opened file's basename
    # ${fileBasenameNoExtension} - the current opened file's basename with no
    #                              file extension
    # ${fileDirname} - the current opened file's dirname
    # ${fileExtname} - the current opened file's extension
    # ${cwd} - the task runner's current working directory on startup
    # ${lineNumber} - the current selected line number in the active file
    # ${selectedText} - the current selected text in the active file
    # ${execPath} - the path to the running VS Code executable

    current_file = utils.GetBufferFilepath( vim.current.buffer )

    self._variables = {
      'dollar': '$', # HACK. Hote '$$' also works.
      'workspaceRoot': self._workspace_root,
      'workspaceFolder': self._workspace_root,
      'gadgetDir': install.GetGadgetDir( VIMSPECTOR_HOME, install.GetOS() ),
      'file': current_file,
      'relativeFile': os.path.relpath( current_file, self._workspace_root ),
      'fileBasename': os.path.basename( current_file ),
      'fileBasenameNoExtension':
        os.path.splitext( os.path.basename( current_file ) )[ 0 ],
      'fileDirname': os.path.dirname( current_file ),
      'fileExtname':
        os.path.splitext( os.path.basename( current_file ) )[ 1 ],
      'cwd': os.getcwd(),
    }
    self._variables.update(
      utils.ParseVariables( adapter.get( 'variables', {} ),
                            self._variables ) )
    self._variables.update(
      utils.ParseVariables( configuration.get( 'variables', {} ),
                            self._variables ) )
    self._variables.update( launch_variables )

    utils.ExpandReferencesInDict( configuration, self._variables )
    utils.ExpandReferencesInDict( adapter, self._variables )

    if not adapter:
      utils.UserMessage( 'No adapter configured for {}'.format(
        configuration_name ), persist=True )
      return

    self._StartWithConfiguration( configuration, adapter )