mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 18:14:11 +02:00
improve namespace handling
This commit is contained in:
parent
bc0bcf936c
commit
724c738a50
6 changed files with 148 additions and 17 deletions
7
logging-extractor/Cargo.lock
generated
7
logging-extractor/Cargo.lock
generated
|
|
@ -114,6 +114,7 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"databake",
|
"databake",
|
||||||
"insta",
|
"insta",
|
||||||
|
"maplit",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
|
|
@ -128,6 +129,12 @@ dependencies = [
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,6 @@ regex = "1.10.5"
|
||||||
cc = "1.1.6"
|
cc = "1.1.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
maplit = "1.0.2"
|
||||||
test-case = "3.3.1"
|
test-case = "3.3.1"
|
||||||
insta = { version = "1.39.0", features = ["json"] }
|
insta = { version = "1.39.0", features = ["json"] }
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::messagebuilder::MessageBuilder;
|
use crate::messagebuilder::MessageBuilder;
|
||||||
|
use crate::name_resolver::resolve_name;
|
||||||
use crate::{LogLevel, LoggingStatement};
|
use crate::{LogLevel, LoggingStatement};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tree_sitter::{Language, Node, Parser, Query, QueryCursor};
|
use tree_sitter::{Language, Node, Parser, Query, QueryCursor};
|
||||||
|
|
@ -8,6 +9,7 @@ pub struct LogExtractor {
|
||||||
method_query: Query,
|
method_query: Query,
|
||||||
throw_query: Query,
|
throw_query: Query,
|
||||||
use_query: Query,
|
use_query: Query,
|
||||||
|
namespace_query: Query,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogExtractor {
|
impl LogExtractor {
|
||||||
|
|
@ -39,11 +41,19 @@ impl LogExtractor {
|
||||||
)"#,
|
)"#,
|
||||||
)
|
)
|
||||||
.expect("invalid query");
|
.expect("invalid query");
|
||||||
|
let namespace_query = Query::new(
|
||||||
|
&language,
|
||||||
|
r#"(namespace_definition
|
||||||
|
name: (namespace_name) @name
|
||||||
|
)"#,
|
||||||
|
)
|
||||||
|
.expect("invalid query");
|
||||||
LogExtractor {
|
LogExtractor {
|
||||||
language,
|
language,
|
||||||
method_query,
|
method_query,
|
||||||
throw_query,
|
throw_query,
|
||||||
use_query,
|
use_query,
|
||||||
|
namespace_query,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,10 +74,12 @@ 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 root = tree.root_node();
|
||||||
|
let aliases = self.get_aliases(&mut log_call_cursor, code, root);
|
||||||
|
let namespace = self.get_namespace(&mut log_call_cursor, code, root);
|
||||||
|
|
||||||
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, root);
|
||||||
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, root);
|
||||||
let mut all = log_calls
|
let mut all = log_calls
|
||||||
.chain(throw_calls)
|
.chain(throw_calls)
|
||||||
.filter_map(|call| {
|
.filter_map(|call| {
|
||||||
|
|
@ -78,13 +90,9 @@ impl LogExtractor {
|
||||||
message_builder.push_node(argument, code);
|
message_builder.push_node(argument, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
let exception = call.exception.map(|exception| {
|
let exception = call
|
||||||
aliases
|
.exception
|
||||||
.get(exception.as_str())
|
.map(|exception| resolve_name(namespace, &aliases, exception.as_str()));
|
||||||
.copied()
|
|
||||||
.map(String::from)
|
|
||||||
.unwrap_or(exception)
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(LoggingStatement {
|
Some(LoggingStatement {
|
||||||
level: call.level,
|
level: call.level,
|
||||||
|
|
@ -184,6 +192,25 @@ impl LogExtractor {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_namespace<'a>(
|
||||||
|
&'a self,
|
||||||
|
cursor: &mut QueryCursor,
|
||||||
|
code: &'a str,
|
||||||
|
node: Node<'a>,
|
||||||
|
) -> &'a str {
|
||||||
|
let mut namespace = cursor.matches(&self.namespace_query, node, code.as_bytes());
|
||||||
|
|
||||||
|
namespace
|
||||||
|
.next()
|
||||||
|
.map(|namespace| {
|
||||||
|
namespace.captures[0]
|
||||||
|
.node
|
||||||
|
.utf8_text(code.as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.unwrap_or("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LogExtractor {
|
impl Default for LogExtractor {
|
||||||
|
|
@ -204,14 +231,19 @@ fn test_extract_logging() {
|
||||||
use crate::MessagePart;
|
use crate::MessagePart;
|
||||||
|
|
||||||
let code = r#"<?php
|
let code = r#"<?php
|
||||||
|
namespace Test;
|
||||||
use Bar\BarException;
|
use Bar\BarException;
|
||||||
use \Foo\Exception as FooException;
|
use \Foo\Exception as FooException;
|
||||||
|
use Foo\Asd;
|
||||||
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');
|
||||||
throw new FooException("foo \"bar\" \' {$this->blarg}");
|
throw new FooException("foo \"bar\" \' {$this->blarg}");
|
||||||
throw new BarException();
|
throw new BarException();
|
||||||
$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
|
$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
|
||||||
|
throw new Asd\Exception();
|
||||||
|
throw new SomeException();
|
||||||
|
throw new \SomeException();
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
"#;
|
"#;
|
||||||
|
|
@ -221,7 +253,7 @@ fn test_extract_logging() {
|
||||||
logs[0],
|
logs[0],
|
||||||
LoggingStatement {
|
LoggingStatement {
|
||||||
path: "foo.php",
|
path: "foo.php",
|
||||||
line: 5,
|
line: 7,
|
||||||
level: LogLevel::Warn,
|
level: LogLevel::Warn,
|
||||||
has_meaningful_message: true,
|
has_meaningful_message: true,
|
||||||
exception: None,
|
exception: None,
|
||||||
|
|
@ -239,7 +271,7 @@ fn test_extract_logging() {
|
||||||
logs[1],
|
logs[1],
|
||||||
LoggingStatement {
|
LoggingStatement {
|
||||||
path: "foo.php",
|
path: "foo.php",
|
||||||
line: 6,
|
line: 8,
|
||||||
level: LogLevel::Info,
|
level: LogLevel::Info,
|
||||||
has_meaningful_message: true,
|
has_meaningful_message: true,
|
||||||
exception: None,
|
exception: None,
|
||||||
|
|
@ -250,7 +282,7 @@ fn test_extract_logging() {
|
||||||
logs[2],
|
logs[2],
|
||||||
LoggingStatement {
|
LoggingStatement {
|
||||||
path: "foo.php",
|
path: "foo.php",
|
||||||
line: 7,
|
line: 9,
|
||||||
level: LogLevel::Exception,
|
level: LogLevel::Exception,
|
||||||
has_meaningful_message: true,
|
has_meaningful_message: true,
|
||||||
exception: Some("Foo\\Exception".into()),
|
exception: Some("Foo\\Exception".into()),
|
||||||
|
|
@ -264,7 +296,7 @@ fn test_extract_logging() {
|
||||||
logs[3],
|
logs[3],
|
||||||
LoggingStatement {
|
LoggingStatement {
|
||||||
path: "foo.php",
|
path: "foo.php",
|
||||||
line: 8,
|
line: 10,
|
||||||
level: LogLevel::Exception,
|
level: LogLevel::Exception,
|
||||||
has_meaningful_message: false,
|
has_meaningful_message: false,
|
||||||
exception: Some("Bar\\BarException".into()),
|
exception: Some("Bar\\BarException".into()),
|
||||||
|
|
@ -275,7 +307,7 @@ fn test_extract_logging() {
|
||||||
logs[4],
|
logs[4],
|
||||||
LoggingStatement {
|
LoggingStatement {
|
||||||
path: "foo.php",
|
path: "foo.php",
|
||||||
line: 9,
|
line: 11,
|
||||||
level: LogLevel::Error,
|
level: LogLevel::Error,
|
||||||
has_meaningful_message: true,
|
has_meaningful_message: true,
|
||||||
exception: None,
|
exception: None,
|
||||||
|
|
@ -285,4 +317,37 @@ fn test_extract_logging() {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
logs[5],
|
||||||
|
LoggingStatement {
|
||||||
|
path: "foo.php",
|
||||||
|
line: 12,
|
||||||
|
level: LogLevel::Exception,
|
||||||
|
has_meaningful_message: false,
|
||||||
|
exception: Some("Foo\\Asd\\Exception".into()),
|
||||||
|
message_parts: vec![]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
logs[6],
|
||||||
|
LoggingStatement {
|
||||||
|
path: "foo.php",
|
||||||
|
line: 13,
|
||||||
|
level: LogLevel::Exception,
|
||||||
|
has_meaningful_message: false,
|
||||||
|
exception: Some("Test\\SomeException".into()),
|
||||||
|
message_parts: vec![]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
logs[7],
|
||||||
|
LoggingStatement {
|
||||||
|
path: "foo.php",
|
||||||
|
line: 14,
|
||||||
|
level: LogLevel::Exception,
|
||||||
|
has_meaningful_message: false,
|
||||||
|
exception: Some("SomeException".into()),
|
||||||
|
message_parts: vec![]
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ pub mod error;
|
||||||
pub mod extractor;
|
pub mod extractor;
|
||||||
mod level;
|
mod level;
|
||||||
mod messagebuilder;
|
mod messagebuilder;
|
||||||
|
mod name_resolver;
|
||||||
pub mod string;
|
pub mod string;
|
||||||
|
|
||||||
use crate::bake::bake_statement;
|
use crate::bake::bake_statement;
|
||||||
|
|
|
||||||
57
logging-extractor/src/name_resolver.rs
Normal file
57
logging-extractor/src/name_resolver.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub fn resolve_name(namespace: &str, aliases: &HashMap<&str, &str>, class: &str) -> String {
|
||||||
|
if class.starts_with('\\') {
|
||||||
|
return class[1..].into();
|
||||||
|
}
|
||||||
|
let (first_part, rest) = class.split_once('\\').unwrap_or((class, ""));
|
||||||
|
if let Some(alias) = aliases.get(first_part) {
|
||||||
|
if rest.is_empty() {
|
||||||
|
format!("{alias}")
|
||||||
|
} else {
|
||||||
|
format!("{alias}\\{rest}")
|
||||||
|
}
|
||||||
|
} else if namespace.is_empty() {
|
||||||
|
if rest.is_empty() {
|
||||||
|
format!("{first_part}")
|
||||||
|
} else {
|
||||||
|
format!("{first_part}\\{rest}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if rest.is_empty() {
|
||||||
|
format!("{namespace}\\{first_part}")
|
||||||
|
} else {
|
||||||
|
format!("{namespace}\\{first_part}\\{rest}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_resolve_name() {
|
||||||
|
use maplit::hashmap;
|
||||||
|
|
||||||
|
assert_eq!(resolve_name("", &hashmap! {}, "Bar"), "Bar");
|
||||||
|
assert_eq!(resolve_name("Foo", &hashmap! {}, "Bar"), "Foo\\Bar");
|
||||||
|
assert_eq!(
|
||||||
|
resolve_name(
|
||||||
|
"Foo",
|
||||||
|
&hashmap! {
|
||||||
|
"Bar" => "Asd"
|
||||||
|
},
|
||||||
|
"Bar"
|
||||||
|
),
|
||||||
|
"Asd"
|
||||||
|
);
|
||||||
|
assert_eq!(resolve_name("Foo", &hashmap! {}, "\\Bar"), "Bar");
|
||||||
|
assert_eq!(resolve_name("Foo", &hashmap! {}, "\\Bar"), "Bar");
|
||||||
|
assert_eq!(
|
||||||
|
resolve_name(
|
||||||
|
"Foo",
|
||||||
|
&hashmap! {
|
||||||
|
"Bar" => "Asd"
|
||||||
|
},
|
||||||
|
"\\Bar"
|
||||||
|
),
|
||||||
|
"Bar"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ expression: output
|
||||||
"path": "/DefaultShareProvider.php",
|
"path": "/DefaultShareProvider.php",
|
||||||
"line": 129,
|
"line": 129,
|
||||||
"has_meaningful_message": true,
|
"has_meaningful_message": true,
|
||||||
"exception": "\\Exception",
|
"exception": "Exception",
|
||||||
"message_parts": [
|
"message_parts": [
|
||||||
{
|
{
|
||||||
"literal": "invalid share type!"
|
"literal": "invalid share type!"
|
||||||
|
|
@ -116,7 +116,7 @@ expression: output
|
||||||
"path": "/DefaultShareProvider.php",
|
"path": "/DefaultShareProvider.php",
|
||||||
"line": 609,
|
"line": 609,
|
||||||
"has_meaningful_message": true,
|
"has_meaningful_message": true,
|
||||||
"exception": "\\Exception",
|
"exception": "Exception",
|
||||||
"message_parts": [
|
"message_parts": [
|
||||||
{
|
{
|
||||||
"literal": "non-shallow getSharesInFolder is no longer supported"
|
"literal": "non-shallow getSharesInFolder is no longer supported"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue