22using System ;
33using System . Collections . Generic ;
44using System . Collections . Immutable ;
5- using System . IO ;
65using System . Linq ;
76using System . Reflection ;
87using DotVVM . Framework . Compilation . ControlTree ;
@@ -34,29 +33,26 @@ public static ImmutableArray<DotvvmCompilationDiagnostic> CompileAll(
3433 foreach ( var markupControl in markupControls )
3534 {
3635 compiledPaths . Add ( markupControl ! ) ;
37- diagnostics . AddRange ( CompileNoThrow ( configuration , markupControl ! ) ) ;
36+ diagnostics . AddRange ( CompileNoThrow ( configuration , markupControl ! , out _ ) ) ;
3837 }
3938
4039 var views = configuration . RouteTable . Select ( r => r . VirtualPath ) . WhereNotNull ( ) . ToImmutableArray ( ) ;
40+ var discoveredMasterPages = new Queue < string > ( ) ;
4141 foreach ( var view in views )
4242 {
4343 compiledPaths . Add ( view ) ;
44- diagnostics . AddRange ( CompileNoThrow ( configuration , view ) ) ;
44+ diagnostics . AddRange ( CompileNoThrow ( configuration , view , out var masterPage ) ) ;
45+ if ( masterPage is not null && compiledPaths . Add ( masterPage ) )
46+ discoveredMasterPages . Enqueue ( masterPage ) ;
4547 }
4648
47- // Also compile master pages (.dotmaster files) that are not already covered
48- // by markup controls or the route table.
49- if ( Directory . Exists ( dotvvmProjectDir ) )
49+ // Discover master pages transitively (a master page may itself use another master page).
50+ while ( discoveredMasterPages . Count > 0 )
5051 {
51- foreach ( var masterPageFile in Directory . EnumerateFiles ( dotvvmProjectDir , "*.dotmaster" , SearchOption . AllDirectories ) )
52- {
53- var virtualPath = Path . GetRelativePath ( dotvvmProjectDir , masterPageFile )
54- . Replace ( '\\ ' , '/' ) ;
55- if ( compiledPaths . Add ( virtualPath ) )
56- {
57- diagnostics . AddRange ( CompileNoThrow ( configuration , virtualPath ) ) ;
58- }
59- }
52+ var masterPagePath = discoveredMasterPages . Dequeue ( ) ;
53+ diagnostics . AddRange ( CompileNoThrow ( configuration , masterPagePath , out var nestedMaster ) ) ;
54+ if ( nestedMaster is not null && compiledPaths . Add ( nestedMaster ) )
55+ discoveredMasterPages . Enqueue ( nestedMaster ) ;
6056 }
6157
6258 var allDiagnostics = diagnostics . Distinct ( ) . ToImmutableArray ( ) ;
@@ -74,8 +70,10 @@ public static ImmutableArray<DotvvmCompilationDiagnostic> CompileAll(
7470
7571 private static ImmutableArray < DotvvmCompilationDiagnostic > CompileNoThrow (
7672 DotvvmConfiguration configuration ,
77- string viewPath )
73+ string viewPath ,
74+ out string ? masterPage )
7875 {
76+ masterPage = null ;
7977 var fileLoader = configuration . ServiceProvider . GetRequiredService < IMarkupFileLoader > ( ) ;
8078 var file = fileLoader . GetMarkup ( configuration , viewPath ) ;
8179 if ( file is null )
@@ -88,10 +86,11 @@ private static ImmutableArray<DotvvmCompilationDiagnostic> CompileNoThrow(
8886 try
8987 {
9088 var compiler = configuration . ServiceProvider . GetRequiredService < IViewCompiler > ( ) ;
91- var ( _ , builderFactory ) = compiler . CompileView (
89+ var ( descriptor , builderFactory ) = compiler . CompileView (
9290 sourceCode : sourceCode ,
9391 fileName : viewPath ) ;
9492 _ = builderFactory ( ) ;
93+ masterPage = descriptor . MasterPage ? . FileName ;
9594 // TODO: get warnings from compilation tracer
9695 return ImmutableArray . Create < DotvvmCompilationDiagnostic > ( ) ;
9796 }
0 commit comments