1313import java .io .StringReader ;
1414import java .io .UncheckedIOException ;
1515import java .lang .reflect .Modifier ;
16+ import java .net .URI ;
1617import java .nio .charset .Charset ;
1718import java .nio .file .Files ;
1819import java .nio .file .Path ;
7778import io .quarkus .arc .processor .DotNames ;
7879import io .quarkus .arc .processor .InjectionPointInfo ;
7980import io .quarkus .arc .processor .QualifierRegistrar ;
81+ import io .quarkus .bootstrap .model .ApplicationModel ;
82+ import io .quarkus .bootstrap .workspace .SourceDir ;
83+ import io .quarkus .bootstrap .workspace .WorkspaceModule ;
8084import io .quarkus .deployment .ApplicationArchive ;
8185import io .quarkus .deployment .Feature ;
8286import io .quarkus .deployment .GeneratedClassGizmo2Adaptor ;
9195import io .quarkus .deployment .builditem .GeneratedClassBuildItem ;
9296import io .quarkus .deployment .builditem .GeneratedResourceBuildItem ;
9397import io .quarkus .deployment .builditem .HotDeploymentWatchedFileBuildItem ;
98+ import io .quarkus .deployment .builditem .LaunchModeBuildItem ;
9499import io .quarkus .deployment .builditem .LiveReloadBuildItem ;
95100import io .quarkus .deployment .builditem .ServiceStartBuildItem ;
96101import io .quarkus .deployment .builditem .nativeimage .NativeImageResourceBuildItem ;
97102import io .quarkus .deployment .builditem .nativeimage .ReflectiveClassBuildItem ;
98103import io .quarkus .deployment .pkg .NativeConfig ;
99104import io .quarkus .deployment .pkg .builditem .CurateOutcomeBuildItem ;
105+ import io .quarkus .dev .spi .DevModeType ;
100106import io .quarkus .gizmo2 .ClassOutput ;
101107import io .quarkus .maven .dependency .ArtifactKey ;
102108import io .quarkus .maven .dependency .DependencyFlags ;
148154import io .quarkus .qute .runtime .QuteConfig ;
149155import io .quarkus .qute .runtime .QuteRecorder ;
150156import io .quarkus .qute .runtime .QuteRecorder .QuteContext ;
157+ import io .quarkus .qute .runtime .QuteRecorder .TemplateInfo ;
151158import io .quarkus .qute .runtime .TemplateProducer ;
152159import io .quarkus .qute .runtime .debug .DebugQuteEngineObserver ;
153160import io .quarkus .qute .runtime .extensions .CollectionTemplateExtensions ;
@@ -653,7 +660,7 @@ void analyzeTemplates(EffectiveTemplatePathsBuildItem effectiveTemplatePaths,
653660 for (TemplatePathBuildItem path : effectiveTemplatePaths .getTemplatePaths ()) {
654661 if (path .isTag ()) {
655662 String tagPath = path .getPath ();
656- String tagName = tagPath .substring (TemplatePathBuildItem .TAGS .length (), tagPath .length ());
663+ String tagName = tagPath .substring (EngineProducer .TAGS .length (), tagPath .length ());
657664 if (tagName .contains ("." )) {
658665 tagName = tagName .substring (0 , tagName .indexOf ('.' ));
659666 }
@@ -764,7 +771,7 @@ public void beforeParsing(ParserHelper parserHelper) {
764771 }
765772 }
766773
767- if (templateId .startsWith (TemplatePathBuildItem .TAGS )) {
774+ if (templateId .startsWith (EngineProducer .TAGS )) {
768775 parserHelper .addParameter (UserTagSectionHelper .Factory .ARGS ,
769776 UserTagSectionHelper .Arguments .class .getName ());
770777 }
@@ -2222,7 +2229,8 @@ void collectTemplates(ApplicationArchivesBuildItem applicationArchives,
22222229 BuildProducer <TemplatePathBuildItem > templatePaths ,
22232230 BuildProducer <NativeImageResourceBuildItem > nativeImageResources ,
22242231 QuteConfig config ,
2225- TemplateRootsBuildItem templateRoots )
2232+ TemplateRootsBuildItem templateRoots ,
2233+ LaunchModeBuildItem launchMode )
22262234 throws IOException {
22272235
22282236 // Make sure the new templates are watched as well
@@ -2244,55 +2252,82 @@ public boolean test(String path) {
22442252 excludePatterns .add (Pattern .compile (exclude .getRegexPattern ()));
22452253 }
22462254
2255+ final boolean tryLocateSource = launchMode .getLaunchMode ().isDev ()
2256+ && DevModeType .LOCAL == launchMode .getDevModeType ().orElse (null );
22472257 final Set <ApplicationArchive > allApplicationArchives = applicationArchives .getAllApplicationArchives ();
22482258 final Set <ArtifactKey > appArtifactKeys = new HashSet <>(allApplicationArchives .size ());
22492259 for (var archive : allApplicationArchives ) {
22502260 appArtifactKeys .add (archive .getKey ());
22512261 }
2252- for ( ResolvedDependency artifact : curateOutcome .getApplicationModel ()
2253- .getDependencies (DependencyFlags .RUNTIME_EXTENSION_ARTIFACT )) {
2262+ ApplicationModel applicationModel = curateOutcome .getApplicationModel ();
2263+ for ( ResolvedDependency artifact : applicationModel .getDependencies (DependencyFlags .RUNTIME_EXTENSION_ARTIFACT )) {
22542264 // Skip extension archives that are also application archives
22552265 if (!appArtifactKeys .contains (artifact .getKey ())) {
22562266 scanPathTree (artifact .getContentTree (), templateRoots , watchedPaths , templatePaths , nativeImageResources ,
2257- config , excludePatterns , TemplatePathBuildItem .APP_ARCHIVE_PRIORITY );
2267+ config , excludePatterns , TemplatePathBuildItem .APP_ARCHIVE_PRIORITY , null , tryLocateSource );
22582268 }
22592269 }
22602270 for (ApplicationArchive archive : applicationArchives .getApplicationArchives ()) {
22612271 archive .accept (
22622272 tree -> scanPathTree (tree , templateRoots , watchedPaths , templatePaths , nativeImageResources , config ,
2263- excludePatterns , TemplatePathBuildItem .APP_ARCHIVE_PRIORITY ));
2273+ excludePatterns , TemplatePathBuildItem .APP_ARCHIVE_PRIORITY , null , tryLocateSource ));
2274+ }
2275+ WorkspaceModule appModule ;
2276+ if (tryLocateSource ) {
2277+ appModule = applicationModel .getApplicationModule ();
2278+ } else {
2279+ appModule = null ;
22642280 }
22652281 applicationArchives .getRootArchive ().accept (
22662282 tree -> scanPathTree (tree , templateRoots , watchedPaths , templatePaths , nativeImageResources , config ,
2267- excludePatterns , TemplatePathBuildItem .ROOT_ARCHIVE_PRIORITY ));
2283+ excludePatterns , TemplatePathBuildItem .ROOT_ARCHIVE_PRIORITY , appModule , tryLocateSource ));
22682284 }
22692285
22702286 private void scanPathTree (PathTree pathTree , TemplateRootsBuildItem templateRoots ,
22712287 BuildProducer <HotDeploymentWatchedFileBuildItem > watchedPaths ,
22722288 BuildProducer <TemplatePathBuildItem > templatePaths ,
22732289 BuildProducer <NativeImageResourceBuildItem > nativeImageResources ,
22742290 QuteConfig config , List <Pattern > excludePatterns ,
2275- int templatePriority ) {
2291+ int templatePriority , WorkspaceModule module , boolean tryLocateSource ) {
22762292 for (String templateRoot : templateRoots ) {
22772293 if (PathTreeUtils .containsCaseSensitivePath (pathTree , templateRoot )) {
22782294 pathTree .walkIfContains (templateRoot , visit -> {
2279- if (Files .isRegularFile (visit .getPath ())) {
2280- if (!Identifiers .isValid (visit .getPath ().getFileName ().toString ())) {
2295+ Path path = visit .getPath ();
2296+ if (Files .isRegularFile (path )) {
2297+ if (!Identifiers .isValid (path .getFileName ().toString ())) {
22812298 LOGGER .warnf ("Invalid file name detected [%s] - template is ignored" , visit .getPath ());
22822299 return ;
22832300 }
2284- LOGGER .debugf ("Found template: %s" , visit . getPath () );
2301+ LOGGER .debugf ("Found template: %s" , path );
22852302 // remove templateRoot + /
22862303 final String relativePath = visit .getRelativePath ();
22872304 String templatePath = relativePath .substring (templateRoot .length () + 1 );
22882305 for (Pattern p : excludePatterns ) {
22892306 if (p .matcher (templatePath ).matches ()) {
2290- LOGGER .debugf ("Template file excluded: %s" , visit . getPath () );
2307+ LOGGER .debugf ("Template file excluded: %s" , path );
22912308 return ;
22922309 }
22932310 }
2311+ // Try to find source
2312+ URI source = null ;
2313+ if (module != null ) {
2314+ for (SourceDir resources : module .getMainSources ().getResourceDirs ()) {
2315+ Path sourcePath = resources .getDir ().resolve (visit .getRelativePath ());
2316+ if (Files .isRegularFile (sourcePath )) {
2317+ LOGGER .debugf ("Source file found for template %s: %s" , templatePath , sourcePath );
2318+ source = sourcePath .toUri ();
2319+ }
2320+ }
2321+ } else if (tryLocateSource ) {
2322+ try {
2323+ source = visit .getUrl ().toURI ();
2324+ LOGGER .debugf ("Source file found for template %s: %s" , templatePath , source );
2325+ } catch (Exception e ) {
2326+ LOGGER .warnf ("Unable to locate source for %s: %s" , templatePath , e .toString ());
2327+ }
2328+ }
22942329 produceTemplateBuildItems (templatePaths , watchedPaths , nativeImageResources ,
2295- relativePath , templatePath , visit . getPath () , config , templatePriority );
2330+ relativePath , templatePath , path , config , templatePriority , source );
22962331 }
22972332 });
22982333 }
@@ -2621,20 +2656,12 @@ void initialize(BuildProducer<SyntheticBeanBuildItem> syntheticBeans, QuteRecord
26212656 EffectiveTemplatePathsBuildItem effectiveTemplatePaths , Optional <TemplateVariantsBuildItem > templateVariants ,
26222657 TemplateRootsBuildItem templateRoots , List <TemplatePathExcludeBuildItem > templatePathExcludes ) {
26232658
2624- List <String > templates = new ArrayList <>();
2625- List <String > tags = new ArrayList <>();
2626- Map <String , String > templateContents = new HashMap <>();
2627- for (TemplatePathBuildItem templatePath : effectiveTemplatePaths .getTemplatePaths ()) {
2628- if (templatePath .isTag ()) {
2629- // tags/myTag.html -> myTag.html
2630- String tagPath = templatePath .getPath ();
2631- tags .add (tagPath .substring (TemplatePathBuildItem .TAGS .length (), tagPath .length ()));
2632- } else {
2633- templates .add (templatePath .getPath ());
2634- }
2635- if (!templatePath .isFileBased ()) {
2636- templateContents .put (templatePath .getPath (), templatePath .getContent ());
2637- }
2659+ Map <String , TemplateInfo > templates = new HashMap <>();
2660+ for (TemplatePathBuildItem template : effectiveTemplatePaths .getTemplatePaths ()) {
2661+ templates .put (template .getPath (),
2662+ new TemplateInfo (template .getPath (),
2663+ template .getSource () != null ? template .getSource ().toString () : null ,
2664+ template .isFileBased () ? null : template .getContent ()));
26382665 }
26392666 Map <String , List <String >> variants ;
26402667 if (templateVariants .isPresent ()) {
@@ -2650,10 +2677,9 @@ void initialize(BuildProducer<SyntheticBeanBuildItem> syntheticBeans, QuteRecord
26502677
26512678 syntheticBeans .produce (SyntheticBeanBuildItem .configure (QuteContext .class )
26522679 .scope (BuiltinScope .SINGLETON .getInfo ())
2653- .supplier (recorder .createContext (templates ,
2654- tags , variants ,
2655- templateRoots .getPaths ().stream ().map (p -> p + "/" ).collect (Collectors .toSet ()), templateContents ,
2656- excludePatterns ))
2680+ .supplier (recorder .createContext (variants ,
2681+ templateRoots .getPaths ().stream ().map (p -> p + "/" ).collect (Collectors .toSet ()),
2682+ excludePatterns , templates ))
26572683 .done ());
26582684 }
26592685
@@ -3635,7 +3661,7 @@ public static String getName(InjectionPointInfo injectionPoint) {
36353661 private static void produceTemplateBuildItems (BuildProducer <TemplatePathBuildItem > templatePaths ,
36363662 BuildProducer <HotDeploymentWatchedFileBuildItem > watchedPaths ,
36373663 BuildProducer <NativeImageResourceBuildItem > nativeImageResources , String resourcePath ,
3638- String templatePath , Path originalPath , QuteConfig config , int templatePriority ) {
3664+ String templatePath , Path originalPath , QuteConfig config , int templatePriority , URI source ) {
36393665 if (templatePath .isEmpty ()) {
36403666 return ;
36413667 }
@@ -3652,6 +3678,7 @@ private static void produceTemplateBuildItems(BuildProducer<TemplatePathBuildIte
36523678 templatePaths .produce (TemplatePathBuildItem .builder ()
36533679 .path (templatePath )
36543680 .fullPath (originalPath )
3681+ .source (source )
36553682 .priority (templatePriority )
36563683 .content (readTemplateContent (originalPath , config .defaultCharset ()))
36573684 .build ());
0 commit comments