コード例 #1
0
ファイル: test_location.py プロジェクト: AndrewWalker/sealang
def test_location():
    tu = get_tu(baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert one is not None
    assert two is not None

    assert_location(one.location, line=1, column=5, offset=4)
    assert_location(two.location, line=2, column=5, offset=13)

    # adding a linebreak at top should keep columns same
    tu = get_tu('\n' + baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert one is not None
    assert two is not None

    assert_location(one.location, line=2, column=5, offset=5)
    assert_location(two.location, line=3, column=5, offset=14)

    # adding a space should affect column on first line only
    tu = get_tu(' ' + baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert_location(one.location, line=1, column=6, offset=5)
    assert_location(two.location, line=2, column=5, offset=14)

    # define the expected location ourselves and see if it matches
    # the returned location
    tu = get_tu(baseInput)

    file = File.from_name(tu, 't.c')
    location = SourceLocation.from_position(tu, file, 1, 5)
    cursor = Cursor.from_location(tu, location)

    one = get_cursor(tu, 'one')
    assert one is not None
    assert one == cursor

    # Ensure locations referring to the same entity are equivalent.
    location2 = SourceLocation.from_position(tu, file, 1, 5)
    assert location == location2
    location3 = SourceLocation.from_position(tu, file, 1, 4)
    assert location2 != location3

    offset_location = SourceLocation.from_offset(tu, file, 5)
    cursor = Cursor.from_location(tu, offset_location)
    verified = False
    for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']:
        assert n == cursor
        verified = True

    assert verified
コード例 #2
0
ファイル: test_location.py プロジェクト: sourabhmisal/sealang
def test_location():
    tu = get_tu(baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert one is not None
    assert two is not None

    assert_location(one.location, line=1, column=5, offset=4)
    assert_location(two.location, line=2, column=5, offset=13)

    # adding a linebreak at top should keep columns same
    tu = get_tu('\n' + baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert one is not None
    assert two is not None

    assert_location(one.location, line=2, column=5, offset=5)
    assert_location(two.location, line=3, column=5, offset=14)

    # adding a space should affect column on first line only
    tu = get_tu(' ' + baseInput)
    one = get_cursor(tu, 'one')
    two = get_cursor(tu, 'two')

    assert_location(one.location, line=1, column=6, offset=5)
    assert_location(two.location, line=2, column=5, offset=14)

    # define the expected location ourselves and see if it matches
    # the returned location
    tu = get_tu(baseInput)

    file = File.from_name(tu, 't.c')
    location = SourceLocation.from_position(tu, file, 1, 5)
    cursor = Cursor.from_location(tu, location)

    one = get_cursor(tu, 'one')
    assert one is not None
    assert one == cursor

    # Ensure locations referring to the same entity are equivalent.
    location2 = SourceLocation.from_position(tu, file, 1, 5)
    assert location == location2
    location3 = SourceLocation.from_position(tu, file, 1, 4)
    assert location2 != location3

    offset_location = SourceLocation.from_offset(tu, file, 5)
    cursor = Cursor.from_location(tu, offset_location)
    verified = False
    for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']:
        assert n == cursor
        verified = True

    assert verified
コード例 #3
0
def generateDoxygenForSourceLocation(line, col):
  filename = vim.current.buffer.name

  index = Index.create()
  tu = index.parse(filename, vim.eval("g:clang_doxygen_clang_args"), [(filename, "\n".join(vim.current.buffer[:]))])

  # Skip whitespace at beginning of line
  indent = re.match(r'^\s*', vim.current.buffer[line - 1]).span()[1]
  col = max(col, indent + 1)

  c = Cursor.from_location(tu, SourceLocation.from_position(tu, File.from_name(tu, filename), line, col))

  # If there is no declaration at the source location try to find the nearest one.
  while c is not None:
    # If cursor is on a TypeRef in a FunctionTemplate, manually go backward in the source.
    if c.kind == CursorKind.TYPE_REF:
      pLine, pCol = previousSourceLocation(c.extent.start.line, c.extent.start.column)
      c = Cursor.from_location(tu, SourceLocation.from_position(tu, File.from_name(tu, filename), pLine, pCol))
      continue
    # If cursor is on a NamespaceRef, manually go forward in the source.
    elif c.kind == CursorKind.NAMESPACE_REF:
      nLine, nCol = nextSourceLocation(c.extent.end.line, c.extent.end.column)
      c = Cursor.from_location(tu, SourceLocation.from_position(tu, File.from_name(tu, filename), nLine, nCol))
      continue
    elif c.kind == CursorKind.FUNCTION_DECL:
      return handleFunctionDecl(c)
    elif c.kind == CursorKind.CXX_METHOD:
      return handleFunctionDecl(c)
    elif c.kind == CursorKind.CONSTRUCTOR:
      return handleFunctionDecl(c)
    elif c.kind == CursorKind.DESTRUCTOR:
      return handleFunctionDecl(c)
    elif c.kind == CursorKind.FUNCTION_TEMPLATE:
      return handleFunctionTemplate(c)
    elif c.kind == CursorKind.CLASS_DECL:
      return handleClassDecl(c)
    elif c.kind == CursorKind.CLASS_TEMPLATE:
      return handleClassDecl(c)
    elif c.kind == CursorKind.OBJC_INSTANCE_METHOD_DECL:
      return handleFunctionDecl(c)
    elif c.kind == CursorKind.OBJC_INTERFACE_DECL:
      return handleClassDecl(c)
    elif c.kind == CursorKind.OBJC_CATEGORY_DECL:
      return handleClassDecl(c)
    elif c.kind == CursorKind.OBJC_IMPLEMENTATION_DECL:
      return handleClassDecl(c)
    # Cursor is not on a supported type, go to the lexical parent
    else:
      c = c.lexical_parent

  if c is None:
    print "Error: No supported declaration found at %s:%i,%i.\n" % (filename, line, col)
    return (None, None)
コード例 #4
0
ファイル: libclang.py プロジェクト: looseyi/k-vim
def gotoDeclaration(preview=True):
  global debug
  debug = int(vim.eval("g:clang_debug")) == 1
  params = getCompileParams(vim.current.buffer.name)
  line, col = vim.current.window.cursor
  timer = CodeCompleteTimer(debug, vim.current.buffer.name, line, col, params)

  with libclangLock:
    tu = getCurrentTranslationUnit(params['args'], getCurrentFile(),
                                   vim.current.buffer.name, timer,
                                   update = True)
    if tu is None:
      print("Couldn't get the TranslationUnit")
      return

    f = File.from_name(tu, vim.current.buffer.name)
    loc = SourceLocation.from_position(tu, f, line, col + 1)
    cursor = Cursor.from_location(tu, loc)
    defs = [cursor.get_definition(), cursor.referenced]

    for d in defs:
      if d is not None and loc != d.location:
        loc = d.location
        if loc.file is not None:
          jumpToLocation(loc.file.name, loc.line, loc.column, preview)
        break

  timer.finish()
コード例 #5
0
ファイル: libclang.py プロジェクト: rahul13ramesh/Vim__files
def gotoDeclaration(preview=True):
    global debug
    debug = int(vim.eval("g:clang_debug")) == 1
    params = getCompileParams(vim.current.buffer.name)
    line, col = vim.current.window.cursor
    timer = CodeCompleteTimer(debug, vim.current.buffer.name, line, col,
                              params)

    with libclangLock:
        tu = getCurrentTranslationUnit(params['args'],
                                       getCurrentFile(),
                                       vim.current.buffer.name,
                                       timer,
                                       update=True)
        if tu is None:
            print("Couldn't get the TranslationUnit")
            return

        f = File.from_name(tu, vim.current.buffer.name)
        loc = SourceLocation.from_position(tu, f, line, col + 1)
        cursor = Cursor.from_location(tu, loc)
        defs = [cursor.get_definition(), cursor.referenced]

        for d in defs:
            if d is not None and loc != d.location:
                loc = d.location
                if loc.file is not None:
                    jumpToLocation(loc.file.name, loc.line, loc.column,
                                   preview)
                break

    timer.finish()
コード例 #6
0
ファイル: project.py プロジェクト: SkidanovAlex/py-ctrlk
    def get_usr_under_cursor(self, file_name, line, col):
        with self.c_parse_lock:
            if file_name not in self.current_file_tus:
                return ""
            tu = self.current_file_tus[file_name]
        f = File.from_name(tu, file_name)
        loc = SourceLocation.from_position(tu, f, int(line), int(col))
        cursor = Cursor.from_location(tu, loc)

        while cursor is not None and (not cursor.referenced
                                      or not cursor.referenced.get_usr()):
            nextCursor = cursor.lexical_parent
            if nextCursor is not None and nextCursor == cursor:
                return ""
            cursor = nextCursor
        if cursor is None:
            return ""

        cursor = cursor.referenced
        if cursor is None:
            return ""

        return {
            'usr': cursor.get_usr(),
            'file': str(cursor.location.file),
            'line': cursor.location.line,
            'column': cursor.location.column
        }
コード例 #7
0
ファイル: references.py プロジェクト: organicnz/nuclide
def local_references(libclang, translation_unit, path, line, column):
    source_location = translation_unit.get_location(path, (line, column))
    cursor = Cursor.from_location(translation_unit, source_location)
    if cursor is None:
        return None
    if cursor.referenced is not None:
        cursor = cursor.referenced
    if cursor.kind == CursorKind.NO_DECL_FOUND:
        return None

    references = []

    def visitor(_context, cursor, source_range):
        range_dict = range_dict_relative(source_range)
        # The end location is non-inclusive.
        range_dict['end']['column'] -= 1
        references.append(range_dict)
        return 1  # continue

    visitor_obj = CXCursorAndRangeVisitor()
    visitor_obj.visit = CFUNCTYPE(c_int, c_void_p, Cursor,
                                  SourceRange)(visitor)
    libclang.clang_findReferencesInFile(cursor, source_location.file,
                                        visitor_obj)
    return {
        'cursor_name': cursor.spelling,
        'cursor_kind': cursor.kind.name,
        'references': references,
    }
コード例 #8
0
ファイル: common.py プロジェクト: kennytm/mozart2-gtk3
def name_of(node):
    spelling = node.spelling.decode('utf-8')
    if spelling:
        return spelling

    typedef_node = Cursor.from_location(node.translation_unit, node.extent.end)
    if typedef_node.kind == CursorKind.TYPEDEF_DECL:
        return name_of(typedef_node)
    else:
        return ''
コード例 #9
0
ファイル: common.py プロジェクト: noware/mozart2-gtk3
def name_of(node):
    spelling = node.spelling.decode('utf-8')
    if spelling:
        return spelling

    typedef_node = Cursor.from_location(node.translation_unit, node.extent.end)
    if typedef_node.kind == CursorKind.TYPEDEF_DECL:
        return name_of(typedef_node)
    else:
        return ''
コード例 #10
0
ファイル: ctrlk_plugin.py プロジェクト: SkidanovAlex/CtrlK
def GetCurrentUsrCursor(tu):
    line, col = vim.current.window.cursor
    col = col + 1
    f = File.from_name(tu, vim.current.buffer.name)
    loc = SourceLocation.from_position(tu, f, line, col)
    cursor = Cursor.from_location(tu, loc)

    while cursor is not None and (not cursor.referenced or not cursor.referenced.get_usr()):
        nextCursor = cursor.lexical_parent
        if nextCursor is not None and nextCursor == cursor:
            return None
        cursor = nextCursor
    if cursor is None:
        return None
    return cursor.referenced
コード例 #11
0
ファイル: clang_server.py プロジェクト: yuanyeyuanye/nuclide
    def get_declaration_info(self, request):
        contents = request['contents']
        line = request['line']
        column = request['column']

        # Update the translation unit with the latest contents.
        translation_unit = self._update_translation_unit(contents)
        if not translation_unit:
            return None

        location = translation_unit.get_location(self.src, (line + 1, column + 1))
        cursor = Cursor.from_location(translation_unit, location)
        cursor = cursor.referenced
        if cursor is None:
            return None

        return self.get_declaration_info_for_cursor(cursor)
コード例 #12
0
ファイル: to_cc.py プロジェクト: kennytm/mozart2-gtk3
def convert_canonical(typ):
    decl = typ.get_declaration()
    struct_name = decl.displayname.decode('utf-8')
    if not struct_name:
        typedef_node = Cursor.from_location(decl.translation_unit, decl.extent.end)
        if typedef_node.kind == CursorKind.TYPEDEF_DECL:
            struct_name = typedef_node.displayname.decode('utf-8')

    if struct_name:
        sb = [struct_name]
    else:
        sb = [RECORD_KEYWORD[decl.kind], ' { ']
        for node in decl.get_children():
            name = node.spelling.decode('utf-8')
            sb.append(to_cc(node.type, name))
            sb.append('; ')
        sb.append('}')
    return (''.join(sb), '', '')
コード例 #13
0
    def find_declaration(self, data, lines):
        self.join_queue()

        context = data['context']
        src = self.get_src("\n".join(lines), context)
        filepath = context['filepath']
        bcol = context['bcol']
        lnum = context['lnum']

        args, directory = self.get_args_dir(data)

        tu = self.get_tu(filepath, args, directory, src)

        f = File.from_name(tu, filepath)
        location = SourceLocation.from_position(tu, f, lnum, bcol)
        cursor = Cursor.from_location(tu, location)

        defs = [cursor.get_definition(), cursor.referenced]
        for d in defs:
            if d is None:
                logger.info("d None")
                continue

            d_loc = d.location
            if d_loc.file is None:
                logger.info("location.file None")
                continue

            ret = {}
            ret['file'] = d_loc.file.name
            ret['lnum'] = d_loc.line
            ret['bcol'] = d_loc.column
            return ret

        # we failed finding the declaration, maybe there's some syntax error
        # stopping us. Report it to the user.
        logger.info('reading Diagnostic for this tu, args: %s', args)
        for diag in tu.diagnostics:
            # type: Diagnostic
            if diag.severity < diag.Error:
                pass
            self.nvim.call('ncm2_pyclang#error', diag.format())
        return {}
コード例 #14
0
ファイル: project.py プロジェクト: SkidanovAlex/py-ctrlk
    def get_usr_under_cursor(self, file_name, line, col):
        with self.c_parse_lock:
            if file_name not in self.current_file_tus:
                return ""
            tu = self.current_file_tus[file_name]
        f = File.from_name(tu, file_name)
        loc = SourceLocation.from_position(tu, f, int(line), int(col))
        cursor = Cursor.from_location(tu, loc)

        while cursor is not None and (not cursor.referenced or not cursor.referenced.get_usr()):
            nextCursor = cursor.lexical_parent
            if nextCursor is not None and nextCursor == cursor:
                return ""
            cursor = nextCursor
        if cursor is None:
            return ""

        cursor = cursor.referenced
        if cursor is None:
            return ""

        return {'usr': cursor.get_usr(), 'file': str(cursor.location.file), 'line': cursor.location.line, 'column': cursor.location.column}
コード例 #15
0
ファイル: libclang.py プロジェクト: roxma/clang_complete
  def gotoDeclaration(self, preview=True):
    params = self.getCompileParams(self.vim.current.buffer.name)
    line, col = self.vim.current.window.cursor

    tu = self.getCurrentTranslationUnit(params['args'], self.getCurrentFile(),
                                   self.vim.current.buffer.name,
                                   update = True)
    if tu is None:
      print("Couldn't get the TranslationUnit")
      return

    f      = File.from_name(tu, self.vim.current.buffer.name)
    loc    = SourceLocation.from_position(tu, f, line, col + 1)
    cursor = Cursor.from_location(tu, loc)
    defs   = [cursor.get_definition(), cursor.referenced]

    for d in defs:
      if d is not None and loc != d.location:
        loc = d.location
        if loc.file is not None:
          self.jumpToLocation(loc.file.name, loc.line, loc.column, preview)
        break
コード例 #16
0
def test_location():
    index = Index.create()
    tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])

    for n in tu.cursor.get_children():
        if n.spelling == 'one':
            assert_location(n.location,line=1,column=5,offset=4)
        if n.spelling == 'two':
            assert_location(n.location,line=2,column=5,offset=13)

    # adding a linebreak at top should keep columns same
    tu = index.parse('t.c', unsaved_files = [('t.c',"\n"+baseInput)])

    for n in tu.cursor.get_children():
        if n.spelling == 'one':
            assert_location(n.location,line=2,column=5,offset=5)
        if n.spelling == 'two':
            assert_location(n.location,line=3,column=5,offset=14)

    # adding a space should affect column on first line only
    tu = index.parse('t.c', unsaved_files = [('t.c'," "+baseInput)])

    for n in tu.cursor.get_children():
        if n.spelling == 'one':
            assert_location(n.location,line=1,column=6,offset=5)
        if n.spelling == 'two':
            assert_location(n.location,line=2,column=5,offset=14)

    # define the expected location ourselves and see if it matches
    # the returned location
    tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])

    file = File.from_name(tu, 't.c')
    location = SourceLocation.from_position(tu, file, 1, 5)
    cursor = Cursor.from_location(tu, location)

    for n in tu.cursor.get_children():
        if n.spelling == 'one':
            assert n == cursor
コード例 #17
0
ファイル: references.py プロジェクト: JoelMarcey/nuclide
def local_references(libclang, translation_unit, path, line, column):
    source_location = translation_unit.get_location(path, (line, column))
    cursor = Cursor.from_location(translation_unit, source_location)
    if cursor is None:
        return None
    if cursor.referenced is not None:
        cursor = cursor.referenced
    if cursor.kind == CursorKind.NO_DECL_FOUND:
        return None

    references = []

    def visitor(_context, cursor, source_range):
        references.append(range_dict_relative(source_range))
        return 1  # continue

    visitor_obj = CXCursorAndRangeVisitor()
    visitor_obj.visit = CFUNCTYPE(c_int, c_void_p, Cursor, SourceRange)(visitor)
    libclang.clang_findReferencesInFile(cursor, source_location.file, visitor_obj)
    return {
        'cursor_name': cursor.spelling,
        'cursor_kind': cursor.kind.name,
        'references': references,
    }
コード例 #18
0
ファイル: trace.py プロジェクト: bstee615/pal-tools
def get_static_locations(dynamic_locations, clang_include_paths):
    """
    Get locations for certain constructs which are only available statically.
    - Variable declarations without any executable code "int i;"
    - Case statements "case foo:"
    - Default statements "default: "
    """
    static_locations = []

    def ancestor_node(n):
        """
        Get the nearest significant ancestor.
        """
        if n.kind == CursorKind.FUNCTION_DECL:
            return n
        else:
            if n.semantic_parent is None:
                return n
            else:
                return ancestor_node(n.semantic_parent)

    def good(n):
        """
        Node should be added to the trace.
        """
        if n.kind in (CursorKind.VAR_DECL, CursorKind.CASE_STMT,
                      CursorKind.DEFAULT_STMT):
            return True
        else:
            return False

    filepaths = defaultdict(list)
    for l in dynamic_locations:
        filepaths[l.filepath].append(l)
    for filepath, locations in filepaths.items():
        log.debug(
            f'Parsing source file {filepath} with args {clang_include_paths}')
        root = nodeutils.parse(filepath, clang_include_paths)
        ancestors = []
        file = File.from_name(root.translation_unit, filepath)
        for l in locations:
            source_location = SourceLocation.from_position(
                root.translation_unit, file, l.lineno, l.column)
            node = Cursor.from_location(root.translation_unit, source_location)
            l.node = node
            if node.kind.is_invalid():
                continue
            ancestor = ancestor_node(node)
            if ancestor not in ancestors:
                log.debug(
                    f'node {nodeutils.pp(node)} has ancestor {nodeutils.pp(ancestor)}'
                )
                ancestors.append(ancestor)
        for a in ancestors:
            if a.kind.is_translation_unit():
                continue  # Do not include global constructs
            else:
                nodes = nodeutils.find(a, good)
                locations = [
                    Location(n.location.file.name, n.location.line,
                             n.location.column, n) for n in nodes
                ]
                for l in locations:
                    log.debug(f'static location {l}')
                static_locations += locations

    return static_locations
コード例 #19
0
ファイル: make_index.py プロジェクト: bholt/textmate-linguist
 def cursor(self):
   """
   Get a Cursor object for TextMate's current cursor point (file,line,column).
   """
   return Cursor.from_location(self.tu, self.tu.get_location(env['TM_FILEPATH'],
     ( int(env['TM_LINE_NUMBER']), int(env['TM_COLUMN_NUMBER'])-1 ) ))
コード例 #20
0
 def get_function_at(self, line_no):
     loc = self.translation_unit.get_location(self.source_file,
                                              (line_no, -1))
     cursor = Cursor.from_location(self.translation_unit, loc)
     return self._get_function_rec(cursor)
コード例 #21
0
def get_declaration_location_and_spelling(translation_unit, contents, flags,
                                          absolute_path, line, column):
    def log(s):
        logger.info('%s:%d:%d - %s', os.path.basename(absolute_path), line,
                    column, s)

    source_location = translation_unit.get_location(absolute_path,
                                                    (line, column))
    cursor = Cursor.from_location(translation_unit, source_location)
    if cursor is None:
        log('No cursor')
        return None

    # Don't allow clicks/tooltips on most declarations, as their content is usually obvious.
    # Make an exception for variable declarations, as these can often have auto types.
    if cursor.kind != CursorKind.VAR_DECL and cursor.kind.is_declaration():
        log('Ignoring declaration')
        return None

    referenced = cursor.referenced
    if referenced is None or referenced.location is None or referenced.location.file is None:
        # If cursor is over an include statement, attempt to resolve the location
        # of the included file.
        line_text = get_line(contents, line)
        bounds = get_include_path_extent(line_text)

        if bounds is not None:
            start_col, end_col = bounds
            # Don't allow hyperclick if cursor is not over the include name, i.e.:
            # #include "header.h"
            #          ^^^^^^^^
            if column < start_col or column > end_col:
                return None

            filename = resolve_include(absolute_path, line_text, flags)
            if filename is None:
                return None
            # Point location to beginning of the found included file (line 0, column 0)
            location = {
                'file': filename,
                'line': 0,
                'column': 0,
                # Show destination file of hyperclick in hover popover
                'type': filename,
                'spelling': None,
                'extent': {
                    'start': {
                        'line': line - 1,
                        'column': start_col
                    },
                    'end': {
                        'line': line - 1,
                        'column': end_col
                    }
                }
            }
            return location
        else:
            log('No referenced information')
            return None

    loc = referenced.location
    log('Returning {0}:{1}:{2}'.format(os.path.basename(loc.file.name),
                                       loc.line, loc.column))

    # An extent has a `start` and `end` property, each of which have a `line`
    # and `column` property.
    extent = cursor.extent

    type = None
    try:
        type = cursor.type and cursor.type.spelling
    except:
        logger.warn('Was not able to get cursor type')
        pass

    location = location_dict(loc)
    location['spelling'] = cursor.spelling
    location['type'] = type
    location['extent'] = range_dict(extent)
    return location
コード例 #22
0
def get_declaration_location_and_spelling(translation_unit, contents, flags,
                                          absolute_path, line, column):
    def log(s):
        logger.info('%s:%d:%d - %s',
                    os.path.basename(absolute_path), line, column, s)

    source_location = translation_unit.get_location(
        absolute_path, (line, column))
    cursor = Cursor.from_location(translation_unit, source_location)
    if cursor is None:
        log('No cursor')
        return None

    # Don't allow clicks/tooltips on most declarations, as their content is usually obvious.
    # Make an exception for variable declarations, as these can often have auto types.
    if cursor.kind != CursorKind.VAR_DECL and cursor.kind.is_declaration():
        log('Ignoring declaration')
        return None

    referenced = cursor.referenced
    if referenced is None or referenced.location is None or referenced.location.file is None:
        # If cursor is over an include statement, attempt to resolve the location
        # of the included file.
        line_text = get_line(contents, line)
        bounds = get_include_path_extent(line_text)

        if bounds is not None:
            start_col, end_col = bounds
            # Don't allow hyperclick if cursor is not over the include name, i.e.:
            # #include "header.h"
            #          ^^^^^^^^
            if column < start_col or column > end_col:
                return None

            filename = resolve_include(absolute_path, line_text, flags)
            if filename is None:
                return None
            # Point location to beginning of the found included file (line 0, column 0)
            location = {
                'file': filename,
                'point': {
                    'row': 0,
                    'column': 0,
                },
                # Show destination file of hyperclick in hover popover
                'type': filename,
                'spelling': None,
                'extent': {
                    'start': {'row': line - 1, 'column': start_col},
                    'end': {'row': line - 1, 'column': end_col}
                }
            }
            return location
        else:
            log('No referenced information')
            return None

    loc = referenced.location
    log('Returning {0}:{1}:{2}'.format(
        os.path.basename(loc.file.name), loc.line, loc.column))

    # An extent has a `start` and `end` property, each of which have a `line`
    # and `column` property.
    extent = cursor.extent

    type = None
    try:
        type = cursor.type and cursor.type.spelling
    except:
        logger.warn('Was not able to get cursor type')
        pass

    location = location_dict(loc)
    location['spelling'] = cursor.spelling
    location['type'] = type
    location['extent'] = range_dict_relative(extent)
    return location