示例#1
0
def _get_document_symbols(
        code_lines: List[str],
        names: List[Name],
        current: Optional[Name] = None) -> List[types.DocumentSymbol]:
    # Looks like names are sorted by order of appearance, so
    # children are after their parents
    result = []
    while names:
        if current and names[0].parent() != current:
            break
        name = names.pop(0)
        if name.type == 'param':
            continue
        children = _get_document_symbols(code_lines, names, name)
        line = name.line - 1
        r = types.Range(start=types.Position(line=line, character=name.column),
                        end=types.Position(line=line,
                                           character=len(code_lines[line]) -
                                           1))
        result.append(
            types.DocumentSymbol(name=name.name,
                                 kind=_DOCUMENT_SYMBOL_KINDS.get(
                                     name.type, types.SymbolKind.Null),
                                 range=r,
                                 selection_range=r,
                                 children=children or None))
    return result
示例#2
0
 def _symbols():
     for name in names:
         if name.type == 'param':
             continue
         parent = name.parent()
         parent_name = parent and parent.full_name
         if parent_name:
             module_name = name.module_name
             if parent_name == module_name:
                 parent_name = None
             elif parent_name.startswith(f'{module_name}.'):
                 parent_name = parent_name[len(module_name) + 1:]
         yield types.SymbolInformation(
             name=name.name,
             kind=_DOCUMENT_SYMBOL_KINDS.get(name.type,
                                             types.SymbolKind.Null),
             location=types.Location(
                 uri=uri,
                 range=types.Range(
                     start=types.Position(line=name.line - 1,
                                          character=name.column),
                     end=types.Position(
                         line=name.line - 1,
                         characret=len(code_lines[name.line - 1]) - 1))),
             container_name=parent_name)
示例#3
0
 def unexpectedError(self, _filename, msg):
     self.result.append(
         types.Diagnostic(range=types.Range(
             start=types.Position(line=0, character=0),
             end=types.Position(line=0, character=0)),
                          message=msg,
                          severity=types.DiagnosticSeverity.Error,
                          source='pyflakes'))
示例#4
0
 def syntaxError(self, _filename, msg, lineno, offset, _text):
     line = lineno - 1
     col = offset or 0
     self.result.append(
         types.Diagnostic(range=types.Range(
             start=types.Position(line=line, character=col),
             end=types.Position(line=line,
                                character=len(self._get_codeline(line)) -
                                col)),
                          message=msg,
                          severity=types.DiagnosticSeverity.Error,
                          source='pyflakes'))
示例#5
0
 def flake(self, message):
     line = message.lineno - 1
     if message.__class__.__name__ in self.errors:
         severity = types.DiagnosticSeverity.Error
     else:
         severity = types.DiagnosticSeverity.Warning
     self.result.append(
         types.Diagnostic(range=types.Range(
             start=types.Position(line=line, character=message.col),
             end=types.Position(line=line,
                                character=len(self._get_codeline(line)))),
                          message=message.message % message.message_args,
                          severity=severity,
                          source='pyflakes'))
示例#6
0
 def error(self, line_number, offset, text, check):
     code = text[:4]
     if self._ignore_code(code) or code in self.expected:
         return
     line = line_number - 1
     self.result.append(
         types.Diagnostic(range=types.Range(
             start=types.Position(line=line, character=offset),
             end=types.Position(line=line,
                                character=len(
                                    self.lines[line].rstrip('\n\r')))),
                          message=text,
                          severity=types.DiagnosticSeverity.Warning,
                          code=code,
                          source='pycodestyle'))
