mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:53 +00:00
ruff_db: rename Diagnostic
to OldDiagnosticTrait
This trait should eventually go away, so we rename it (and supporting types) to make room for a new concrete `Diagnostic` type. This commit is just the rename. In the next commit, we'll move it to a different module.
This commit is contained in:
parent
81bcdcebd3
commit
021640a7a6
14 changed files with 91 additions and 83 deletions
|
@ -15,7 +15,7 @@ use red_knot_project::watch::ProjectWatcher;
|
||||||
use red_knot_project::{watch, Db};
|
use red_knot_project::{watch, Db};
|
||||||
use red_knot_project::{ProjectDatabase, ProjectMetadata};
|
use red_knot_project::{ProjectDatabase, ProjectMetadata};
|
||||||
use red_knot_server::run_server;
|
use red_knot_server::run_server;
|
||||||
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity};
|
use ruff_db::diagnostic::{DisplayDiagnosticConfig, OldDiagnosticTrait, Severity};
|
||||||
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
|
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
|
||||||
use salsa::plumbing::ZalsaDatabase;
|
use salsa::plumbing::ZalsaDatabase;
|
||||||
|
|
||||||
|
@ -354,8 +354,7 @@ enum MainLoopMessage {
|
||||||
CheckWorkspace,
|
CheckWorkspace,
|
||||||
CheckCompleted {
|
CheckCompleted {
|
||||||
/// The diagnostics that were found during the check.
|
/// The diagnostics that were found during the check.
|
||||||
result: Vec<Box<dyn Diagnostic>>,
|
result: Vec<Box<dyn OldDiagnosticTrait>>,
|
||||||
|
|
||||||
revision: u64,
|
revision: u64,
|
||||||
},
|
},
|
||||||
ApplyChanges(Vec<watch::ChangeEvent>),
|
ApplyChanges(Vec<watch::ChangeEvent>),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::DEFAULT_LINT_REGISTRY;
|
||||||
use crate::{Project, ProjectMetadata};
|
use crate::{Project, ProjectMetadata};
|
||||||
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
|
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
|
||||||
use red_knot_python_semantic::{Db as SemanticDb, Program};
|
use red_knot_python_semantic::{Db as SemanticDb, Program};
|
||||||
use ruff_db::diagnostic::Diagnostic;
|
use ruff_db::diagnostic::OldDiagnosticTrait;
|
||||||
use ruff_db::files::{File, Files};
|
use ruff_db::files::{File, Files};
|
||||||
use ruff_db::system::System;
|
use ruff_db::system::System;
|
||||||
use ruff_db::vendored::VendoredFileSystem;
|
use ruff_db::vendored::VendoredFileSystem;
|
||||||
|
@ -55,11 +55,11 @@ impl ProjectDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks all open files in the project and its dependencies.
|
/// Checks all open files in the project and its dependencies.
|
||||||
pub fn check(&self) -> Result<Vec<Box<dyn Diagnostic>>, Cancelled> {
|
pub fn check(&self) -> Result<Vec<Box<dyn OldDiagnosticTrait>>, Cancelled> {
|
||||||
self.with_db(|db| db.project().check(db))
|
self.with_db(|db| db.project().check(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_file(&self, file: File) -> Result<Vec<Box<dyn Diagnostic>>, Cancelled> {
|
pub fn check_file(&self, file: File) -> Result<Vec<Box<dyn OldDiagnosticTrait>>, Cancelled> {
|
||||||
let _span = tracing::debug_span!("check_file", file=%file.path(self)).entered();
|
let _span = tracing::debug_span!("check_file", file=%file.path(self)).entered();
|
||||||
|
|
||||||
self.with_db(|db| self.project().check_file(db, file))
|
self.with_db(|db| self.project().check_file(db, file))
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub use metadata::{ProjectDiscoveryError, ProjectMetadata};
|
||||||
use red_knot_python_semantic::lint::{LintRegistry, LintRegistryBuilder, RuleSelection};
|
use red_knot_python_semantic::lint::{LintRegistry, LintRegistryBuilder, RuleSelection};
|
||||||
use red_knot_python_semantic::register_lints;
|
use red_knot_python_semantic::register_lints;
|
||||||
use red_knot_python_semantic::types::check_types;
|
use red_knot_python_semantic::types::check_types;
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, ParseDiagnostic, Severity, Span};
|
use ruff_db::diagnostic::{DiagnosticId, OldDiagnosticTrait, ParseDiagnostic, Severity, Span};
|
||||||
use ruff_db::files::File;
|
use ruff_db::files::File;
|
||||||
use ruff_db::parsed::parsed_module;
|
use ruff_db::parsed::parsed_module;
|
||||||
use ruff_db::source::{source_text, SourceTextError};
|
use ruff_db::source::{source_text, SourceTextError};
|
||||||
|
@ -163,22 +163,22 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks all open files in the project and its dependencies.
|
/// Checks all open files in the project and its dependencies.
|
||||||
pub(crate) fn check(self, db: &ProjectDatabase) -> Vec<Box<dyn Diagnostic>> {
|
pub(crate) fn check(self, db: &ProjectDatabase) -> Vec<Box<dyn OldDiagnosticTrait>> {
|
||||||
let project_span = tracing::debug_span!("Project::check");
|
let project_span = tracing::debug_span!("Project::check");
|
||||||
let _span = project_span.enter();
|
let _span = project_span.enter();
|
||||||
|
|
||||||
tracing::debug!("Checking project '{name}'", name = self.name(db));
|
tracing::debug!("Checking project '{name}'", name = self.name(db));
|
||||||
|
|
||||||
let mut diagnostics: Vec<Box<dyn Diagnostic>> = Vec::new();
|
let mut diagnostics: Vec<Box<dyn OldDiagnosticTrait>> = Vec::new();
|
||||||
diagnostics.extend(self.settings_diagnostics(db).iter().map(|diagnostic| {
|
diagnostics.extend(self.settings_diagnostics(db).iter().map(|diagnostic| {
|
||||||
let diagnostic: Box<dyn Diagnostic> = Box::new(diagnostic.clone());
|
let diagnostic: Box<dyn OldDiagnosticTrait> = Box::new(diagnostic.clone());
|
||||||
diagnostic
|
diagnostic
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let files = ProjectFiles::new(db, self);
|
let files = ProjectFiles::new(db, self);
|
||||||
|
|
||||||
diagnostics.extend(files.diagnostics().iter().cloned().map(|diagnostic| {
|
diagnostics.extend(files.diagnostics().iter().cloned().map(|diagnostic| {
|
||||||
let diagnostic: Box<dyn Diagnostic> = Box::new(diagnostic);
|
let diagnostic: Box<dyn OldDiagnosticTrait> = Box::new(diagnostic);
|
||||||
diagnostic
|
diagnostic
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -207,12 +207,12 @@ impl Project {
|
||||||
Arc::into_inner(result).unwrap().into_inner().unwrap()
|
Arc::into_inner(result).unwrap().into_inner().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_file(self, db: &dyn Db, file: File) -> Vec<Box<dyn Diagnostic>> {
|
pub(crate) fn check_file(self, db: &dyn Db, file: File) -> Vec<Box<dyn OldDiagnosticTrait>> {
|
||||||
let mut file_diagnostics: Vec<_> = self
|
let mut file_diagnostics: Vec<_> = self
|
||||||
.settings_diagnostics(db)
|
.settings_diagnostics(db)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|diagnostic| {
|
.map(|diagnostic| {
|
||||||
let diagnostic: Box<dyn Diagnostic> = Box::new(diagnostic.clone());
|
let diagnostic: Box<dyn OldDiagnosticTrait> = Box::new(diagnostic.clone());
|
||||||
diagnostic
|
diagnostic
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -397,8 +397,8 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_file_impl(db: &dyn Db, file: File) -> Vec<Box<dyn Diagnostic>> {
|
fn check_file_impl(db: &dyn Db, file: File) -> Vec<Box<dyn OldDiagnosticTrait>> {
|
||||||
let mut diagnostics: Vec<Box<dyn Diagnostic>> = Vec::new();
|
let mut diagnostics: Vec<Box<dyn OldDiagnosticTrait>> = Vec::new();
|
||||||
|
|
||||||
// Abort checking if there are IO errors.
|
// Abort checking if there are IO errors.
|
||||||
let source = source_text(db.upcast(), file);
|
let source = source_text(db.upcast(), file);
|
||||||
|
@ -413,12 +413,13 @@ fn check_file_impl(db: &dyn Db, file: File) -> Vec<Box<dyn Diagnostic>> {
|
||||||
|
|
||||||
let parsed = parsed_module(db.upcast(), file);
|
let parsed = parsed_module(db.upcast(), file);
|
||||||
diagnostics.extend(parsed.errors().iter().map(|error| {
|
diagnostics.extend(parsed.errors().iter().map(|error| {
|
||||||
let diagnostic: Box<dyn Diagnostic> = Box::new(ParseDiagnostic::new(file, error.clone()));
|
let diagnostic: Box<dyn OldDiagnosticTrait> =
|
||||||
|
Box::new(ParseDiagnostic::new(file, error.clone()));
|
||||||
diagnostic
|
diagnostic
|
||||||
}));
|
}));
|
||||||
|
|
||||||
diagnostics.extend(check_types(db.upcast(), file).iter().map(|diagnostic| {
|
diagnostics.extend(check_types(db.upcast(), file).iter().map(|diagnostic| {
|
||||||
let boxed: Box<dyn Diagnostic> = Box::new(diagnostic.clone());
|
let boxed: Box<dyn OldDiagnosticTrait> = Box::new(diagnostic.clone());
|
||||||
boxed
|
boxed
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -492,7 +493,7 @@ pub struct IOErrorDiagnostic {
|
||||||
error: IOErrorKind,
|
error: IOErrorKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for IOErrorDiagnostic {
|
impl OldDiagnosticTrait for IOErrorDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
DiagnosticId::Io
|
DiagnosticId::Io
|
||||||
}
|
}
|
||||||
|
@ -524,7 +525,7 @@ mod tests {
|
||||||
use crate::db::tests::TestDb;
|
use crate::db::tests::TestDb;
|
||||||
use crate::{check_file_impl, ProjectMetadata};
|
use crate::{check_file_impl, ProjectMetadata};
|
||||||
use red_knot_python_semantic::types::check_types;
|
use red_knot_python_semantic::types::check_types;
|
||||||
use ruff_db::diagnostic::Diagnostic;
|
use ruff_db::diagnostic::OldDiagnosticTrait;
|
||||||
use ruff_db::files::system_path_to_file;
|
use ruff_db::files::system_path_to_file;
|
||||||
use ruff_db::source::source_text;
|
use ruff_db::source::source_text;
|
||||||
use ruff_db::system::{DbWithTestSystem, SystemPath, SystemPathBuf};
|
use ruff_db::system::{DbWithTestSystem, SystemPath, SystemPathBuf};
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::metadata::value::{RangedValue, RelativePathBuf, ValueSource, ValueSou
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
use red_knot_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection};
|
use red_knot_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection};
|
||||||
use red_knot_python_semantic::{ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings};
|
use red_knot_python_semantic::{ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings};
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity, Span};
|
use ruff_db::diagnostic::{DiagnosticId, OldDiagnosticTrait, Severity, Span};
|
||||||
use ruff_db::files::system_path_to_file;
|
use ruff_db::files::system_path_to_file;
|
||||||
use ruff_db::system::{System, SystemPath};
|
use ruff_db::system::{System, SystemPath};
|
||||||
use ruff_macros::Combine;
|
use ruff_macros::Combine;
|
||||||
|
@ -376,7 +376,7 @@ impl OptionDiagnostic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for OptionDiagnostic {
|
impl OldDiagnosticTrait for OptionDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::types::diagnostic::{
|
||||||
};
|
};
|
||||||
use crate::types::signatures::Parameter;
|
use crate::types::signatures::Parameter;
|
||||||
use crate::types::{todo_type, CallableType, UnionType};
|
use crate::types::{todo_type, CallableType, UnionType};
|
||||||
use ruff_db::diagnostic::{SecondaryDiagnosticMessage, Span};
|
use ruff_db::diagnostic::{OldSecondaryDiagnosticMessage, Span};
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ impl<'db> CallBindingError<'db> {
|
||||||
if let Some(span) =
|
if let Some(span) =
|
||||||
Self::parameter_span_from_index(context.db(), callable_ty, parameter.index)
|
Self::parameter_span_from_index(context.db(), callable_ty, parameter.index)
|
||||||
{
|
{
|
||||||
messages.push(SecondaryDiagnosticMessage::new(
|
messages.push(OldSecondaryDiagnosticMessage::new(
|
||||||
span,
|
span,
|
||||||
"parameter declared in function definition here",
|
"parameter declared in function definition here",
|
||||||
));
|
));
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
|
|
||||||
use drop_bomb::DebugDropBomb;
|
use drop_bomb::DebugDropBomb;
|
||||||
use ruff_db::{
|
use ruff_db::{
|
||||||
diagnostic::{DiagnosticId, SecondaryDiagnosticMessage, Severity},
|
diagnostic::{DiagnosticId, OldSecondaryDiagnosticMessage, Severity},
|
||||||
files::File,
|
files::File,
|
||||||
};
|
};
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
@ -84,7 +84,7 @@ impl<'db> InferContext<'db> {
|
||||||
lint: &'static LintMetadata,
|
lint: &'static LintMetadata,
|
||||||
ranged: T,
|
ranged: T,
|
||||||
message: fmt::Arguments,
|
message: fmt::Arguments,
|
||||||
secondary_messages: Vec<SecondaryDiagnosticMessage>,
|
secondary_messages: Vec<OldSecondaryDiagnosticMessage>,
|
||||||
) where
|
) where
|
||||||
T: Ranged,
|
T: Ranged,
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ impl<'db> InferContext<'db> {
|
||||||
id: DiagnosticId,
|
id: DiagnosticId,
|
||||||
severity: Severity,
|
severity: Severity,
|
||||||
message: fmt::Arguments,
|
message: fmt::Arguments,
|
||||||
secondary_messages: Vec<SecondaryDiagnosticMessage>,
|
secondary_messages: Vec<OldSecondaryDiagnosticMessage>,
|
||||||
) where
|
) where
|
||||||
T: Ranged,
|
T: Ranged,
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,9 @@ use crate::types::string_annotation::{
|
||||||
};
|
};
|
||||||
use crate::types::{ClassLiteralType, KnownInstanceType, Type};
|
use crate::types::{ClassLiteralType, KnownInstanceType, Type};
|
||||||
use crate::{declare_lint, Db};
|
use crate::{declare_lint, Db};
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, SecondaryDiagnosticMessage, Severity, Span};
|
use ruff_db::diagnostic::{
|
||||||
|
DiagnosticId, OldDiagnosticTrait, OldSecondaryDiagnosticMessage, Severity, Span,
|
||||||
|
};
|
||||||
use ruff_db::files::File;
|
use ruff_db::files::File;
|
||||||
use ruff_python_ast::{self as ast, AnyNodeRef};
|
use ruff_python_ast::{self as ast, AnyNodeRef};
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
|
@ -828,7 +830,7 @@ pub struct TypeCheckDiagnostic {
|
||||||
pub(crate) range: TextRange,
|
pub(crate) range: TextRange,
|
||||||
pub(crate) severity: Severity,
|
pub(crate) severity: Severity,
|
||||||
pub(crate) file: File,
|
pub(crate) file: File,
|
||||||
pub(crate) secondary_messages: Vec<SecondaryDiagnosticMessage>,
|
pub(crate) secondary_messages: Vec<OldSecondaryDiagnosticMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeCheckDiagnostic {
|
impl TypeCheckDiagnostic {
|
||||||
|
@ -845,7 +847,7 @@ impl TypeCheckDiagnostic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for TypeCheckDiagnostic {
|
impl OldDiagnosticTrait for TypeCheckDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
@ -858,7 +860,7 @@ impl Diagnostic for TypeCheckDiagnostic {
|
||||||
Some(Span::from(self.file).with_range(self.range))
|
Some(Span::from(self.file).with_range(self.range))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
&self.secondary_messages
|
&self.secondary_messages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ fn compute_diagnostics(snapshot: &DocumentSnapshot, db: &ProjectDatabase) -> Vec
|
||||||
|
|
||||||
fn to_lsp_diagnostic(
|
fn to_lsp_diagnostic(
|
||||||
db: &dyn Db,
|
db: &dyn Db,
|
||||||
diagnostic: &dyn ruff_db::diagnostic::Diagnostic,
|
diagnostic: &dyn ruff_db::diagnostic::OldDiagnosticTrait,
|
||||||
encoding: crate::PositionEncoding,
|
encoding: crate::PositionEncoding,
|
||||||
) -> Diagnostic {
|
) -> Diagnostic {
|
||||||
let range = if let Some(span) = diagnostic.span() {
|
let range = if let Some(span) = diagnostic.span() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! We don't assume that we will get the diagnostics in source order.
|
//! We don't assume that we will get the diagnostics in source order.
|
||||||
|
|
||||||
use ruff_db::diagnostic::Diagnostic;
|
use ruff_db::diagnostic::OldDiagnosticTrait;
|
||||||
use ruff_source_file::{LineIndex, OneIndexed};
|
use ruff_source_file::{LineIndex, OneIndexed};
|
||||||
use std::ops::{Deref, Range};
|
use std::ops::{Deref, Range};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ pub(crate) struct SortedDiagnostics<T> {
|
||||||
|
|
||||||
impl<T> SortedDiagnostics<T>
|
impl<T> SortedDiagnostics<T>
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(diagnostics: impl IntoIterator<Item = T>, line_index: &LineIndex) -> Self {
|
pub(crate) fn new(diagnostics: impl IntoIterator<Item = T>, line_index: &LineIndex) -> Self {
|
||||||
let mut diagnostics: Vec<_> = diagnostics
|
let mut diagnostics: Vec<_> = diagnostics
|
||||||
|
@ -99,7 +99,7 @@ pub(crate) struct LineDiagnosticsIterator<'a, T> {
|
||||||
|
|
||||||
impl<'a, T> Iterator for LineDiagnosticsIterator<'a, T>
|
impl<'a, T> Iterator for LineDiagnosticsIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
type Item = LineDiagnostics<'a, T>;
|
type Item = LineDiagnostics<'a, T>;
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> std::iter::FusedIterator for LineDiagnosticsIterator<'_, T> where T: Diagnostic {}
|
impl<T> std::iter::FusedIterator for LineDiagnosticsIterator<'_, T> where T: OldDiagnosticTrait {}
|
||||||
|
|
||||||
/// All diagnostics that start on a single line of source code in one embedded Python file.
|
/// All diagnostics that start on a single line of source code in one embedded Python file.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -144,7 +144,7 @@ struct DiagnosticWithLine<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::db::Db;
|
use crate::db::Db;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::OldDiagnosticTrait;
|
||||||
use ruff_db::diagnostic::{DiagnosticId, LintName, Severity, Span};
|
use ruff_db::diagnostic::{DiagnosticId, LintName, Severity, Span};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::source::line_index;
|
use ruff_db::source::line_index;
|
||||||
|
@ -190,7 +190,7 @@ mod tests {
|
||||||
file: File,
|
file: File,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for DummyDiagnostic {
|
impl OldDiagnosticTrait for DummyDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
DiagnosticId::Lint(LintName::of("dummy"))
|
DiagnosticId::Lint(LintName::of("dummy"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use colored::Colorize;
|
||||||
use parser as test_parser;
|
use parser as test_parser;
|
||||||
use red_knot_python_semantic::types::check_types;
|
use red_knot_python_semantic::types::check_types;
|
||||||
use red_knot_python_semantic::{Program, ProgramSettings, PythonPath, SearchPathSettings};
|
use red_knot_python_semantic::{Program, ProgramSettings, PythonPath, SearchPathSettings};
|
||||||
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, ParseDiagnostic};
|
use ruff_db::diagnostic::{DisplayDiagnosticConfig, OldDiagnosticTrait, ParseDiagnostic};
|
||||||
use ruff_db::files::{system_path_to_file, File, Files};
|
use ruff_db::files::{system_path_to_file, File, Files};
|
||||||
use ruff_db::panic::catch_unwind;
|
use ruff_db::panic::catch_unwind;
|
||||||
use ruff_db::parsed::parsed_module;
|
use ruff_db::parsed::parsed_module;
|
||||||
|
@ -200,7 +200,7 @@ fn run_test(
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|error| {
|
.map(|error| {
|
||||||
let diagnostic: Box<dyn Diagnostic> =
|
let diagnostic: Box<dyn OldDiagnosticTrait> =
|
||||||
Box::new(ParseDiagnostic::new(test_file.file, error));
|
Box::new(ParseDiagnostic::new(test_file.file, error));
|
||||||
diagnostic
|
diagnostic
|
||||||
})
|
})
|
||||||
|
@ -234,7 +234,7 @@ fn run_test(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
diagnostics.extend(type_diagnostics.into_iter().map(|diagnostic| {
|
diagnostics.extend(type_diagnostics.into_iter().map(|diagnostic| {
|
||||||
let diagnostic: Box<dyn Diagnostic> = Box::new((*diagnostic).clone());
|
let diagnostic: Box<dyn OldDiagnosticTrait> = Box::new((*diagnostic).clone());
|
||||||
diagnostic
|
diagnostic
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ struct TestFile {
|
||||||
backtick_offsets: Vec<BacktickOffsets>,
|
backtick_offsets: Vec<BacktickOffsets>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_diagnostic_snapshot<D: Diagnostic>(
|
fn create_diagnostic_snapshot<D: OldDiagnosticTrait>(
|
||||||
db: &mut db::Db,
|
db: &mut db::Db,
|
||||||
relative_fixture_path: &Utf8Path,
|
relative_fixture_path: &Utf8Path,
|
||||||
test: &parser::MarkdownTest,
|
test: &parser::MarkdownTest,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! Match [`Diagnostic`]s against assertions and produce test failure messages for any
|
//! Match [`OldDiagnosticTrait`]s against assertions and produce test failure
|
||||||
//! mismatches.
|
//! messages for any mismatches.
|
||||||
use crate::assertion::{InlineFileAssertions, ParsedAssertion, UnparsedAssertion};
|
use crate::assertion::{InlineFileAssertions, ParsedAssertion, UnparsedAssertion};
|
||||||
use crate::db::Db;
|
use crate::db::Db;
|
||||||
use crate::diagnostic::SortedDiagnostics;
|
use crate::diagnostic::SortedDiagnostics;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticAsStrError, DiagnosticId};
|
use ruff_db::diagnostic::{DiagnosticAsStrError, DiagnosticId, OldDiagnosticTrait};
|
||||||
use ruff_db::files::File;
|
use ruff_db::files::File;
|
||||||
use ruff_db::source::{line_index, source_text, SourceText};
|
use ruff_db::source::{line_index, source_text, SourceText};
|
||||||
use ruff_source_file::{LineIndex, OneIndexed};
|
use ruff_source_file::{LineIndex, OneIndexed};
|
||||||
|
@ -53,7 +53,7 @@ pub(super) fn match_file<T>(
|
||||||
diagnostics: impl IntoIterator<Item = T>,
|
diagnostics: impl IntoIterator<Item = T>,
|
||||||
) -> Result<(), FailuresByLine>
|
) -> Result<(), FailuresByLine>
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
// Parse assertions from comments in the file, and get diagnostics from the file; both
|
// Parse assertions from comments in the file, and get diagnostics from the file; both
|
||||||
// ordered by line number.
|
// ordered by line number.
|
||||||
|
@ -155,7 +155,7 @@ impl Unmatched for ParsedAssertion<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_add_undefined_reveal_clarification<T: Diagnostic>(
|
fn maybe_add_undefined_reveal_clarification<T: OldDiagnosticTrait>(
|
||||||
diagnostic: &T,
|
diagnostic: &T,
|
||||||
original: std::fmt::Arguments,
|
original: std::fmt::Arguments,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
@ -171,7 +171,7 @@ fn maybe_add_undefined_reveal_clarification<T: Diagnostic>(
|
||||||
|
|
||||||
impl<T> Unmatched for T
|
impl<T> Unmatched for T
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
fn unmatched(&self) -> String {
|
fn unmatched(&self) -> String {
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
|
@ -188,7 +188,7 @@ where
|
||||||
|
|
||||||
impl<T> UnmatchedWithColumn for T
|
impl<T> UnmatchedWithColumn for T
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
fn unmatched_with_column(&self, column: OneIndexed) -> String {
|
fn unmatched_with_column(&self, column: OneIndexed) -> String {
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
|
@ -226,10 +226,12 @@ impl Matcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check a slice of [`Diagnostic`]s against a slice of [`UnparsedAssertion`]s.
|
/// Check a slice of [`OldDiagnosticTrait`]s against a slice of
|
||||||
|
/// [`UnparsedAssertion`]s.
|
||||||
///
|
///
|
||||||
/// Return vector of [`Unmatched`] for any unmatched diagnostics or assertions.
|
/// Return vector of [`Unmatched`] for any unmatched diagnostics or
|
||||||
fn match_line<'a, 'b, T: Diagnostic + 'a>(
|
/// assertions.
|
||||||
|
fn match_line<'a, 'b, T: OldDiagnosticTrait + 'a>(
|
||||||
&self,
|
&self,
|
||||||
diagnostics: &'a [T],
|
diagnostics: &'a [T],
|
||||||
assertions: &'a [UnparsedAssertion<'b>],
|
assertions: &'a [UnparsedAssertion<'b>],
|
||||||
|
@ -261,7 +263,7 @@ impl Matcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn column<T: Diagnostic>(&self, diagnostic: &T) -> OneIndexed {
|
fn column<T: OldDiagnosticTrait>(&self, diagnostic: &T) -> OneIndexed {
|
||||||
diagnostic
|
diagnostic
|
||||||
.span()
|
.span()
|
||||||
.and_then(|span| span.range())
|
.and_then(|span| span.range())
|
||||||
|
@ -273,7 +275,7 @@ impl Matcher {
|
||||||
.unwrap_or(OneIndexed::from_zero_indexed(0))
|
.unwrap_or(OneIndexed::from_zero_indexed(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if `assertion` matches any [`Diagnostic`]s in `unmatched`.
|
/// Check if `assertion` matches any [`OldDiagnosticTrait`]s in `unmatched`.
|
||||||
///
|
///
|
||||||
/// If so, return `true` and remove the matched diagnostics from `unmatched`. Otherwise, return
|
/// If so, return `true` and remove the matched diagnostics from `unmatched`. Otherwise, return
|
||||||
/// `false`.
|
/// `false`.
|
||||||
|
@ -283,7 +285,11 @@ impl Matcher {
|
||||||
///
|
///
|
||||||
/// A `Revealed` assertion must match a revealed-type diagnostic, and may also match an
|
/// A `Revealed` assertion must match a revealed-type diagnostic, and may also match an
|
||||||
/// undefined-reveal diagnostic, if present.
|
/// undefined-reveal diagnostic, if present.
|
||||||
fn matches<T: Diagnostic>(&self, assertion: &ParsedAssertion, unmatched: &mut Vec<&T>) -> bool {
|
fn matches<T: OldDiagnosticTrait>(
|
||||||
|
&self,
|
||||||
|
assertion: &ParsedAssertion,
|
||||||
|
unmatched: &mut Vec<&T>,
|
||||||
|
) -> bool {
|
||||||
match assertion {
|
match assertion {
|
||||||
ParsedAssertion::Error(error) => {
|
ParsedAssertion::Error(error) => {
|
||||||
let position = unmatched.iter().position(|diagnostic| {
|
let position = unmatched.iter().position(|diagnostic| {
|
||||||
|
@ -341,7 +347,7 @@ impl Matcher {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::FailuresByLine;
|
use super::FailuresByLine;
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity, Span};
|
use ruff_db::diagnostic::{DiagnosticId, OldDiagnosticTrait, Severity, Span};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
|
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
|
||||||
use ruff_python_trivia::textwrap::dedent;
|
use ruff_python_trivia::textwrap::dedent;
|
||||||
|
@ -383,7 +389,7 @@ mod tests {
|
||||||
file: File,
|
file: File,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for TestDiagnostic {
|
impl OldDiagnosticTrait for TestDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use red_knot_project::metadata::options::{EnvironmentOptions, Options};
|
||||||
use red_knot_project::metadata::value::RangedValue;
|
use red_knot_project::metadata::value::RangedValue;
|
||||||
use red_knot_project::ProjectMetadata;
|
use red_knot_project::ProjectMetadata;
|
||||||
use red_knot_project::{Db, ProjectDatabase};
|
use red_knot_project::{Db, ProjectDatabase};
|
||||||
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig};
|
use ruff_db::diagnostic::{DisplayDiagnosticConfig, OldDiagnosticTrait};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::system::walk_directory::WalkDirectoryBuilder;
|
use ruff_db::system::walk_directory::WalkDirectoryBuilder;
|
||||||
use ruff_db::system::{
|
use ruff_db::system::{
|
||||||
|
|
|
@ -10,7 +10,7 @@ use red_knot_project::watch::{ChangeEvent, ChangedKind};
|
||||||
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
|
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
|
||||||
use ruff_benchmark::criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
use ruff_benchmark::criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
||||||
use ruff_benchmark::TestFile;
|
use ruff_benchmark::TestFile;
|
||||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity};
|
use ruff_db::diagnostic::{DiagnosticId, OldDiagnosticTrait, Severity};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::source::source_text;
|
use ruff_db::source::source_text;
|
||||||
use ruff_db::system::{MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
|
use ruff_db::system::{MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
|
||||||
|
@ -223,7 +223,7 @@ fn benchmark_cold(criterion: &mut Criterion) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_diagnostics(db: &dyn Db, diagnostics: &[Box<dyn Diagnostic>]) {
|
fn assert_diagnostics(db: &dyn Db, diagnostics: &[Box<dyn OldDiagnosticTrait>]) {
|
||||||
let normalized: Vec<_> = diagnostics
|
let normalized: Vec<_> = diagnostics
|
||||||
.iter()
|
.iter()
|
||||||
.map(|diagnostic| {
|
.map(|diagnostic| {
|
||||||
|
|
|
@ -162,7 +162,7 @@ impl std::fmt::Display for DiagnosticId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Diagnostic: Send + Sync + std::fmt::Debug {
|
pub trait OldDiagnosticTrait: Send + Sync + std::fmt::Debug {
|
||||||
fn id(&self) -> DiagnosticId;
|
fn id(&self) -> DiagnosticId;
|
||||||
|
|
||||||
fn message(&self) -> Cow<str>;
|
fn message(&self) -> Cow<str>;
|
||||||
|
@ -175,7 +175,7 @@ pub trait Diagnostic: Send + Sync + std::fmt::Debug {
|
||||||
|
|
||||||
/// Returns an optional sequence of "secondary" messages (with spans) to
|
/// Returns an optional sequence of "secondary" messages (with spans) to
|
||||||
/// include in the rendering of this diagnostic.
|
/// include in the rendering of this diagnostic.
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,11 +185,11 @@ pub trait Diagnostic: Send + Sync + std::fmt::Debug {
|
||||||
&'diag self,
|
&'diag self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
config: &'config DisplayDiagnosticConfig,
|
config: &'config DisplayDiagnosticConfig,
|
||||||
) -> DisplayDiagnostic<'db, 'diag, 'config>
|
) -> OldDisplayDiagnostic<'db, 'diag, 'config>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
DisplayDiagnostic {
|
OldDisplayDiagnostic {
|
||||||
db,
|
db,
|
||||||
diagnostic: self,
|
diagnostic: self,
|
||||||
config,
|
config,
|
||||||
|
@ -199,14 +199,14 @@ pub trait Diagnostic: Send + Sync + std::fmt::Debug {
|
||||||
|
|
||||||
/// A single secondary message assigned to a `Diagnostic`.
|
/// A single secondary message assigned to a `Diagnostic`.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct SecondaryDiagnosticMessage {
|
pub struct OldSecondaryDiagnosticMessage {
|
||||||
span: Span,
|
span: Span,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecondaryDiagnosticMessage {
|
impl OldSecondaryDiagnosticMessage {
|
||||||
pub fn new(span: Span, message: impl Into<String>) -> SecondaryDiagnosticMessage {
|
pub fn new(span: Span, message: impl Into<String>) -> OldSecondaryDiagnosticMessage {
|
||||||
SecondaryDiagnosticMessage {
|
OldSecondaryDiagnosticMessage {
|
||||||
span,
|
span,
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
}
|
}
|
||||||
|
@ -298,13 +298,13 @@ impl DisplayDiagnosticConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DisplayDiagnostic<'db, 'diag, 'config> {
|
pub struct OldDisplayDiagnostic<'db, 'diag, 'config> {
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
diagnostic: &'diag dyn Diagnostic,
|
diagnostic: &'diag dyn OldDiagnosticTrait,
|
||||||
config: &'config DisplayDiagnosticConfig,
|
config: &'config DisplayDiagnosticConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for DisplayDiagnostic<'_, '_, '_> {
|
impl std::fmt::Display for OldDisplayDiagnostic<'_, '_, '_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let render = |f: &mut std::fmt::Formatter, message| {
|
let render = |f: &mut std::fmt::Formatter, message| {
|
||||||
let renderer = if self.config.color {
|
let renderer = if self.config.color {
|
||||||
|
@ -461,9 +461,9 @@ impl Annotation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Diagnostic for Box<T>
|
impl<T> OldDiagnosticTrait for Box<T>
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
(**self).id()
|
(**self).id()
|
||||||
|
@ -477,7 +477,7 @@ where
|
||||||
(**self).span()
|
(**self).span()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
(**self).secondary_messages()
|
(**self).secondary_messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,9 +486,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Diagnostic for std::sync::Arc<T>
|
impl<T> OldDiagnosticTrait for std::sync::Arc<T>
|
||||||
where
|
where
|
||||||
T: Diagnostic,
|
T: OldDiagnosticTrait,
|
||||||
{
|
{
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
(**self).id()
|
(**self).id()
|
||||||
|
@ -502,7 +502,7 @@ where
|
||||||
(**self).span()
|
(**self).span()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
(**self).secondary_messages()
|
(**self).secondary_messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +511,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for Box<dyn Diagnostic> {
|
impl OldDiagnosticTrait for Box<dyn OldDiagnosticTrait> {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
(**self).id()
|
(**self).id()
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,7 @@ impl Diagnostic for Box<dyn Diagnostic> {
|
||||||
(**self).span()
|
(**self).span()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
(**self).secondary_messages()
|
(**self).secondary_messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ impl Diagnostic for Box<dyn Diagnostic> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for &'_ dyn Diagnostic {
|
impl OldDiagnosticTrait for &'_ dyn OldDiagnosticTrait {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
(**self).id()
|
(**self).id()
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ impl Diagnostic for &'_ dyn Diagnostic {
|
||||||
(**self).span()
|
(**self).span()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
(**self).secondary_messages()
|
(**self).secondary_messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +555,7 @@ impl Diagnostic for &'_ dyn Diagnostic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for std::sync::Arc<dyn Diagnostic> {
|
impl OldDiagnosticTrait for std::sync::Arc<dyn OldDiagnosticTrait> {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
(**self).id()
|
(**self).id()
|
||||||
}
|
}
|
||||||
|
@ -568,7 +568,7 @@ impl Diagnostic for std::sync::Arc<dyn Diagnostic> {
|
||||||
(**self).span()
|
(**self).span()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary_messages(&self) -> &[SecondaryDiagnosticMessage] {
|
fn secondary_messages(&self) -> &[OldSecondaryDiagnosticMessage] {
|
||||||
(**self).secondary_messages()
|
(**self).secondary_messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +589,7 @@ impl ParseDiagnostic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic for ParseDiagnostic {
|
impl OldDiagnosticTrait for ParseDiagnostic {
|
||||||
fn id(&self) -> DiagnosticId {
|
fn id(&self) -> DiagnosticId {
|
||||||
DiagnosticId::InvalidSyntax
|
DiagnosticId::InvalidSyntax
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue