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
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)
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)))
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'))
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'))
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'))
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'))
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
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))
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)))
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
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), ), ), )
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)
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)))