示例#7
0
def test_completion():
    uri = 'file://test_completion.py'
    content = '''
def foo(a, *, b, c=None):
    pass

foo'''
    doc = Document(uri, content)
    server.workspace.get_document = Mock(return_value=doc)
    aserver.completionFunction = aserver._completions_snippets
    completion = aserver.completions(
        server,
        types.CompletionParams(
            text_document=types.TextDocumentIdentifier(uri=uri),
            position=types.Position(line=4, character=3),
            context=types.CompletionContext(
                trigger_kind=types.CompletionTriggerKind.Invoked)))
    assert len(completion.items) == 2
    item = completion.items[0]
    assert item.insert_text is None
    assert item.label == 'foo'
    assert item.sort_text == 'aaafoo'
    assert item.insert_text_format is None
    item = completion.items[1]
    assert item.label == 'foo(a, b)'
    assert item.sort_text == 'aazfoo'
    assert item.insert_text_format == types.InsertTextFormat.Snippet
    assert item.insert_text == 'foo(${1:a}, b=${2:b})$0'
示例#8
0
 def _append():
     if replace_lines:
         end = types.Position(line=line_number, character=0)
     else:
         end = start
     result.append(
         types.TextEdit(range=types.Range(start=start, end=end),
                        new_text=''.join(lines)))
示例#9
0
def hover(ls: LanguageServer,
          params: types.TextDocumentPositionParams) -> Optional[types.Hover]:
    """Get hover information for a symbol, if present at position"""
    markdown_file = get_markdown_file(ls, params.text_document.uri)
    key, start, stop = find_key(markdown_file, params.position)
    if start is None or stop is None:
        return None
    if key is not None and key in cached_bibliographies:
        return types.Hover(
            contents=info(cached_bibliographies[key]),
            range=types.Range(
                start=types.Position(line=params.position.line,
                                     character=start),
                end=types.Position(line=params.position.line, character=stop),
            ),
        )
    return None
示例#10
0
def completions(ls: LanguageServer, params: types.CompletionParams):
    global completionFunction
    script = get_script(ls, params.text_document.uri)
    completions = script.complete(params.position.line + 1,
                                  params.position.character,
                                  fuzzy=config['completion_fuzzy'])
    code_line = script._code_lines[params.position.line]
    word_match = RE_WORD.match(code_line[params.position.character:])
    if word_match:
        word_rest = word_match.end()
    else:
        word_rest = 0
    r = types.Range(start=types.Position(line=params.position.line,
                                         character=params.position.character),
                    end=types.Position(line=params.position.line,
                                       character=params.position.character +
                                       word_rest))
    return types.CompletionList(is_incomplete=False,
                                items=list(completionFunction(completions, r)))
示例#11
0
def _get_text_edits(diff: str) -> List[types.TextEdit]:
    result = []
    line_number = 0
    start = None
    replace_lines = False
    lines: List[str] = []

    def _append():
        if replace_lines:
            end = types.Position(line=line_number, character=0)
        else:
            end = start
        result.append(
            types.TextEdit(range=types.Range(start=start, end=end),
                           new_text=''.join(lines)))

    for line in diff.splitlines(True)[2:]:
        kind = line[0]
        if kind == '-':
            if not start:
                start = types.Position(line=line_number, character=0)
            replace_lines = True
            line_number += 1
            continue
        if kind == '+':
            if not start:
                start = types.Position(line=line_number, character=0)
            lines.append(line[1:])
            continue
        if start:
            _append()
            start = None
            replace_lines = False
            lines = []
        if kind == '@':
            line_number = int(line[4:line.index(',')]) - 1
        else:
            line_number += 1
    if start:
        _append()
    return result
示例#12
0
def _mypy_check(ls: LanguageServer, uri: str, script: Script,
                result: List[types.Diagnostic]):
    from mypy import api
    assert jediEnvironment is not None
    version_info = jediEnvironment.version_info
    if config['diagnostic_on_change']:
        args = ['--command', script._code]
    else:
        args = [to_fs_path(uri)]
    lines = api.run([
        '--python-executable', jediEnvironment.executable, '--python-version',
        f'{version_info.major}.{version_info.minor}', '--config-file',
        get_mypy_config(ls,
                        uri), '--hide-error-context', '--show-column-numbers',
        '--show-error-codes', '--no-pretty', '--no-error-summary'
    ] + args)
    if lines[1]:
        ls.show_message(lines[1], types.MessageType.Error)
        return

    for line in lines[0].split('\n'):
        parts = line.split(':', 4)
        if len(parts) < 5:
            continue
        _fn, row, column, err_type, message = parts
        row = int(row) - 1
        column = int(column) - 1
        if err_type.strip() == 'note':
            severity = types.DiagnosticSeverity.Hint
        else:
            severity = types.DiagnosticSeverity.Warning
        result.append(
            types.Diagnostic(range=types.Range(
                start=types.Position(line=row, character=column),
                end=types.Position(line=row,
                                   character=len(script._code_lines[row]))),
                             message=message.strip(),
                             severity=severity,
                             source='mypy'))
    return result
