Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2019-11-29 11:30:12 -0500
committerHenrik Rentz-Reichert2019-11-29 11:30:12 -0500
commit34912487f8dc3014f3f43cfb285dac815adda60d (patch)
tree544a8863e9e294a1623500067d75ac3538922cdc
parentef61f47c1b777774534fb4c7dcd486dff08d698c (diff)
downloadorg.eclipse.etrice-34912487f8dc3014f3f43cfb285dac815adda60d.tar.gz
org.eclipse.etrice-34912487f8dc3014f3f43cfb285dac815adda60d.tar.xz
org.eclipse.etrice-34912487f8dc3014f3f43cfb285dac815adda60d.zip
Bug 546282 - [ui] Implement "organize imports"
Implemented a fairly general mechanism that can be adapted easily for other models, e.g. one using the FSM part only. Change-Id: Ib322afaed71b55e7dc66fb330a203520828f2c8f
-rw-r--r--plugins/org.eclipse.etrice.core.common.ui/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/IOrganizeImportHelper.java101
-rw-r--r--plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/ImportOrganizer.java186
-rw-r--r--plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/OrganizeImportsHandler.java84
-rw-r--r--plugins/org.eclipse.etrice.core.room.ui/plugin.xml24
-rw-r--r--plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/RoomUiModule.java5
-rw-r--r--plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/imports/RoomOrganizeImportHelper.java114
7 files changed, 517 insertions, 1 deletions
diff --git a/plugins/org.eclipse.etrice.core.common.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.etrice.core.common.ui/META-INF/MANIFEST.MF
index c434bd944..74394d092 100644
--- a/plugins/org.eclipse.etrice.core.common.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.etrice.core.common.ui/META-INF/MANIFEST.MF
@@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.etrice.core.common;visibility:=reexport,
org.eclipse.core.filesystem,
org.eclipse.help,
org.eclipse.xtext.xbase.lib,
- org.eclipse.etrice.generator.base
+ org.eclipse.etrice.generator.base,
+ org.eclipse.xtext.xbase.ui
Import-Package: org.apache.log4j,
org.eclipse.xtext.xbase.lib
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -31,6 +32,7 @@ Export-Package: org.eclipse.etrice.core.common.ui.autoedit,
org.eclipse.etrice.core.common.ui.editor.model,
org.eclipse.etrice.core.common.ui.highlight,
org.eclipse.etrice.core.common.ui.hover,
+ org.eclipse.etrice.core.common.ui.imports,
org.eclipse.etrice.core.common.ui.internal,
org.eclipse.etrice.core.common.ui.labeling,
org.eclipse.etrice.core.common.ui.linking,
diff --git a/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/IOrganizeImportHelper.java b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/IOrganizeImportHelper.java
new file mode 100644
index 000000000..94ca67981
--- /dev/null
+++ b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/IOrganizeImportHelper.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2019 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+package org.eclipse.etrice.core.common.ui.imports;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.etrice.core.common.base.Import;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.util.ITextRegion;
+import org.eclipse.xtext.util.TextRegion;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ */
+public interface IOrganizeImportHelper {
+
+ public static class ImportRegionResult {
+ private ITextRegion region;
+ private boolean needNewLine;
+
+ public ImportRegionResult(int offset, int length, boolean needNewLine) {
+ super();
+ this.region = new TextRegion(offset, length);
+ this.needNewLine = needNewLine;
+ }
+ public ITextRegion getRegion() {
+ return region;
+ }
+ public boolean isNeedNewLine() {
+ return needNewLine;
+ }
+ }
+
+ /**
+ * @return a map of all {@link EClass}es that reference to be resolved objects with the corresponding {@link EReference}s
+ */
+ Multimap<EClass, EReference> getTypeReferences();
+
+ /**
+ * @param resource the Xtext resource being processed
+ * @return the region where the imports should go to
+ */
+ default ImportRegionResult getImportRegion(XtextResource resource) {
+ EObject root = resource.getContents().get(0);
+ TreeIterator<EObject> it = root.eAllContents();
+ int begin = Integer.MAX_VALUE;
+ int end = 0;
+ while (it.hasNext()) {
+ EObject object = it.next();
+ if (object instanceof Import) {
+ INode node = NodeModelUtils.findActualNodeFor(object);
+ if (node!=null) {
+ begin = Math.min(begin, node.getOffset());
+ end = Math.max(end, node.getEndOffset());
+ }
+ }
+ }
+ if (begin < end) {
+ return new ImportRegionResult(begin, end - begin, false);
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * @param object the object we need a qualified name for
+ * @return a fully qualified name for the object
+ */
+ QualifiedName getFullyQualifiedName(EObject object);
+
+ /**
+ * @param refText the reference text
+ * @param type the expected {@link EClass}
+ * @param resource the current resource
+ * @return a list of qualified names that resolve this reference
+ */
+ List<QualifiedName> resolveFullyQualifiedName(String refText, EClass type, Resource resource);
+}
diff --git a/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/ImportOrganizer.java b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/ImportOrganizer.java
new file mode 100644
index 000000000..d93dde004
--- /dev/null
+++ b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/ImportOrganizer.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2019 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+package org.eclipse.etrice.core.common.ui.imports;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.etrice.core.common.base.BaseFactory;
+import org.eclipse.etrice.core.common.base.Import;
+import org.eclipse.etrice.core.common.ui.imports.IOrganizeImportHelper.ImportRegionResult;
+import org.eclipse.xtext.formatting.IWhitespaceInformationProvider;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.util.ReplaceRegion;
+
+import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ */
+public class ImportOrganizer {
+
+ private static final int IMPORT_ALL_THRESHOLD = 3;
+
+ @Inject
+ private IOrganizeImportHelper organizeImportHelper;
+
+ @Inject
+ private IWhitespaceInformationProvider whitespaceInformationProvider;
+
+ public List<ReplaceRegion> getOrganizedImportChanges(XtextResource resource) {
+ Set<QualifiedName> typeUsages = getTypeUsages(resource);
+
+ typeUsages = simplifyImports(typeUsages);
+
+ List<ReplaceRegion> changes = getOrganizedImportChanges(resource, typeUsages);
+
+ removeNullEdits(resource, changes);
+
+ return changes;
+ }
+
+ protected Set<QualifiedName> getTypeUsages(XtextResource resource) {
+ Set<QualifiedName> result = new HashSet<>();
+
+ Multimap<EClass, EReference> typeReferences = organizeImportHelper.getTypeReferences();
+ EObject root = resource.getContents().get(0);
+ TreeIterator<EObject> it = root.eAllContents();
+ while (it.hasNext()) {
+ EObject object = it.next();
+ if (typeReferences.containsKey(object.eClass())) {
+ Collection<EReference> references = typeReferences.get(object.eClass());
+ references.forEach(ref -> {
+ Object refObject = object.eGet(ref);
+ if (refObject instanceof EObject) {
+ if (((EObject) refObject).eIsProxy()) {
+ List<INode> nodes = NodeModelUtils.findNodesForFeature((EObject) object, ref);
+ if (!nodes.isEmpty()) {
+ result.addAll(organizeImportHelper.resolveFullyQualifiedName(nodes.get(0).getText().trim(), ref.getEReferenceType(), resource));
+ }
+ }
+ else {
+ boolean isQualified = false;
+ List<INode> nodes = NodeModelUtils.findNodesForFeature((EObject) object, ref);
+ if (!nodes.isEmpty()) {
+ // check whether this is a qualified name
+ if (nodes.stream().filter(node -> !node.getText().contains(".")).count()==0l) {
+ isQualified = true;
+ }
+ }
+ if (!isQualified) {
+ QualifiedName namespace = organizeImportHelper.getFullyQualifiedName((EObject) refObject);
+ if (namespace!=null) {
+ result.add(namespace);
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+
+ // remove our own namespace
+ QualifiedName ownNamespace = organizeImportHelper.getFullyQualifiedName(root);
+ result.removeIf(fqn -> fqn.startsWith(ownNamespace));
+
+ return result;
+ }
+
+ private Set<QualifiedName> simplifyImports(Set<QualifiedName> typeUsages) {
+ Map<QualifiedName, List<QualifiedName>> grouped = typeUsages.stream().collect(Collectors.groupingBy(fqn->fqn.skipLast(1)));
+ Set<QualifiedName> result = new HashSet<>();
+ grouped.forEach((namespace, names) -> {
+ if (names.size() > IMPORT_ALL_THRESHOLD) {
+ result.add(namespace.append("*"));
+ }
+ else {
+ result.addAll(names);
+ }
+ });
+ return result;
+ }
+
+ protected List<ReplaceRegion> getOrganizedImportChanges(XtextResource resource, Set<QualifiedName> namespaces) {
+ ImportRegionResult importRegionResult = organizeImportHelper.getImportRegion(resource);
+ ArrayList<ReplaceRegion> result = newArrayList();
+ if (importRegionResult.getRegion()!=null) {
+ ArrayList<QualifiedName> sortedNamespaces = new ArrayList<>(namespaces);
+ Collections.sort(sortedNamespaces);
+ List<Import> allImportDeclarations = sortedNamespaces.stream().map(namespace -> createImport(namespace)).collect(Collectors.toList());
+ String lineSeparator = getLineSeparator(resource);
+ String newImportSection = serializeImports(allImportDeclarations, lineSeparator);
+ if (importRegionResult.isNeedNewLine()) {
+ newImportSection += lineSeparator + lineSeparator + "\t";
+ }
+ result.add(new ReplaceRegion(importRegionResult.getRegion(), newImportSection));
+ return result;
+ }
+ else {
+ return result;
+ }
+ }
+
+ protected void removeNullEdits(XtextResource resource, List<ReplaceRegion> changes) {
+ Iterator<ReplaceRegion> iterator = changes.iterator();
+ String document = resource.getParseResult().getRootNode().getText();
+ while(iterator.hasNext()) {
+ ReplaceRegion region = iterator.next();
+ if (region.getText().equals(document.substring(region.getOffset(), region.getEndOffset()))) {
+ iterator.remove();
+ }
+ }
+ }
+
+ protected Import createImport(QualifiedName namespace) {
+ Import result = BaseFactory.eINSTANCE.createImport();
+ result.setImportedNamespace(namespace.toString());
+ return result;
+ }
+
+ private String serializeImports(List<Import> allImportDeclarations, String newLine) {
+ if (allImportDeclarations.isEmpty()) {
+ return "";
+ }
+ StringBuilder builder = new StringBuilder();
+ allImportDeclarations.forEach(imp -> appendImport(builder, imp, newLine));
+ return builder.toString().trim(); // omit first \t and trailing newLine
+ }
+
+ protected void appendImport(StringBuilder builder, Import imp, String newLine) {
+ builder.append("\timport " + imp.getImportedNamespace() + newLine);
+ }
+
+ protected String getLineSeparator(XtextResource resource) {
+ return whitespaceInformationProvider.getLineSeparatorInformation(resource.getURI()).getLineSeparator();
+ }
+
+}
diff --git a/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/OrganizeImportsHandler.java b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/OrganizeImportsHandler.java
new file mode 100644
index 000000000..51f9d8e7b
--- /dev/null
+++ b/plugins/org.eclipse.etrice.core.common.ui/src/org/eclipse/etrice/core/common/ui/imports/OrganizeImportsHandler.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2019 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+package org.eclipse.etrice.core.common.ui.imports;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.model.IXtextDocument;
+import org.eclipse.xtext.ui.editor.utils.EditorUtils;
+import org.eclipse.xtext.util.ReplaceRegion;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+import org.eclipse.xtext.xbase.ui.imports.ReplaceConverter;
+
+import com.google.inject.Inject;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ * @see org.eclipse.xtext.xbase.ui.imports.OrganizeImportsHandler
+ *
+ */
+@SuppressWarnings("restriction") // ReplaceConverter is non-API
+public class OrganizeImportsHandler extends AbstractHandler {
+
+ private static final Logger LOG = Logger.getLogger(OrganizeImportsHandler.class);
+
+ @Inject private ReplaceConverter replaceConverter;
+
+ @Inject private ImportOrganizer importOrganizer;
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ XtextEditor editor = EditorUtils.getActiveXtextEditor(event);
+ if (editor != null) {
+ final IXtextDocument document = editor.getDocument();
+ doOrganizeImports(document);
+ }
+ return null;
+ }
+
+ public void doOrganizeImports(final IXtextDocument document) {
+ List<ReplaceRegion> result = document.priorityReadOnly(new IUnitOfWork<List<ReplaceRegion>, XtextResource>() {
+ @Override
+ public List<ReplaceRegion> exec(XtextResource state) throws Exception {
+ return importOrganizer.getOrganizedImportChanges(state);
+ }
+ });
+ if (result == null || result.isEmpty())
+ return;
+ try {
+ DocumentRewriteSession session = null;
+ if(document instanceof IDocumentExtension4) {
+ session = ((IDocumentExtension4)document).startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+ }
+ replaceConverter.convertToTextEdit(result).apply(document);
+ if(session != null) {
+ ((IDocumentExtension4)document).stopRewriteSession(session);
+ }
+ } catch (BadLocationException e) {
+ LOG.error("Error organizing imports:", e);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.etrice.core.room.ui/plugin.xml b/plugins/org.eclipse.etrice.core.room.ui/plugin.xml
index 311b0a822..fa2a92bc6 100644
--- a/plugins/org.eclipse.etrice.core.room.ui/plugin.xml
+++ b/plugins/org.eclipse.etrice.core.room.ui/plugin.xml
@@ -16,6 +16,7 @@
name="Room Editor">
</editor>
</extension>
+
<extension
point="org.eclipse.ui.handlers">
<handler
@@ -36,7 +37,17 @@
</reference>
</activeWhen>
</handler>
+ <handler
+ class="org.eclipse.etrice.core.ui.RoomExecutableExtensionFactory:org.eclipse.etrice.core.common.ui.imports.OrganizeImportsHandler"
+ commandId="org.eclipse.xtext.xbase.ui.organizeImports">
+ <activeWhen>
+ <reference
+ definitionId="org.eclipse.etrice.core.Room.Editor.opened">
+ </reference>
+ </activeWhen>
+ </handler>
</extension>
+
<extension point="org.eclipse.core.expressions.definitions">
<definition id="org.eclipse.etrice.core.Room.Editor.opened">
<and>
@@ -121,6 +132,19 @@
</visibleWhen>
</command>
</menuContribution>
+ <menuContribution
+ locationURI="popup:#TextEditorContext?after=group.edit">
+ <command
+ commandId="org.eclipse.xtext.xbase.ui.organizeImports"
+ style="push"
+ tooltip="Organize Imports">
+ <visibleWhen checkEnabled="false">
+ <reference
+ definitionId="org.eclipse.etrice.core.Room.Editor.opened">
+ </reference>
+ </visibleWhen>
+ </command>
+ </menuContribution>
</extension>
<extension point="org.eclipse.ui.menus">
<menuContribution locationURI="popup:#TextEditorContext?endof=group.find">
diff --git a/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/RoomUiModule.java b/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/RoomUiModule.java
index 06f9aeabb..8562599c7 100644
--- a/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/RoomUiModule.java
+++ b/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/RoomUiModule.java
@@ -21,11 +21,13 @@ import org.eclipse.etrice.core.common.ui.editor.folding.FoldingRegionProvider;
import org.eclipse.etrice.core.common.ui.editor.model.BaseTokenTypeToPartitionMapper;
import org.eclipse.etrice.core.common.ui.hover.BaseHoverDocumentationProvider;
import org.eclipse.etrice.core.common.ui.hover.IKeywordHoverContentProvider;
+import org.eclipse.etrice.core.common.ui.imports.IOrganizeImportHelper;
import org.eclipse.etrice.core.common.ui.linking.GlobalNonPlatformURIEditorOpener;
import org.eclipse.etrice.core.ui.highlight.RoomHighlightingConfiguration;
import org.eclipse.etrice.core.ui.highlight.RoomSemanticHighlightingCalculator;
import org.eclipse.etrice.core.ui.hover.RoomEObjectHover;
import org.eclipse.etrice.core.ui.hover.RoomHoverProvider;
+import org.eclipse.etrice.core.ui.imports.RoomOrganizeImportHelper;
import org.eclipse.etrice.core.ui.internal.RoomActivator;
import org.eclipse.etrice.core.ui.linking.RoomHyperlinkHelper;
import org.eclipse.etrice.core.ui.outline.RoomOutlinePage;
@@ -68,6 +70,9 @@ public class RoomUiModule extends org.eclipse.etrice.core.ui.AbstractRoomUiModul
binder.bind(IEObjectDocumentationProviderExtension.class).to(MultiLineCommentDocumentationProvider.class);
binder.bind(FQNPrefixMatcher.LastSegmentFinder.class).to(FQNLastSegmentFinder.class);
+
+ // namespace provider for OrganizeImports
+ binder.bind(IOrganizeImportHelper.class).to(RoomOrganizeImportHelper.class);
}
@Override
diff --git a/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/imports/RoomOrganizeImportHelper.java b/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/imports/RoomOrganizeImportHelper.java
new file mode 100644
index 000000000..eaa492033
--- /dev/null
+++ b/plugins/org.eclipse.etrice.core.room.ui/src/org/eclipse/etrice/core/ui/imports/RoomOrganizeImportHelper.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2019 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.core.ui.imports;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.etrice.core.common.base.util.ImportHelpers;
+import org.eclipse.etrice.core.common.ui.imports.IOrganizeImportHelper;
+import org.eclipse.etrice.core.room.RoomClass;
+import org.eclipse.etrice.core.room.RoomModel;
+import org.eclipse.etrice.core.room.RoomPackage;
+import org.eclipse.xtext.EcoreUtil2;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.nodemodel.ICompositeNode;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+import org.eclipse.xtext.resource.XtextResource;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ */
+public class RoomOrganizeImportHelper implements IOrganizeImportHelper {
+
+ @Inject
+ ImportHelpers importHelpers;
+
+ @Override
+ public Multimap<EClass, EReference> getTypeReferences() {
+ Multimap<EClass, EReference> result = ArrayListMultimap.create();
+ RoomPackage.eINSTANCE.getEClassifiers().stream() //
+ .filter(EClass.class::isInstance) //
+ .map(EClass.class::cast) //
+ .forEach(cls -> {
+ List<EReference> refs = cls.getEReferences().stream() //
+ .filter(ref -> !ref.isContainment() && typeNeedsImport(ref.getEReferenceType())) //
+ .collect(Collectors.toList());
+ if (!refs.isEmpty()) {
+ result.putAll(cls, refs);
+ }
+ });
+ return result;
+ }
+
+ @Override
+ public QualifiedName getFullyQualifiedName(EObject object) {
+ if (object instanceof RoomClass) {
+ EObject root = EcoreUtil2.getRootContainer(object);
+ if (root instanceof RoomModel) {
+ QualifiedName result = QualifiedName.create(((RoomModel) root).getName().split("\\."));
+ result = result.append(((RoomClass) object).getName());
+ return result;
+ }
+ }
+ else if (object instanceof RoomModel) {
+ return QualifiedName.create(((RoomModel) object).getName().split("\\."));
+ }
+ return null;
+ }
+
+ @Override
+ public List<QualifiedName> resolveFullyQualifiedName(String refText, EClass type, Resource resource) {
+ return importHelpers.createModelPathImports(refText, resource, type, false).stream() //
+ .map(imp -> importHelpers.toFQN(imp)).collect(Collectors.toList());
+ }
+
+ public ImportRegionResult getImportRegion(XtextResource resource) {
+ ImportRegionResult importRegion = IOrganizeImportHelper.super.getImportRegion(resource);
+ if (importRegion==null) {
+ // there is no import yet: check annotation types
+ if (resource.getContents().get(0) instanceof RoomModel) {
+ RoomModel roomModel = (RoomModel) resource.getContents().get(0);
+ EObject placeBefore = null;
+ if (!roomModel.getAnnotationTypes().isEmpty()) {
+ placeBefore = roomModel.getAnnotationTypes().get(0);
+ }
+ else if (!roomModel.getRoomClasses().isEmpty()) {
+ placeBefore = roomModel.getRoomClasses().get(0);
+ }
+ if (placeBefore!=null) {
+ ICompositeNode node = NodeModelUtils.findActualNodeFor(placeBefore);
+ if (node!=null) {
+ return new ImportRegionResult(node.getOffset(), 0, true);
+ }
+ }
+ }
+ }
+ return importRegion;
+ }
+
+ private boolean typeNeedsImport(EClass type) {
+ return RoomPackage.Literals.ROOM_CLASS.isSuperTypeOf(type);
+ }
+}

Back to the top