简体   繁体   中英

How to get resource from INode in Xtext?

A value converter for my XText grammar depends on an eclipse preference, so I need to get the project of the current file. I have tried this:

class IStringValueConverter extends OtherIStringValueConverter {

    @Inject MyLanguageGrammarAccess grammarAccess

    // this is called in toValue(String string, INode node) if some conditions are fullfilled
    override correctAssignementValue(String path, INode node, AssignmentImpl assign) {

            try {
            val uri = assign.eContainer.eResource.URI //<<<<<< ?????

            val root = ResourcesPlugin.getWorkspace().getRoot();
            val file = root.getFile(new Path(uri.toPlatformString(true)));

            [do something for which I need the file]

                return super.correctAssignementValue(path, node, assign)
            } catch (Exception ex) {
                ex.printStackTrace
                return path
        }

    }
}

The issue is in the line marked with question marks. I have tried:

assign.eContainer.eResource.URI
assign.eResource.URI
node.grammarElement.eResource.URI

All of those return the same URL: classpath:/my/Language.xtextbin

Which is a file generated by XText, and not my resource. What am I doing wrong, how can I get the resource that is currently being parsed?

you can ask nodes for their parent. and for their semantic element. that should allow you to retrieve the information you need. alternatively you can customize DefaultEcoreElementFactory too.

What I did in the end:

I created a Guice scope which scopes on the file, and extended the IResourceFactory (not DefaultEcoreElementFactory) implementation to enter this scope at the correct time:

public class UiResourceFactory extends MyResourceFactory {

  private FileScope scope;

  @Inject
  public UiResourceFactory(Injector injector) {
    super(injector);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Resource createResource(URI uri) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    IFile file = root.getFile(new Path(uri.toPlatformString(true)));
    scope.enter(file);
    try {
      return super.createResource(uri);
    } finally {
      scope.exit();
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void setInjector(Injector injector) {
    super.setInjector(injector);
    scope = getInjector().getInstance(FileScope.class);
  }

}

That way my ValueConverter can get correctly scoped objects injected (it is created for each value that needs to be converted, apparently, so there are no issues with side effects. The reason why getting the resource did not work is that the ValueConverter is used during parsing, the parse tree is not actually associated to the resource yet. The information what the resource is is located quite high in the call chain, IResourceFactory seemed like a good place to put the scope since the Injector is set there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM