Beispiel #1
0
 def BuildFixItChunk(change):
     filepath = self._ServerPathToAbsolute(change['file'])
     file_contents = GetFileLines(request_data, filepath)
     return responses.FixItChunk(
         change['text'],
         BuildRange(file_contents, filepath, change['start'],
                    change['end']))
Beispiel #2
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))
    ]
Beispiel #3
0
 def BuildFixItChunk(change):
     filename = os.path.abspath(change['file'])
     file_contents = utils.SplitLines(
         GetFileContents(request_data, filename))
     return responses.FixItChunk(
         change['text'],
         BuildRange(file_contents, filename, change['start'],
                    change['end']))
Beispiel #4
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'])))
Beispiel #5
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
    ]
Beispiel #6
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)
Beispiel #7
0
 def BuildFixItChunk(change):
     return responses.FixItChunk(
         change['text'],
         BuildRange(os.path.abspath(change['file']), change['start'],
                    change['end']))