1
1
use djls_semantic:: ValidationError ;
2
2
use djls_source:: File ;
3
3
use djls_source:: LineIndex ;
4
+ use djls_source:: Offset ;
4
5
use djls_source:: Span ;
5
6
use djls_templates:: TemplateError ;
6
7
use djls_templates:: TemplateErrorAccumulator ;
@@ -13,6 +14,30 @@ trait DiagnosticError: std::fmt::Display {
13
14
fn message ( & self ) -> String {
14
15
self . to_string ( )
15
16
}
17
+
18
+ fn as_diagnostic ( & self , line_index : & LineIndex ) -> lsp_types:: Diagnostic {
19
+ let range = self
20
+ . span ( )
21
+ . map ( |( start, length) | {
22
+ let span = Span :: new ( start, length) ;
23
+ LspRange :: from ( ( & span, line_index) ) . into ( )
24
+ } )
25
+ . unwrap_or_default ( ) ;
26
+
27
+ lsp_types:: Diagnostic {
28
+ range,
29
+ severity : Some ( lsp_types:: DiagnosticSeverity :: ERROR ) ,
30
+ code : Some ( lsp_types:: NumberOrString :: String (
31
+ self . diagnostic_code ( ) . to_string ( ) ,
32
+ ) ) ,
33
+ code_description : None ,
34
+ source : Some ( "Django Language Server" . to_string ( ) ) ,
35
+ message : self . message ( ) ,
36
+ related_information : None ,
37
+ tags : None ,
38
+ data : None ,
39
+ }
40
+ }
16
41
}
17
42
18
43
impl DiagnosticError for TemplateError {
@@ -32,14 +57,12 @@ impl DiagnosticError for TemplateError {
32
57
impl DiagnosticError for ValidationError {
33
58
fn span ( & self ) -> Option < ( u32 , u32 ) > {
34
59
match self {
35
- ValidationError :: UnbalancedStructure { opening_span, .. } => {
36
- Some ( opening_span. as_tuple ( ) )
37
- }
60
+ ValidationError :: UnbalancedStructure { opening_span, .. } => Some ( opening_span. into ( ) ) ,
38
61
ValidationError :: UnclosedTag { span, .. }
39
62
| ValidationError :: OrphanedTag { span, .. }
40
63
| ValidationError :: UnmatchedBlockName { span, .. }
41
64
| ValidationError :: MissingRequiredArguments { span, .. }
42
- | ValidationError :: TooManyArguments { span, .. } => Some ( span. as_tuple ( ) ) ,
65
+ | ValidationError :: TooManyArguments { span, .. } => Some ( span. into ( ) ) ,
43
66
}
44
67
}
45
68
@@ -55,47 +78,43 @@ impl DiagnosticError for ValidationError {
55
78
}
56
79
}
57
80
58
- /// Convert a Span to an LSP Range using line offsets.
59
- fn span_to_lsp_range ( span : Span , line_index : & LineIndex ) -> lsp_types:: Range {
60
- let ( start_pos, end_pos) = span. to_line_col ( line_index) ;
61
-
62
- lsp_types:: Range {
63
- start : lsp_types:: Position {
64
- line : start_pos. line ( ) ,
65
- character : start_pos. column ( ) ,
66
- } ,
67
- end : lsp_types:: Position {
68
- line : end_pos. line ( ) ,
69
- character : end_pos. column ( ) ,
70
- } ,
81
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
82
+ #[ repr( transparent) ]
83
+ pub struct LspRange ( pub lsp_types:: Range ) ;
84
+
85
+ impl From < ( & Span , & LineIndex ) > for LspRange {
86
+ #[ inline]
87
+ fn from ( ( s, line_index) : ( & Span , & LineIndex ) ) -> Self {
88
+ let start = LspPosition :: from ( ( s. start_offset ( ) , line_index) ) . into ( ) ;
89
+ let end = LspPosition :: from ( ( s. end_offset ( ) , line_index) ) . into ( ) ;
90
+
91
+ LspRange ( lsp_types:: Range { start, end } )
92
+ }
93
+ }
94
+
95
+ impl From < LspRange > for lsp_types:: Range {
96
+ #[ inline]
97
+ fn from ( value : LspRange ) -> Self {
98
+ value. 0
99
+ }
100
+ }
101
+
102
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
103
+ #[ repr( transparent) ]
104
+ pub struct LspPosition ( pub lsp_types:: Position ) ;
105
+
106
+ impl From < ( Offset , & LineIndex ) > for LspPosition {
107
+ #[ inline]
108
+ fn from ( ( offset, line_index) : ( Offset , & LineIndex ) ) -> Self {
109
+ let ( line, character) = line_index. to_line_col ( offset) . into ( ) ;
110
+ Self ( lsp_types:: Position { line, character } )
71
111
}
72
112
}
73
113
74
- /// Convert any error implementing `DiagnosticError` to an LSP diagnostic.
75
- fn error_to_diagnostic (
76
- error : & impl DiagnosticError ,
77
- line_index : & LineIndex ,
78
- ) -> lsp_types:: Diagnostic {
79
- let range = error
80
- . span ( )
81
- . map ( |( start, length) | {
82
- let span = Span :: new ( start, length) ;
83
- span_to_lsp_range ( span, line_index)
84
- } )
85
- . unwrap_or_default ( ) ;
86
-
87
- lsp_types:: Diagnostic {
88
- range,
89
- severity : Some ( lsp_types:: DiagnosticSeverity :: ERROR ) ,
90
- code : Some ( lsp_types:: NumberOrString :: String (
91
- error. diagnostic_code ( ) . to_string ( ) ,
92
- ) ) ,
93
- code_description : None ,
94
- source : Some ( "Django Language Server" . to_string ( ) ) ,
95
- message : error. message ( ) ,
96
- related_information : None ,
97
- tags : None ,
98
- data : None ,
114
+ impl From < LspPosition > for lsp_types:: Position {
115
+ #[ inline]
116
+ fn from ( value : LspPosition ) -> Self {
117
+ value. 0
99
118
}
100
119
}
101
120
@@ -133,7 +152,7 @@ pub fn collect_diagnostics(
133
152
let line_index = file. line_index ( db) ;
134
153
135
154
for error_acc in template_errors {
136
- diagnostics. push ( error_to_diagnostic ( & error_acc. 0 , line_index) ) ;
155
+ diagnostics. push ( error_acc. 0 . as_diagnostic ( line_index) ) ;
137
156
}
138
157
139
158
if let Some ( nodelist) = nodelist {
@@ -142,7 +161,7 @@ pub fn collect_diagnostics(
142
161
> ( db, nodelist) ;
143
162
144
163
for error_acc in validation_errors {
145
- diagnostics. push ( error_to_diagnostic ( & error_acc. 0 , line_index) ) ;
164
+ diagnostics. push ( error_acc. 0 . as_diagnostic ( line_index) ) ;
146
165
}
147
166
}
148
167
0 commit comments