Esempio n. 1
0
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))
    ]
Esempio n. 2
0
 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 ) )
Esempio n. 3
0
 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())
Esempio n. 4
0
    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())
Esempio n. 5
0
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'])))
Esempio n. 6
0
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
    ]
Esempio n. 7
0
 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' ] ) )
Esempio n. 8
0
    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)
Esempio n. 9
0
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)
Esempio n. 10
0
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())
Esempio n. 11
0
 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())
Esempio n. 12
0
  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 )
Esempio n. 13
0
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')
Esempio n. 14
0
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')