Accessing the resources during active annotation processing.

858 views
Skip to first unread message

chris...@gmail.com

unread,
Dec 6, 2013, 9:44:42 AM12/6/13
to xtend...@googlegroups.com
I am revisiting some work I did on accessing resource bundles (i.e. properties files) during active annotation processing.

I just can't figure out how to do it! Can it be done?

I have an eclipse project structure like this:

myProject
--- source
------ myPackage
--------- myAnnotatedClass.xtend
--- resouces
------ myPackage
--------- myBundle.properties

I want to be able to load the myBundle.properties file?

Here is what I have tried:

Method 1:
ResourceBundle.getBundle("myBundle") 
ResourceBundle.getBundle("myPackage.myBundle")
Both don't yield anything.

Method 2:
Getting the project folder (using FileSystemSupport) for the annotated class, works it gives me: /myProject
But when I try to get the children of it, I get nothing.



Ideas
Could the various context objects available during annotation parsing be enhanced to find/lookup/load a resource in the current project/classpath just as you can with a ClassLoader? 
Could the FileSystemSupport be enhanced to support the entire project structure, or find/lookup/load a resource ?


Can anyone shed some light on the situation?

Thanks

C.

Sven Efftinge

unread,
Dec 6, 2013, 10:01:39 AM12/6/13
to xtend...@googlegroups.com

On Dec 6, 2013, at 3:44 PM, chris...@gmail.com wrote:
Ideas
Could the FileSystemSupport be enhanced to support the entire project structure, or find/lookup/load a resource ?

That's how it is intended to work.
Can you share what exactly you tried?

Thanks,
Sven
signature.asc

chris...@gmail.com

unread,
Dec 9, 2013, 8:50:11 AM12/9/13
to xtend...@googlegroups.com

Sven, here is some more information, and a simplification of what I was trying to do:



My Annotation
@Retention(RetentionPolicy::SOURCE)
@Target(ElementType::TYPE)
@Active(ProjectStructureProcessor)
annotation ProjectStructure
}

My Annotated Interface
@ProjectStructure()
interface ResourceDefinition
{
def String aaa() 
}

My Annotation Processor
class ProjectStructureProcessor extends AbstractInterfaceProcessor
def private List<Path> getPaths(Path folder, extension TransformationContext context)
{
log("folder: " + folder)
val list = <Path>newArrayList()
val q = new LinkedList<Path>
q.offer(folder) 
while (!q.empty)
{
val p = q.poll
log("poll q: " + p) 
list.add(p) 
context.getChildren(p).forEach[q.add(it)]
}
list
}

override doRegisterGlobals(InterfaceDeclaration annotatedInterface, RegisterGlobalsContext context)
{
super.doRegisterGlobals(annotatedInterface, context)
}

override doTransform(MutableInterfaceDeclaration annotatedInterface, extension TransformationContext context)
{
super.doTransform(annotatedInterface, context)
log(annotatedInterface.toString) 
val projectFolder = annotatedInterface.compilationUnit.filePath.projectFolder
log("project\n" + getPaths(projectFolder, context).toString) 
val sourceFolder = annotatedInterface.compilationUnit.filePath.sourceFolder
log("source\n" + getPaths(sourceFolder, context).toString) 
val targetFolder = annotatedInterface.compilationUnit.filePath.targetFolder
log("target\n" + getPaths(targetFolder, context).toString)
}

override doGenerateCode(InterfaceDeclaration annotatedInterface, extension CodeGenerationContext context)
{
super.doGenerateCode(annotatedInterface, context)
}


And here is an exception I get on the annotated interface:
Error during annotation processing:
java.lang.IllegalArgumentException:
   Path must include project and resource name: /MiscTools
at
   org.eclipse.core.runtime.Assert.isLegal(Assert.java:63)
at
   org.eclipse.core.internal.resources.Workspace.newResource(Workspace.java:2163)
at
   org.eclipse.core.internal.resources.Container.getFolder(Container.java:222)
at
   org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getEclipseFolder(EclipseFileSystemSupportImpl.java:56)
at
   org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getChildren(EclipseFileSystemSupportImpl.java:76)
at
   org.eclipse.xtend.core.macro.TransformationContextImpl.getChildren(TransformationContextImpl.java:338)
at
   resources.ProjectStructureProcessor.getPaths(ProjectStructureProcessor.java:42)
