def _BuildChunks(request_data, new_buffer): filepath = request_data['filepath'] old_buffer = request_data['file_data'][filepath]['contents'] new_buffer = _FixLineEndings(old_buffer, new_buffer) new_length = len(new_buffer) old_length = len(old_buffer) if new_length == old_length and new_buffer == old_buffer: return [] min_length = min(new_length, old_length) start_index = 0 end_index = min_length for i in range(0, min_length - 1): if new_buffer[i] != old_buffer[i]: start_index = i break for i in range(1, min_length): if new_buffer[new_length - i] != old_buffer[old_length - i]: end_index = i - 1 break # To handle duplicates, i.e aba => a if (start_index + end_index > min_length): start_index -= start_index + end_index - min_length replacement_text = new_buffer[start_index:new_length - end_index] (start_line, start_column) = _IndexToLineColumn(old_buffer, start_index) (end_line, end_column) = _IndexToLineColumn(old_buffer, old_length - end_index) start = responses.Location(start_line, start_column, filepath) end = responses.Location(end_line, end_column, filepath) return [ responses.FixItChunk(replacement_text, responses.Range(start, end)) ]
def BuildRange( filename, start, end ): return responses.Range( responses.Location( start[ 'line' ] + 1, start[ 'ch' ] + 1, filename ), responses.Location( end[ 'line' ] + 1, end[ 'ch' ] + 1, filename ) )
def _QuickFixToDiagnostic(self, request_data, quick_fix): filename = quick_fix["FileName"] location = _BuildLocation(request_data, filename, quick_fix['Line'], quick_fix['Column']) location_range = responses.Range(location, location) return responses.Diagnostic(list(), location, location_range, quick_fix["Text"], quick_fix["LogLevel"].upper())
def _QuickFixToDiagnostic(self, quick_fix): filename = quick_fix["FileName"] location = responses.Location(quick_fix["Line"], quick_fix["Column"], filename) location_range = responses.Range(location, location) return responses.Diagnostic(list(), location, location_range, quick_fix["Text"], quick_fix["LogLevel"].upper())
def _BuildFixItChunkForRange(new_name, file_contents, file_name, source_range): """ returns list FixItChunk for a tsserver source range """ return responses.FixItChunk( new_name, responses.Range(start=_BuildLocation(file_contents, file_name, source_range['start']['line'], source_range['start']['offset']), end=_BuildLocation(file_contents, file_name, source_range['end']['line'], source_range['end']['offset'])))
def _LinePositionSpanTextChangeToFixItChunks(chunks, filename, request_data): return [ responses.FixItChunk( chunk['NewText'], responses.Range( _BuildLocation(request_data, filename, chunk['StartLine'], chunk['StartColumn']), _BuildLocation(request_data, filename, chunk['EndLine'], chunk['EndColumn']))) for chunk in chunks ]
def BuildRange( file_contents, filename, start, end ): return responses.Range( _BuildLocation( file_contents, filename, start[ 'line' ], start[ 'ch' ] ), _BuildLocation( file_contents, filename, end[ 'line' ], end[ 'ch' ] ) )
def _TsDiagnosticToYcmdDiagnostic(self, request_data, ts_diagnostic): filepath = request_data['filepath'] ts_fixes = self._SendRequest( 'getCodeFixes', { 'file': filepath, 'startLine': ts_diagnostic['startLocation']['line'], 'startOffset': ts_diagnostic['startLocation']['offset'], 'endLine': ts_diagnostic['endLocation']['line'], 'endOffset': ts_diagnostic['endLocation']['offset'], 'errorCodes': [ts_diagnostic['code']] }) location = responses.Location(request_data['line_num'], request_data['column_num'], filepath) fixits = [] for fix in ts_fixes: description = fix['description'] # TSServer returns these fixits for every error in JavaScript files. # Ignore them since they are not useful. if description in [ 'Ignore this error message', 'Disable checking for this file' ]: continue fixit = responses.FixIt( location, _BuildFixItForChanges(request_data, fix['changes']), description) fixits.append(fixit) contents = GetFileLines(request_data, filepath) ts_start_location = ts_diagnostic['startLocation'] ts_start_line = ts_start_location['line'] start_offset = utils.CodepointOffsetToByteOffset( contents[ts_start_line - 1], ts_start_location['offset']) ts_end_location = ts_diagnostic['endLocation'] ts_end_line = ts_end_location['line'] end_offset = utils.CodepointOffsetToByteOffset( contents[ts_end_line - 1], ts_end_location['offset']) location_start = responses.Location(ts_start_line, start_offset, filepath) location_end = responses.Location(ts_end_line, end_offset, filepath) location_extent = responses.Range(location_start, location_end) return responses.Diagnostic([location_extent], location_start, location_extent, ts_diagnostic['message'], 'ERROR', fixits=fixits)
def _RefactoringToFixIt(refactoring): """Converts a Jedi Refactoring instance to a single responses.FixIt.""" # FIXME: refactorings can rename files (apparently). ycmd API doesn't have any # interface for that, so we just ignore them. changes = refactoring.get_changed_files() chunks = [] # We sort the files to ensure the tests are stable for filename in sorted(changes.keys()): changed_file = changes[filename] # NOTE: This is an internal API. We _could_ use GetFileContents( filename ) # here, but using Jedi's representation means that it is always consistent # with get_new_code() old_text = changed_file._module_node.get_code() new_text = changed_file.get_new_code() # Cache the offsets of all the newlines in the file. These are used to # calculate the line/column values from the offsets retuned by the diff # scanner newlines = [i for i, c in enumerate(old_text) if c == '\n'] newlines.append(len(old_text)) sequence_matcher = difflib.SequenceMatcher(a=old_text, b=new_text, autojunk=False) for (operation, old_start, old_end, new_start, new_end) in sequence_matcher.get_opcodes(): # Tag of equal means the range is identical, so nothing to do. if operation == 'equal': continue # operation can be 'insert', 'replace' or 'delete', the offsets actually # already cover that in our FixIt API (a delete has an empty new_text, an # insert has an empty range), so we just encode the line/column offset and # the replacement text extracted from new_text chunks.append( responses.FixItChunk( new_text[new_start:new_end], # FIXME: new_end must be equal to or after new_start, so we should make # OffsetToPosition take 2 offsets and return them rather than repeating # work responses.Range( _OffsetToPosition(old_start, filename, old_text, newlines), _OffsetToPosition(old_end, filename, old_text, newlines)))) return responses.FixIt(responses.Location(1, 1, 'none'), chunks, '', kind=responses.FixIt.Kind.REFACTOR)
def _SwiftDiagnosticWithColumnToYcmdDiagnostic(filename, split_lines, swift_diagnostic, computed_line=None): start_col = swift_diagnostic.column end_col = start_col + 1 line = computed_line if computed_line else swift_diagnostic.line location = _BuildLocation(split_lines, filename, line, start_col) location_end = _BuildLocation(split_lines, filename, line, end_col) location_extent = responses.Range(location, location_end) return responses.Diagnostic(list(), location, location_extent, swift_diagnostic.description, swift_diagnostic.GetYCMDSeverity())
def _QuickFixToDiagnostic(self, request_data, quick_fix): filename = quick_fix["FileName"] # NOTE: end of diagnostic range returned by the OmniSharp server is not # included. location = _BuildLocation(request_data, filename, quick_fix['Line'], quick_fix['Column']) location_end = _BuildLocation(request_data, filename, quick_fix['EndLine'], quick_fix['EndColumn']) if not location_end: location_end = location location_extent = responses.Range(location, location_end) return responses.Diagnostic([], location, location_extent, quick_fix['Text'], quick_fix['LogLevel'].upper())
def _TsDiagnosticToYcmdDiagnostic( self, request_data, ts_diagnostic ): filepath = request_data[ 'filepath' ] ts_fixes = self._SendRequest( 'getCodeFixes', { 'file': filepath, 'startLine': ts_diagnostic[ 'startLocation' ][ 'line' ], 'startOffset': ts_diagnostic[ 'startLocation' ][ 'offset' ], 'endLine': ts_diagnostic[ 'endLocation' ][ 'line' ], 'endOffset': ts_diagnostic[ 'endLocation' ][ 'offset' ], 'errorCodes': [ ts_diagnostic[ 'code' ] ] } ) location = responses.Location( request_data[ 'line_num' ], request_data[ 'column_num' ], filepath ) fixits = [ responses.FixIt( location, _BuildFixItForChanges( request_data, fix[ 'changes' ] ), fix[ 'description' ] ) for fix in ts_fixes ] contents = GetFileLines( request_data, filepath ) ts_start_location = ts_diagnostic[ 'startLocation' ] ts_start_line = ts_start_location[ 'line' ] start_offset = utils.CodepointOffsetToByteOffset( contents[ ts_start_line - 1 ], ts_start_location[ 'offset' ] ) ts_end_location = ts_diagnostic[ 'endLocation' ] ts_end_line = ts_end_location[ 'line' ] end_offset = utils.CodepointOffsetToByteOffset( contents[ ts_end_line - 1 ], ts_end_location[ 'offset' ] ) location_start = responses.Location( ts_start_line, start_offset, filepath ) location_end = responses.Location( ts_end_line, end_offset, filepath ) location_extent = responses.Range( location_start, location_end ) return responses.Diagnostic( [ location_extent ], location_start, location_extent, ts_diagnostic[ 'message' ], 'ERROR', fixits = fixits )
def TsDiagnosticToYcmdDiagnostic(filepath, line_value, ts_diagnostic): ts_start_location = ts_diagnostic['startLocation'] ts_end_location = ts_diagnostic['endLocation'] start_offset = utils.CodepointOffsetToByteOffset( line_value, ts_start_location['offset']) end_offset = utils.CodepointOffsetToByteOffset(line_value, ts_end_location['offset']) location = responses.Location(ts_start_location['line'], start_offset, filepath) location_end = responses.Location(ts_end_location['line'], end_offset, filepath) location_extent = responses.Range(location, location_end) return responses.Diagnostic([location_extent], location, location_extent, ts_diagnostic['message'], 'ERROR')
def TsDiagnosticToYcmdDiagnostic(request_data, ts_diagnostic): filepath = request_data['filepath'] contents = request_data['lines'] ts_start_location = ts_diagnostic['startLocation'] ts_start_line = ts_start_location['line'] start_offset = utils.CodepointOffsetToByteOffset( contents[ts_start_line - 1], ts_start_location['offset']) ts_end_location = ts_diagnostic['endLocation'] ts_end_line = ts_end_location['line'] end_offset = utils.CodepointOffsetToByteOffset(contents[ts_end_line - 1], ts_end_location['offset']) location_start = responses.Location(ts_start_line, start_offset, filepath) location_end = responses.Location(ts_end_line, end_offset, filepath) location_extent = responses.Range(location_start, location_end) return responses.Diagnostic([location_extent], location_start, location_extent, ts_diagnostic['message'], 'ERROR')