@@ -2,7 +2,9 @@ use std::future::Future;
22use std:: sync:: Arc ;
33
44use djls_project:: Db as ProjectDb ;
5- use djls_templates:: analyze_template;
5+ use djls_semantic:: validate_nodelist;
6+ use djls_semantic:: SemanticDiagnostic ;
7+ use djls_templates:: parse_template;
68use djls_templates:: TemplateDiagnostic ;
79use djls_workspace:: paths;
810use djls_workspace:: FileKind ;
@@ -96,14 +98,26 @@ impl DjangoLanguageServer {
9698 let file = session. get_or_create_file ( & path) ;
9799
98100 session. with_db ( |db| {
99- // Parse and validate the template (triggers accumulation)
100- // This should be a cheap call since salsa should cache the function
101- // call, but we may need to revisit if that assumption is incorrect
102- let _ast = analyze_template ( db, file) ;
101+ let Some ( nodelist) = parse_template ( db, file) else {
102+ // If parsing failed completely, just return syntax errors
103+ return parse_template:: accumulated :: < TemplateDiagnostic > ( db, file)
104+ . into_iter ( )
105+ . map ( Into :: into)
106+ . collect ( ) ;
107+ } ;
108+
109+ validate_nodelist ( db, nodelist) ;
103110
104- let diagnostics = analyze_template:: accumulated :: < TemplateDiagnostic > ( db, file) ;
111+ let syntax_diagnostics =
112+ parse_template:: accumulated :: < TemplateDiagnostic > ( db, file) ;
113+ let semantic_diagnostics =
114+ validate_nodelist:: accumulated :: < SemanticDiagnostic > ( db, nodelist) ;
105115
106- diagnostics. into_iter ( ) . map ( Into :: into) . collect ( )
116+ syntax_diagnostics
117+ . into_iter ( )
118+ . map ( Into :: into)
119+ . chain ( semantic_diagnostics. into_iter ( ) . map ( Into :: into) )
120+ . collect ( )
107121 } )
108122 } )
109123 . await ;
@@ -240,7 +254,6 @@ impl LanguageServer for DjangoLanguageServer {
240254 } )
241255 . await ;
242256
243- // Publish diagnostics for template files
244257 if let Some ( ( url, version) ) = url_version {
245258 self . publish_diagnostics ( & url, Some ( version) ) . await ;
246259 }
@@ -262,7 +275,6 @@ impl LanguageServer for DjangoLanguageServer {
262275 } )
263276 . await ;
264277
265- // Publish diagnostics for template files
266278 if let Some ( ( url, version) ) = url_version {
267279 self . publish_diagnostics ( & url, version) . await ;
268280 }
@@ -426,14 +438,25 @@ impl LanguageServer for DjangoLanguageServer {
426438 return vec ! [ ] ;
427439 } ;
428440
429- // Parse and validate the template (triggers accumulation)
430- let _ast = analyze_template ( db, file) ;
441+ let Some ( nodelist) = parse_template ( db, file) else {
442+ return parse_template:: accumulated :: < TemplateDiagnostic > ( db, file)
443+ . into_iter ( )
444+ . map ( Into :: into)
445+ . collect ( ) ;
446+ } ;
447+
448+ validate_nodelist ( db, nodelist) ;
431449
432- // Get accumulated diagnostics directly - they're already LSP diagnostics!
433- let diagnostics = analyze_template:: accumulated :: < TemplateDiagnostic > ( db, file) ;
450+ let syntax_diagnostics =
451+ parse_template:: accumulated :: < TemplateDiagnostic > ( db, file) ;
452+ let semantic_diagnostics =
453+ validate_nodelist:: accumulated :: < SemanticDiagnostic > ( db, nodelist) ;
434454
435- // Convert from TemplateDiagnostic wrapper to lsp_types::Diagnostic
436- diagnostics. into_iter ( ) . map ( Into :: into) . collect ( )
455+ syntax_diagnostics
456+ . into_iter ( )
457+ . map ( Into :: into)
458+ . chain ( semantic_diagnostics. into_iter ( ) . map ( Into :: into) )
459+ . collect ( )
437460 } )
438461 } )
439462 . await ;
0 commit comments