at
   resources.ProjectStructureProcessor.doTransform(ProjectStructureProcessor.java:70)
at
   annotation.processing.AbstractInterfaceProcessor.doTransform(AbstractInterfaceProcessor.java:18)

If I try and process the source directory first (rather than the project folder) I get a different exception on the annotated interface:
Error during annotation processing:
org.eclipse.core.internal.resources.ResourceException:
   Resource '/MiscTools/source/tools/SomeTool.xtend'
   does not exist.
at org.eclipse.core.internal.resources.Resource.checkExists(Resource.java:341)
at
   org.eclipse.core.internal.resources.Resource.checkAccessible(Resource.java:215)
at
   org.eclipse.core.internal.resources.Container.members(Container.java:266)
at
   org.eclipse.core.internal.resources.Container.members(Container.java:249)
at
   org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getChildren(EclipseFileSystemSupportImpl.java:77)
at
   org.eclipse.xtend.core.macro.TransformationContextImpl.getChildren(TransformationContextImpl.java:338)
...




I hope this sheds some light on the problem.

Thanks,

Chris.

Anton Kosyakov

unread,
Dec 9, 2013, 10:06:52 AM12/9/13
to xtend...@googlegroups.com
Hi,

It seems there is a bug into implementation of org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getChildren method for a project path.

You can introduce annotation property to narrow search path and avoid this problem, e.g. /MiscTools/resources will be a search path instead of just /MiscTools. 

I’ve done an example for you:

1. Client: 
package foo

@Foo('resources’) // this annotation will iterate over all sub folders of ‘resources' folder and collect properties files
class FooClient {
}

2. Annotation:
package foo

import java.util.List
import org.eclipse.xtend.lib.macro.AbstractClassProcessor
import org.eclipse.xtend.lib.macro.Active
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
import org.eclipse.xtend.lib.macro.file.Path

@Active(FooProcessor)
annotation Foo {

String value // a folder path for processing

}

class FooProcessor extends AbstractClassProcessor {

override doTransform(MutableClassDeclaration annotatedClass, extension TransformationContext context) {
val projectFolder = annotatedClass.compilationUnit.filePath.projectFolder

val value = annotatedClass.findAnnotation(Foo.newTypeReference.type).getValue('value') as String
val path = projectFolder.append(value)

val properties = path.findProperties(newArrayList, context)
...
}

def List<Path> findProperties(Path path, List<Path> results, extension TransformationContext context) {
for (child : path.children) {
if (child.folder) {
child.findProperties(results, context)
}
if (child.file && child.fileExtension.equals("properties")) {
results += child
}
}
results
}

}

Might it even be enough to specify a path to the particular file and avoid iterating over subfolders at all?

Best regards,
Anton

--
You received this message because you are subscribed to the Google Groups "Xtend Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xtend-lang+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

chris...@gmail.com

unread,
Dec 9, 2013, 3:45:43 PM12/9/13
to xtend...@googlegroups.com

Thanks for you reply Anton, I tried you suggestion and it works - thank you.

I hope the bug in org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getChildren is fixed soon, as I didn't want to have project configuration polluting the annotation/code, but it's a work around for now.


Chris

Anton Kosyakov

unread,
Dec 10, 2013, 4:26:48 AM12/10/13
to xtend...@googlegroups.com
Hi,


Regarding to the second exception: 
org.eclipse.core.internal.resources.ResourceException:
   Resource '/MiscTools/source/tools/SomeTool.xtend'
   does not exist.
at org.eclipse.core.internal.resources.Resource.checkExists(Resource.java:341)
at
   org.eclipse.core.internal.resources.Resource.checkAccessible(Resource.java:215)
at
   org.eclipse.core.internal.resources.Container.members(Container.java:266)
at
   org.eclipse.core.internal.resources.Container.members(Container.java:249)
at
   org.eclipse.xtext.xbase.ui.file.EclipseFileSystemSupportImpl.getChildren(EclipseFileSystemSupportImpl.java:77)
at
   org.eclipse.xtend.core.macro.TransformationContextImpl.getChildren(TransformationContextImpl.java:338)

You tried to get children (subfolders) of the file, it’s just not possible. You have to check first whether a given child is folder.

Best regards,
Anton
Reply all
Reply to author
Forward
0 new messages