xtext中的跨文件引用和链接

时间:2015-12-07 01:47:44

标签: dsl xtext emf cross-reference

我使用xtext创建了一个新的DSL,如下所示。 (实际上我将在RCP应用程序上访问DSL。)

grammar org.xtext.example.mydsl.MyDsl with      org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"


Configuration:
components+=(Component)*;

Component:
'Component' name=ID
'{'
(('display' display=STRING) &
('dependency' dependency=[Component|ID])?)
'}'
 ;

我有两个文件:sample1.mydsl

 Component comp1 {
     display "comp1"
     children comp2
 }

sampl2.mydsl

 Component comp2 {
      display "comp2"
 }

在RCP应用程序中,我将使用Configuration模型编写树视图。但是当我从comp1对象的getChildren()方法获取comp2对象时,有时候我无法准确地获得comp2对象。

  1. 我按如下方式加载了模型数据:

        private List<ConfigurationItem> itemList;
    
        void loadData() {
        project =               ResourcesPlugin.getWorkspace().getRoot().getProject("test");
    
        XtextResourceSet resourceSet = (XtextResourceSet) injector
            .getInstance(XtextResourceSetProvider.class)
            .get(project);
        resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
    
        IFile[] samples = findFiles(resources);
    
        List<Resource> resourceList = new ArrayList<Resource>();
        for (IFile sample : samples) {
            Resource resourceSample = resourceSet.getResource(
                    URI.createURI(sample.getLocationURI().toString(), true), true);
            resourceList.add(resourceSample);
        }
    
        for (Resource resource : resourceList) {
            System.out.println("resource = " + resource.toString());
            try {
                resource.load(null);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            EcoreUtil.resolveAll(resource);
        }
    
        // add all to configuration item list
        for (Resource rc : resourceList) {
            Configuration config = (Configuration) rc.getContents().get(0);
            itemList.addAll(config.getConfigurationItems().toArray(new ConfigurationItem[config.getConfigurationItems().size()]));
        }
    

    }

  2. 测试代码

    for (ConfigurationItem item : itemList) {
       if (item.getName().equals("comp1") {
          Component[] comps = item.getChildren();
          for (Component comp : comps) {
             if (comp != null) {
                 System.out.println("comp display : " + comp.getDisplay());
             }
          }
      }
    

    }

  3. 结果

    comp display : null
    
  4. 我希望结果是&#34; comp display:comp2&#34;。

    但有时结果是&#34; comp显示:comp2&#34;

    有时结果是&#34; comp display:null&#34;

    我认为这是因为xtext的延迟链接。

    我怎样才能得到正确的结果 - &gt; &#34; comp显示:comp2&#34;?

    我希望有人可以帮我解决。感谢。

3 个答案:

答案 0 :(得分:0)

您可以尝试以下代码:

  void loadData() {
    project =               ResourcesPlugin.getWorkspace().getRoot().getProject("test");
    ResourceSet resourceSet = new ResourceSetImpl();
IFile[] samples = findFiles(project);
List<Resource> resourceList = new ArrayList<Resource>();
for (IFile sample : samples) {
    Resource resourceSample = resourceSet.getResource(
            URI.createURI(sample.getFullPath().toString()), true);
    resourceList.add(resourceSample);
}


// add all to configuration item list
for (Resource rc : resourceList) {
    Configuration config = (Configuration) rc.getContents().get(0);
    itemList.addAll(config.getConfigurationItems()));
}
}

答案 1 :(得分:0)

我制作了一份分析样本。 请查看以下内容。

  1. 以下代码是我的示例测试代码。我打电话 new SampleConfigLoadOperation3()。run(monitor);在我的RCP申请表上。
  2. SampleConfigLoadOperation3.java

    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.eclipse.core.resources.IFile;
    import org.eclipse.core.resources.IFolder;
    import org.eclipse.core.resources.IProject;
    import org.eclipse.core.resources.IResource;
    import org.eclipse.core.resources.IWorkspace;
    import org.eclipse.core.resources.IWorkspaceRoot;
    import org.eclipse.core.resources.ResourcesPlugin;
    import org.eclipse.core.runtime.CoreException;
    import org.eclipse.core.runtime.IProgressMonitor;
    import org.eclipse.emf.common.util.URI;
    import org.eclipse.emf.ecore.resource.Resource;
    import org.eclipse.emf.ecore.resource.ResourceSet;
    import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
    import org.eclipse.jface.operation.IRunnableWithProgress;
    
    import com.mdstec.ide.kcdsl.ConfigDSL.ConfigurationItem;
    import com.mdstec.ide.kcdsl.ConfigDSL.Configuration;
    
    
    public class SampleConfigLoadOperation3 implements IRunnableWithProgress {
    
    // Progress message
    final String loadConfigTaskBeginMsg = "load configuration.";
    
    IProject project;
    
    DataListener dataListener;
    
    /**
     * Constructor for project configuration object
     * 
     * @param prjConfig
     *            the project configuration object
     */
    public SampleConfigLoadOperation3() {
        // TODO Auto-generated constructor stub
    }
    
    
    public SampleConfigLoadOperation3(IProject project, DataListener listner) {
        // TODO Auto-generated constructor stub
        this.project = project;
        this.dataListener = listner;
    
    }
    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException,
            InterruptedException {
        // TODO Auto-generated method stub
        if (monitor != null) {
            monitor.beginTask(loadConfigTaskBeginMsg, IProgressMonitor.UNKNOWN);
        }
    
        try {
            loadConfigData(monitor);
        } catch (Exception e) {
            throw new InvocationTargetException(e, "Loading error" + ": "
                    + e.getMessage());
        } finally {
            if (monitor != null) {
                monitor.done();
            }
        }
    
        if (monitor != null) {
            if (monitor.isCanceled()) {
                throw new InterruptedException("Cancel loading");
            }
        }
    
    }
    
    private void loadConfigData(IProgressMonitor monitor) {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IWorkspaceRoot workspaceRoot = workspace.getRoot();
        project  = workspaceRoot.getProject("testproject");
        IFolder sampleFolder = project.getFolder("data");
        //at this point, no resources have been created
        try {
            if (!project.exists())
                project.create(null);
            if (!project.isOpen()) 
                project.open(null);
        } catch (CoreException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
    
        if (!sampleFolder.exists()) {
            try {
                sampleFolder.create(IResource.NONE, true, null);
            } catch (CoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        copyDataFileToProject("sample1.cdl", "data");
        copyDataFileToProject("sample2.cdl", "data");
    
    
        ResourceSet resourceSet = new ResourceSetImpl();
    
        IResource[] resources = null;
        try {
            resources = sampleFolder.members();
        } catch (CoreException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        if (resources != null) {
            IFile[] samples = findFiles(resources);
            List<Resource> resourceList = new ArrayList<Resource>();
            for (IFile sample : samples) {
                Resource resourceSample = resourceSet.getResource(
                        URI.createURI(sample.getFullPath().toString()), true);
    
                resourceList.add(resourceSample);
            }
    
            // add all to configuration item list
            List<ConfigurationItem> configItemList = new ArrayList<ConfigurationItem>();
            for (Resource rc : resourceList) {
                Configuration config = (Configuration) rc
                        .getContents().get(0);
                configItemList.addAll(config.getConfigurationItems());
            }
    
            // root model
            List<ConfigurationItem> rootItemList = new ArrayList<ConfigurationItem>();
            // set root list in configuration item list
            for (int i = 0; i < configItemList.size(); i++) {
                ConfigurationItem item = configItemList.get(i);
                if (item instanceof com.mdstec.ide.kcdsl.ConfigDSL.Package) {
                    if (((com.mdstec.ide.kcdsl.ConfigDSL.Package) item)
                            .isIsRoot()) {
                        rootItemList.add(item);
                    }
                }
            }
    
            // set parents
            for (int i = 0; i < rootItemList.size(); i++) {
                ConfigurationItem root = rootItemList.get(i);
                ConfigurationItem[] children = (ConfigurationItem[]) root
                        .getChildren().toArray();
                setParent(children, root);
    
            }
    
            System.out.println("root size = " + rootItemList.size());
            for (ConfigurationItem item : rootItemList) {
                findChildren(item);
            }
    
    
        }
    }
    
    private void copyDataFileToProject(String fileName, String prjDir) {
        // TODO Auto-generated method stub
        File file = new File("C:/test/data/" + fileName);
        URL sourceURL = null;
        try {
            sourceURL = file.toURL(); // using .toURI().toURL()
                                        // fails,
                                        // due to
                                        // spaces substitution
    
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        InputStream in = null;
        try {
            in = sourceURL.openStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        IFile iFile = project.getFile(prjDir + "/" + fileName);
        if (!iFile.exists()) {
            try {
                iFile.create(in, true, null);
                iFile.refreshLocal(IResource.DEPTH_ONE, null);
            } catch (CoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    
    private void findChildren(ConfigurationItem item) {
        // TODO Auto-generated method stub
    
        ConfigurationItem[] children = (ConfigurationItem[]) item.getChildren()
                .toArray();
        if (children != null && children.length > 0) {
            for (ConfigurationItem child : children) {
                System.out.println("child name of " + item.getName() + " : "
                        + child.getName());
                findChildren(child);
            }
        }
    }
    
    private void setParent(ConfigurationItem[] children,
            ConfigurationItem parent) {
        // TODO Auto-generated method stub
        if (children != null && children.length > 0) {
            for (ConfigurationItem child : children) {
                child.setParent(parent);
                setParent((ConfigurationItem[]) child.getChildren().toArray(),
                        child);
            }
        }
    }
    
    private IFile[] findFiles(IResource[] resources) {
        List<IFile> fileList = new ArrayList<IFile>();
        find(resources, fileList);
        return fileList.toArray(new IFile[fileList.size()]);
    }
    
    private void find(IResource[] resources, List<IFile> fileList) {
        // TODO Auto-generated method stub
    
        if (resources != null && resources.length > 0) {
            for (IResource res : resources) {
                if (res instanceof IFile) {
                    fileList.add((IFile) res);
                } else if (res instanceof IFolder) {
                    IResource[] reses;
                    try {
                        reses = ((IFolder) res).members();
                        find(reses, fileList);
                    } catch (CoreException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
    
                }
            }
        }
    }
    
    }
    
    1. 我使用xtext定义了我的DSL,如下所示,并生成了模型和解析器。
    2. ConfigDSL.xtext

      generate ConfigDSL "............."
      
      Configuration:
          ((configurationItems+=ConfigurationItem)*
      ;
      
      ConfigurationItem:
          Package | Component
      ;
      
      Package:
          'Package' name=ID
          '{'
              (('display' display=STRING) &
              ('description' description=STRING)? &
              ('children' children += [ConfigurationItem|ID] (',' children +=         [ConfigurationItem|ID])*)?  &
              ('parent' parent = [ConfigurationItem|ID])? &
              ('isRoot' isRoot=BOOLEAN)?
              )
          '}'
      ;
      
      Component:
          'Component' name=ID
          '{'
              (('display' display=STRING) &
              ('parent' parent = [ConfigurationItem|ID])?
              )
          '}'
      ;
      
      terminal BOOLEAN returns ecore::EBoolean
          : 'true' | 'false';
      
      1. 我创建了两个DSL文件(sample1.cdl,sample2.cdl),如下所示,位于&#34; C:/ test / data&#34;目录。
      2. sample1.cdl

        Component ds1 {
            display "ds1"
        }
        
        Component ds2 {
            display "ds2"
        }
        
        
        Package pk1 {
            display "pk1"
            children ds1, ds2, ds3
            isRoot true
        }
        

        sample2.cdl

        Component ds3 {
            display "ds3"
        }
        
        1. 当我调用&#34; new SampleConfigLoadOperation3()。run(monitor);&#34;在我的RCP应用程序中,结果如下。

          root size = 1
          child name of pk1 : ds1
          child name of pk1 : ds2
          child name of pk1 : null
          
        2. 我不知道为什么第3行的结果是&#34; pk1的子名称:null&#34;。 我希望结果是&#34; pk1的子名:ds3&#34;。

答案 2 :(得分:0)

我解决了这个问题。 创建ResourceSet对象时,我修改了如下代码。 现在效果很好。

     Injector injector = new MyDSLStandaloneSetup().createInjectorAndDoEMFRegistration();
     XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);

我理解错误,MyDSLStandaloneSetup()不应该在RCP中使用。