def get_rule_range(document: str, pos: lsp.Position) -> lsp.Range: '''Get the range of the YARA rule that a given symbol is in :document: Text to search in To determine line numbers, text is split at newlines, and carriage returns are ignored :pos: Symbol position to base range off of ''' start_pattern = re.compile(r"^((private|global) )?rule\b") end_pattern = re.compile("^}$") lines = document.replace("\r", "").split("\n") # default to assuming the entire document is within range start_pos = lsp.Position(line=0, char=0) end_pos = lsp.Position(line=len(lines), char=0) # work backwards from the given position and find the start of rule for index in range(pos.line, 0, -1): line = lines[index] match = start_pattern.match(line) if match: start_pos = lsp.Position(line=index, char=0) break # start from the given position and find the first end of rule for index in range(pos.line, len(lines)): line = lines[index] match = end_pattern.match(line) if match: end_pos = lsp.Position(line=index, char=0) break return lsp.Range(start=start_pos, end=end_pos)
def test_range(): ''' Ensure Range is properly encoded to JSON dictionaries ''' pos_dict = {"line": 10, "character": 15} pos = protocol.Position(line=pos_dict["line"], char=pos_dict["character"]) rg_dict = {"start": pos_dict, "end": pos_dict} rg_obj = protocol.Range(start=pos, end=pos) assert json.dumps(rg_obj, cls=protocol.JSONEncoder) == json.dumps(rg_dict)
def test_location(): ''' Ensure Location is properly encoded to JSON dictionaries ''' pos_dict = {"line": 10, "character": 15} pos = protocol.Position(line=pos_dict["line"], char=pos_dict["character"]) rg_dict = {"start": pos_dict, "end": pos_dict} rg_obj = protocol.Range(start=pos, end=pos) loc_dict = {"range": rg_dict, "uri": "fake:///one/two/three/four.path"} loc = protocol.Location(locrange=rg_obj, uri=loc_dict["uri"]) assert json.dumps(loc, cls=protocol.JSONEncoder) == json.dumps(loc_dict)
def test_get_rule_range(test_rules): ''' Ensure YARA rules are parsed out and their range is returned ''' peek_rules = test_rules.joinpath("peek_rules.yara").resolve() rules = peek_rules.read_text() pos = protocol.Position(line=42, char=12) result = helpers.get_rule_range(rules, pos) assert isinstance(result, protocol.Range) is True assert result.start.line == 33 assert result.start.char == 0 assert result.end.line == 43 assert result.end.char == 0
def test_diagnostic(): ''' Ensure Diagnostic is properly encoded to JSON dictionaries ''' pos_dict = {"line": 10, "character": 15} pos = protocol.Position(line=pos_dict["line"], char=pos_dict["character"]) rg_dict = {"start": pos_dict, "end": pos_dict} rg_obj = protocol.Range(start=pos, end=pos) diag_dict = { "message": "Test Diagnostic", "range": rg_dict, "relatedInformation": [], "severity": 1 } diag = protocol.Diagnostic(locrange=rg_obj, message=diag_dict["message"], severity=diag_dict["severity"]) assert json.dumps(diag, cls=protocol.JSONEncoder) == json.dumps(diag_dict)
def test_position(): ''' Ensure Position is properly encoded to JSON dictionaries ''' pos_dict = {"line": 10, "character": 15} pos = protocol.Position(line=pos_dict["line"], char=pos_dict["character"]) assert json.dumps(pos, cls=protocol.JSONEncoder) == json.dumps(pos_dict)
def test_resolve_symbol(): ''' Ensure symbols are properly resolved ''' document = "rule ResolveSymbol {\n strings:\n $a = \"test\"\n condition:\n #a > 3\n}\n" pos = protocol.Position(line=4, char=4) symbol = helpers.resolve_symbol(document, pos) assert symbol == "#a"