resolve exception aliases

This commit is contained in:
Robin Appelman 2024-07-22 22:17:54 +02:00
commit a0dc7450a4
2 changed files with 75 additions and 20 deletions

View file

@ -1,11 +1,13 @@
use crate::messagebuilder::MessageBuilder; use crate::messagebuilder::MessageBuilder;
use crate::{LogLevel, LoggingStatement}; use crate::{LogLevel, LoggingStatement};
use std::collections::HashMap;
use tree_sitter::{Language, Node, Parser, Query, QueryCursor}; use tree_sitter::{Language, Node, Parser, Query, QueryCursor};
pub struct LogExtractor { pub struct LogExtractor {
language: Language, language: Language,
method_query: Query, method_query: Query,
throw_query: Query, throw_query: Query,
use_query: Query,
} }
impl LogExtractor { impl LogExtractor {
@ -29,10 +31,19 @@ impl LogExtractor {
)"#, )"#,
) )
.expect("invalid query"); .expect("invalid query");
let use_query = Query::new(
&language,
r#"(namespace_use_clause
[(name) (qualified_name)] @name
(namespace_aliasing_clause (name) @alias)?
)"#,
)
.expect("invalid query");
LogExtractor { LogExtractor {
language, language,
method_query, method_query,
throw_query, throw_query,
use_query,
} }
} }
@ -52,6 +63,9 @@ impl LogExtractor {
let mut log_call_cursor = QueryCursor::new(); let mut log_call_cursor = QueryCursor::new();
let mut throw_call_cursor = QueryCursor::new(); let mut throw_call_cursor = QueryCursor::new();
let aliases = self.get_aliases(&mut log_call_cursor, code, tree.root_node());
let log_calls = self.get_log_calls(&mut log_call_cursor, code, tree.root_node()); let log_calls = self.get_log_calls(&mut log_call_cursor, code, tree.root_node());
let throw_calls = self.get_throw_calls(&mut throw_call_cursor, code, tree.root_node()); let throw_calls = self.get_throw_calls(&mut throw_call_cursor, code, tree.root_node());
let mut all = log_calls let mut all = log_calls
@ -64,12 +78,20 @@ impl LogExtractor {
message_builder.push_node(argument, code); message_builder.push_node(argument, code);
} }
let exception = call.exception.map(|exception| {
aliases
.get(exception.as_str())
.copied()
.map(String::from)
.unwrap_or(exception)
});
Some(LoggingStatement { Some(LoggingStatement {
level: call.level, level: call.level,
line: call.line + 1, line: call.line + 1,
path, path,
has_meaningful_message: message_builder.is_meaningful(), has_meaningful_message: message_builder.is_meaningful(),
exception: call.exception, exception,
message_parts: message_builder.into(), message_parts: message_builder.into(),
}) })
}) })
@ -131,6 +153,37 @@ impl LogExtractor {
} }
}) })
} }
fn get_aliases<'a>(
&'a self,
cursor: &mut QueryCursor,
code: &'a str,
node: Node<'a>,
) -> HashMap<&'a str, &'a str> {
let use_calls = cursor.matches(&self.use_query, node, code.as_bytes());
use_calls
.map(|method_call| {
let source = method_call.captures[0]
.node
.utf8_text(code.as_bytes())
.unwrap_or("malformed utf8")
.trim_start_matches('\\');
let target = method_call
.captures
.get(1)
.map(|capture| {
capture
.node
.utf8_text(code.as_bytes())
.expect("invalid utf8")
})
.unwrap_or_else(|| source.rsplit('\\').next().unwrap());
(target, source)
})
.collect()
}
} }
impl Default for LogExtractor { impl Default for LogExtractor {
@ -151,6 +204,8 @@ fn test_extract_logging() {
use crate::MessagePart; use crate::MessagePart;
let code = r#"<?php let code = r#"<?php
use Bar\BarException;
use \Foo\Exception as FooException;
function test() { function test() {
$this->logger->warning("failed to find trash item for $rootTrashedItemName deleted at $rootTrashedItemDate in folder $groupFolderId", ['app' => 'groupfolders']); $this->logger->warning("failed to find trash item for $rootTrashedItemName deleted at $rootTrashedItemDate in folder $groupFolderId", ['app' => 'groupfolders']);
$logger->info('foobar'); $logger->info('foobar');
@ -166,7 +221,7 @@ fn test_extract_logging() {
logs[0], logs[0],
LoggingStatement { LoggingStatement {
path: "foo.php", path: "foo.php",
line: 3, line: 5,
level: LogLevel::Warn, level: LogLevel::Warn,
has_meaningful_message: true, has_meaningful_message: true,
exception: None, exception: None,
@ -184,7 +239,7 @@ fn test_extract_logging() {
logs[1], logs[1],
LoggingStatement { LoggingStatement {
path: "foo.php", path: "foo.php",
line: 4, line: 6,
level: LogLevel::Info, level: LogLevel::Info,
has_meaningful_message: true, has_meaningful_message: true,
exception: None, exception: None,
@ -195,10 +250,10 @@ fn test_extract_logging() {
logs[2], logs[2],
LoggingStatement { LoggingStatement {
path: "foo.php", path: "foo.php",
line: 5, line: 7,
level: LogLevel::Exception, level: LogLevel::Exception,
has_meaningful_message: true, has_meaningful_message: true,
exception: Some("FooException".into()), exception: Some("Foo\\Exception".into()),
message_parts: vec![ message_parts: vec![
MessagePart::Literal(r#"foo "bar" \' "#.into()), MessagePart::Literal(r#"foo "bar" \' "#.into()),
MessagePart::PlaceHolder("$this->blarg".into()) MessagePart::PlaceHolder("$this->blarg".into())
@ -209,10 +264,10 @@ fn test_extract_logging() {
logs[3], logs[3],
LoggingStatement { LoggingStatement {
path: "foo.php", path: "foo.php",
line: 6, line: 8,
level: LogLevel::Exception, level: LogLevel::Exception,
has_meaningful_message: false, has_meaningful_message: false,
exception: Some("BarException".into()), exception: Some("Bar\\BarException".into()),
message_parts: vec![] message_parts: vec![]
} }
); );
@ -220,7 +275,7 @@ fn test_extract_logging() {
logs[4], logs[4],
LoggingStatement { LoggingStatement {
path: "foo.php", path: "foo.php",
line: 7, line: 9,
level: LogLevel::Error, level: LogLevel::Error,
has_meaningful_message: true, has_meaningful_message: true,
exception: None, exception: None,

View file

@ -20,7 +20,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 305, "line": 305,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Group \"" "Literal": "Group \""
@ -38,7 +38,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 309, "line": 309,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Recipient not in receiving group" "Literal": "Recipient not in receiving group"
@ -50,7 +50,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 339, "line": 339,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Recipient does not match" "Literal": "Recipient does not match"
@ -62,7 +62,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 344, "line": 344,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Invalid shareType" "Literal": "Invalid shareType"
@ -74,7 +74,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 431, "line": 431,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Group \"" "Literal": "Group \""
@ -92,7 +92,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 476, "line": 476,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Recipient does not match" "Literal": "Recipient does not match"
@ -104,7 +104,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 482, "line": 482,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "ProviderException", "exception": "OC\\Share20\\Exception\\ProviderException",
"message_parts": [ "message_parts": [
{ {
"Literal": "Invalid shareType" "Literal": "Invalid shareType"
@ -128,7 +128,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 763, "line": 763,
"has_meaningful_message": false, "has_meaningful_message": false,
"exception": "ShareNotFound", "exception": "OCP\\Share\\Exceptions\\ShareNotFound",
"message_parts": [] "message_parts": []
}, },
{ {
@ -136,7 +136,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 769, "line": 769,
"has_meaningful_message": false, "has_meaningful_message": false,
"exception": "ShareNotFound", "exception": "OCP\\Share\\Exceptions\\ShareNotFound",
"message_parts": [] "message_parts": []
}, },
{ {
@ -144,7 +144,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 963, "line": 963,
"has_meaningful_message": true, "has_meaningful_message": true,
"exception": "BackendError", "exception": "OC\\Share20\\Exception\\BackendError",
"message_parts": [ "message_parts": [
{ {
"Literal": "Invalid backend" "Literal": "Invalid backend"
@ -156,7 +156,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 993, "line": 993,
"has_meaningful_message": false, "has_meaningful_message": false,
"exception": "ShareNotFound", "exception": "OCP\\Share\\Exceptions\\ShareNotFound",
"message_parts": [] "message_parts": []
}, },
{ {
@ -164,7 +164,7 @@ expression: output
"path": "/DefaultShareProvider.php", "path": "/DefaultShareProvider.php",
"line": 999, "line": 999,
"has_meaningful_message": false, "has_meaningful_message": false,
"exception": "ShareNotFound", "exception": "OCP\\Share\\Exceptions\\ShareNotFound",
"message_parts": [] "message_parts": []
}, },
{ {