"""Definition targets for literal TclOO classes and resolved method calls.""" from tools.tcloo_completion import _analyze, may_contain_classes, name_location, parse_completion_source from tools.tcloo_symbols import class_symbols def tcloo_definition(source, uri, position, external_classes=None, tree=None): if not may_contain_classes(source, external_classes): return None if tree is None: tree = parse_completion_source(source) if tree is None: return None classes, _, calls = _analyze(tree, external_classes=external_classes, uri=uri, source=source) def contains(location): if location is None: return False start, end = location.range.start, location.range.end return (start.line, start.character) <= (position.line, position.character) < (end.line, end.character) targets = {} declarations, references = class_symbols(tree, classes, targets) for node in references: if contains(name_location(node, uri, source)): return classes[targets[node.pos]].definition for name, node in declarations.items(): if contains(name_location(node, uri, source)): return classes[name].definition for call in calls: if call.command.args and contains(name_location(call.command.args[0], uri, source)): return call.definition # F12 on a declaration itself should stay on that declaration. for info in classes.values(): for location in [*info.method_definitions.values(), info.constructor_definition]: if location is not None and location.uri == uri and contains(location): return location return None