示例#13
0
def _validate(ls: LanguageServer, uri: str, script: Script = None):
    if script is None:
        script = get_script(ls, uri)

    # Jedi
    result = [
        types.Diagnostic(
            range=types.Range(start=types.Position(line=x.line - 1,
                                                   character=x.column),
                              end=types.Position(line=x.until_line - 1,
                                                 character=x.until_column)),
            message=x.get_message(),
            severity=types.DiagnosticSeverity.Error,
            source='jedi') for x in script.get_syntax_errors()
    ]
    if result:
        ls.publish_diagnostics(uri, result)
        return

    # pyflakes
    pyflakes_check(script._code, script.path,
                   PyflakesReporter(result, script, config['pyflakes_errors']))

    # pycodestyle
    codestyleopts = get_pycodestyle_options(ls, uri)
    CodestyleChecker(script.path, script._code.splitlines(True), codestyleopts,
                     CodestyleReport(codestyleopts, result)).check_all()

    # mypy
    if config['mypy_enabled']:
        try:
            _mypy_check(ls, uri, script, result)
        except Exception as e:
            ls.show_message(f'mypy check error: {e}',
                            types.MessageType.Warning)

    ls.publish_diagnostics(uri, result)
示例#14
0
def _completion_item(completion: Completion, r: types.Range) -> Dict:
    label = completion.name
    _r = r
    lnm = completion._like_name_length
    if lnm == 1 and label[0] in {'"', "'"}:
        lnm = 0
        label = label[1:]
    elif lnm:
        _r = types.Range(start=types.Position(line=r.start.line,
                                              character=r.start.character -
                                              lnm),
                         end=r.end)
    return dict(label=label,
                kind=_COMPLETION_TYPES.get(completion.type,
                                           types.CompletionItemKind.Text),
                documentation=completion.docstring(raw=True),
                text_edit=types.TextEdit(range=_r, new_text=label))
示例#15
0
def test_hover():
    uri = 'file://test_hover.py'
    content = '''
def foo(a, *, b, c=None):
    """docstring"""
    pass

foo'''
    doc = Document(uri, content)
    server.workspace.get_document = Mock(return_value=doc)
    aserver.hoverFunction = aserver._docstring
    h = aserver.hover(
        server,
        types.TextDocumentPositionParams(
            text_document=types.TextDocumentIdentifier(uri=uri),
            position=types.Position(line=5, character=0)))
    assert h is not None
    assert isinstance(h.contents, types.MarkupContent)
    assert h.contents.kind == types.MarkupKind.PlainText
    assert h.contents.value == 'foo(a, *, b, c=None)\n\ndocstring'
示例#16
0
def definition(
    ls: LanguageServer,
    params: types.TextDocumentPositionParams = None
) -> Optional[types.Location]:
    """Goto definition of symbol, if a bibliography key is present"""
    if params is None:
        return None
    markdown_file = get_markdown_file(ls, params.text_document.uri)
    key, *_ = find_key(markdown_file, params.position)
    if key is None or not key in keys:
        return None
    key_position = keys[key]
    return types.Location(
        uri=key_position.text_document.uri,
        range=types.Range(
            start=key_position.position,
            end=types.Position(
                line=key_position.position.line,
                character=key_position.position.character + len(key),
            ),
        ),
    )
示例#17
0
def _get_name_range(name: Name) -> types.Range:
    return types.Range(start=types.Position(line=name.line - 1,
                                            character=name.column),
                       end=types.Position(line=name.line - 1,
                                          character=name.column +
                                          len(name.name)))