Commit 4eca3eff authored by Juergen Haug's avatar Juergen Haug
Browse files

[ui] improved usability of imports + removed deprecated warning

Change-Id: I731b661789c2ff3022922717f71da8ccabe0de0b
parent f3a028ad
......@@ -16,6 +16,7 @@ package org.eclipse.etrice.core.common.ui.editor.folding;
import java.util.List;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.etrice.core.common.base.Import;
......@@ -57,7 +58,8 @@ public class FoldingRegionProvider extends DefaultFoldingRegionProvider {
protected void computeObjectFolding(EObject eObject, IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor,
boolean initiallyFolded) {
if(eObject instanceof Import) {
boolean autoFoldPref = Platform.getPreferencesService().getBoolean("org.eclipse.etrice.ui.common.base", "AUTO_FOLD_IMPORTS" /* RoomPreferenceConstants.AUTO_FOLD_IMPORTS */, false, null);
if(autoFoldPref && eObject instanceof Import) {
// fold imports
EStructuralFeature importsFeature = eObject.eContainmentFeature();
if(importsFeature.isMany()) {
......
......@@ -13,18 +13,18 @@
*******************************************************************************/
package org.eclipse.etrice.core.common.ui.quickfix
import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
import org.eclipse.xtext.ui.editor.quickfix.Fix
import org.eclipse.etrice.core.common.validation.BaseJavaValidator
import org.eclipse.xtext.validation.Issue
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
import org.eclipse.etrice.core.common.base.Import
import org.eclipse.core.resources.ResourcesPlugin
import org.eclipse.core.runtime.Path
import org.eclipse.etrice.core.common.base.Import
import org.eclipse.etrice.core.common.ui.modelpath.ModelPathManager
import org.eclipse.etrice.core.common.validation.BaseJavaValidator
import org.eclipse.ui.PlatformUI
import org.eclipse.ui.ide.IDE
import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
import org.eclipse.xtext.ui.editor.quickfix.Fix
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
import org.eclipse.xtext.util.StringInputStream
import org.eclipse.xtext.validation.Issue
//import org.eclipse.xtext.ui.editor.quickfix.Fix
//import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
......
......@@ -14,10 +14,16 @@
package org.eclipse.etrice.core.common.base.util;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
......@@ -25,8 +31,10 @@ import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.etrice.core.common.base.BaseFactory;
import org.eclipse.etrice.core.common.base.Import;
import org.eclipse.etrice.core.common.scoping.ModelLocatorUriResolver;
import org.eclipse.etrice.core.common.scoping.RelativeFileURIHandler;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.IEObjectDescription;
......@@ -48,18 +56,25 @@ public class ImportHelpers {
@Inject IQualifiedNameConverter nameConverter;
@Inject ModelLocatorUriResolver importUriResolver;
@Inject IGlobalScopeProvider globalScope; // visible/imported scope
@Inject IResourceDescriptions resourceDescriptions; // world scope
@Inject IResourceDescriptions resourceDescriptions; // world/workspace scope
public ModelLocatorUriResolver getUriResolver() {
return importUriResolver;
}
// /**
// * Returns elements from workspace.
// */
// public Iterable<IEObjectDescription> findInWorskpace(QualifiedName fqn) {
// return resourceDescriptions.getExportedObjects(EOBJECT, fqn, false);
// }
/**
* Returns elements from workspace.
*/
public Iterable<IEObjectDescription> findInWorskpace(QualifiedName fqn, boolean ignoreCase) {
return resourceDescriptions.getExportedObjects(EOBJECT, fqn, ignoreCase);
}
/**
* Returns elements from workspace.
*/
public IResourceDescriptions getWorkspaceDescriptions() {
return resourceDescriptions;
}
/**
* Returns current visible/imported scope of given resource.
......@@ -78,6 +93,13 @@ public class ImportHelpers {
return globalScope.getScope(context, reference, Predicates.alwaysTrue());
}
/**
* Returns current visible/imported scope of given resource.
*/
public IGlobalScopeProvider getVisibleScopeProvider() {
return globalScope;
}
/**
* Returns a list of imported target eObjects for an import or absent if import is not computable.
* The list contains either a single exact match (imported namespace && quickFixCandidateMatcher)
......@@ -147,4 +169,63 @@ public class ImportHelpers {
public QualifiedName toFQN(Import imp) {
return toFQN(imp.getImportedNamespace());
}
public List<Import> createModelPathImports(String issueString, Resource resource, EClass type, boolean wildcard) {
final List<Import> result = new ArrayList<>();
IScope scope = getVisibleScope(resource, type);
scope.getAllElements().forEach((eObjDesc) -> {
if(eObjDesc.getName().getLastSegment().equalsIgnoreCase(issueString)) {
// - Bug 549427 - hide element that cannot be resolved (why is it here?)
if(scope.getSingleElement(eObjDesc.getName()) == null) return;
// -
Import imp = BaseFactory.eINSTANCE.createImport();
imp.setImportedNamespace((wildcard) ? eObjDesc.getQualifiedName().skipLast(1) + ".*" : eObjDesc.getQualifiedName().toString());
result.add(imp);
}
});
return result;
}
public List<Import> createURIImports(String issueString, EClass type, URI baseURI) {
final List<Import> result = new ArrayList<>();
getWorkspaceDescriptions().getExportedObjectsByType(type).forEach((eObjDesc) -> {
if(eObjDesc.getName().getLastSegment().equalsIgnoreCase(issueString)) {
Import imp = BaseFactory.eINSTANCE.createImport();
imp.setImportedNamespace(eObjDesc.getQualifiedName().skipLast(1) + ".*");
imp.setImportURI(computeImportURIString(baseURI, eObjDesc.getEObjectURI()));
result.add(imp);
}
});
return result;
}
private String computeImportURIString(URI base, URI toImport) {
URI trimmedBase = base.trimQuery().trimFragment();
URI trimmedImport = toImport.trimQuery().trimFragment();
RelativeFileURIHandler fileHandler = new RelativeFileURIHandler();
fileHandler.setBaseURI(trimmedBase);
URI resolvedRelative= fileHandler.deresolve(trimmedImport);
// same project => relative
if(base.isPlatformResource() && toImport.isPlatformResource() && Objects.equals(base.segment(1), toImport.segment(1))) {
// check if exists
String baseLocation = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(base.trimSegments(1).toPlatformString(false))).getLocation().toFile().getAbsolutePath();
if(resolvedRelative.isRelative() && Files.exists(Paths.get(baseLocation, resolvedRelative.toString()))) {
return resolvedRelative.toString();
} else {
return trimmedImport.toString();
}
}
// both in workspace => platform resource
if(base.isPlatformResource() && toImport.isPlatformResource()) {
return trimmedImport.toString();
} else {
// else file
return resolvedRelative.toString();
}
}
}
......@@ -201,9 +201,10 @@ public class BaseJavaValidator extends org.eclipse.etrice.core.common.validation
}
Resource resource = imp.eResource();
if(!modelPathProvider.get(resource).isEmpty()) {
warning("import statements using uris are deprecated", BasePackage.Literals.IMPORT__IMPORT_URI, DEPRECATED_IMPORT_URI);
}
// too many warnings for now
// if(!modelPathProvider.get(resource).isEmpty()) {
// warning("import statements using uris are deprecated", BasePackage.Literals.IMPORT__IMPORT_URI, DEPRECATED_IMPORT_URI);
// }
String uriString = importUriResolver.resolve(imp);
if (uriString == null) {
......@@ -254,9 +255,13 @@ public class BaseJavaValidator extends org.eclipse.etrice.core.common.validation
error("no modelpath definition present", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, MODELPATH_DESCRIPTION_MISSING);
return;
}
IEObjectDescription eod = importHelpers.getVisibleScope(resource).getSingleElement(fqn);
if(eod == null) {
error("could not find imported namespace " + fqn, BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, IMPORTED_NAMESPACE_MISSING);
IEObjectDescription eObjDesc = importHelpers.getVisibleScope(resource).getSingleElement(fqn);
if(eObjDesc == null) {
if(importHelpers.findInWorskpace(fqn, false).iterator().hasNext()) {
error("could not find namespace on modelpath '" + fqn + "'", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, IMPORTED_NAMESPACE_MISSING);
} else {
error("could not find imported namespace '" + fqn + "'", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, IMPORTED_NAMESPACE_MISSING);
}
}
}
}
......@@ -22,4 +22,6 @@ import org.eclipse.etrice.ui.common.base.preferences.UIBasePreferenceConstants;
public interface RoomPreferenceConstants {
public static final String SAVE_TEXT_ON_FOCUS_LOST = UIBasePreferenceConstants.SAVE_TEXT_ON_FOCUS_LOST;
/** Used by org.eclipse.etrice.core.common.ui.editor.folding.FoldingRegionProvider */
public static final String AUTO_FOLD_IMPORTS = "AUTO_FOLD_IMPORTS";
}
......@@ -15,30 +15,17 @@
package org.eclipse.etrice.core.ui.quickfix
import com.google.inject.Inject
import java.nio.file.Files
import java.nio.file.Paths
import org.eclipse.core.resources.ResourcesPlugin
import org.eclipse.core.runtime.Path
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.EClass
import org.eclipse.etrice.core.common.base.BaseFactory
import org.eclipse.etrice.core.common.scoping.RelativeFileURIHandler
import org.eclipse.etrice.core.common.base.util.ImportHelpers
import org.eclipse.etrice.core.room.RoomModel
import org.eclipse.xtext.resource.IResourceDescriptions
import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
import org.eclipse.xtext.validation.Issue
import static org.eclipse.xtext.EcoreUtil2.getContainerOfType
import static org.eclipse.etrice.core.room.RoomPackage.Literals.*
import org.eclipse.etrice.core.common.scoping.ModelPathGlobalScopeProvider
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.EReference
class RoomQuickFixProviderXtend extends RoomQuickfixProvider {
@Inject ModelPathGlobalScopeProvider modelPathGlobalScopeProvider
@Inject IResourceDescriptions resourceDescriptions
@Inject ImportHelpers importHelpers
// override xtext linking issues
override getResolutionsForLinkingIssue(Issue issue) {
......@@ -60,76 +47,28 @@ class RoomQuickFixProviderXtend extends RoomQuickfixProvider {
val reference = getUnresolvedEReference(issue, target)
if(reference !== null) {
// import without uri by element
importQuickfixElementWithoutURI(issueString, resource, reference, issue, acceptor)
// import by namespace per default
importQuickfixNamespace(issueString, reference.EReferenceType, issue, acceptor)
// import by element
if(reference == ACTOR_CLASS) {
importQuickfixElement(issueString, reference.EReferenceType, issue, acceptor)
}
createLinkingImports(issue, issueString, resource, reference.EReferenceType, false, acceptor);
}
}
protected def void importQuickfixElementWithoutURI(String issueString, Resource resource, EReference reference, Issue issue, IssueResolutionAcceptor acceptor) {
modelPathGlobalScopeProvider.getScope(resource, reference, [name.lastSegment.equalsIgnoreCase(issueString)]).allElements.forEach[ eObjDesc |
acceptor.accept(issue, '''Import 'eObjDesc.qualifiedName' ''', '', null) [elem, ctx |
val model = getContainerOfType(elem, RoomModel)
model.imports += BaseFactory.eINSTANCE.createImport => [
importedNamespace = eObjDesc.qualifiedName.toString
]
protected def void createLinkingImports(Issue issue, String issueString, XtextResource resource, EClass type, boolean wildcard, IssueResolutionAcceptor acceptor) {
// try first import based on model path
val elementImports = importHelpers.createModelPathImports(issueString, resource, type, false)
elementImports.forEach[imp |
acceptor.accept(issue, '''Import 'imp.importedNamespace' ''', '', null) [elem, ctx |
val model = EcoreUtil2.getContainerOfType(elem, RoomModel)
model.imports += imp
]
]
}
protected def void importQuickfixNamespace(String issueString, EClass type, Issue issue, IssueResolutionAcceptor acceptor) {
resourceDescriptions.getExportedObjectsByType(type).filter[name.lastSegment.equalsIgnoreCase(issueString)].forEach [ eObjDesc |
acceptor.accept(issue, '''Import namespace 'eObjDesc.qualifiedName.skipLast(1)' from 'eObjDesc.EObjectURI.lastSegment' ''', '', null) [elem, ctx |
val model = getContainerOfType(elem, RoomModel)
model.imports += BaseFactory.eINSTANCE.createImport => [
importedNamespace = eObjDesc.qualifiedName.skipLast(1) + '.*'
importURI = computeImportURIString(model.eResource.URI, eObjDesc.EObjectURI)
]
]
]
}
protected def void importQuickfixElement(String issueString, EClass type, Issue issue, IssueResolutionAcceptor acceptor) {
resourceDescriptions.getExportedObjectsByType(type).filter[name.lastSegment.equalsIgnoreCase(issueString)].forEach [ eObjDesc |
acceptor.accept(issue, '''Import 'eObjDesc.qualifiedName' from 'eObjDesc.EObjectURI.lastSegment' ''', '', null) [elem, ctx |
val model = getContainerOfType(elem, RoomModel)
model.imports += BaseFactory.eINSTANCE.createImport => [
importedNamespace = eObjDesc.qualifiedName.toString
importURI = computeImportURIString(model.eResource.URI, eObjDesc.EObjectURI)
// fallback: old style imports with uri
if(elementImports.empty) {
importHelpers.createURIImports(issueString, type, resource.URI).forEach[imp |
acceptor.accept(issue, '''Import namespace 'imp.importedNamespace' from 'imp.importURI' ''', '', null) [elem, ctx |
val model = EcoreUtil2.getContainerOfType(elem, RoomModel)
model.imports += imp
]
]
]
}
private def String computeImportURIString(URI base, URI toImport) {
val trimmedBase = base.trimQuery.trimFragment
val trimmedImport = toImport.trimQuery.trimFragment
val fileHandler = new RelativeFileURIHandler => [baseURI = trimmedBase]
val resolvedRelative= fileHandler.deresolve(trimmedImport)
// same project => relative
if(base.platformResource && toImport.platformResource && base.segment(1) == toImport.segment(1)) {
// check if exists
val baseLocation = ResourcesPlugin.workspace.root.getFile(new Path(base.trimSegments(1).toPlatformString(false))).location.toFile.absolutePath
if(resolvedRelative.isRelative && Files.exists(Paths.get(baseLocation, resolvedRelative.toString))) {
return resolvedRelative.toString
} else {
return trimmedImport.toString
}
}
// both in workspace => platform resource
if(base.platformResource && toImport.platformResource) {
trimmedImport.toString
} else {
// else file
resolvedRelative.toString
}
}
}
\ No newline at end of file
......@@ -39,6 +39,7 @@ import org.eclipse.etrice.core.room.ReferenceType;
import org.eclipse.etrice.core.room.StandardOperation;
import org.eclipse.etrice.core.validation.RoomJavaValidator;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.xtext.conversion.impl.QualifiedNameValueConverter;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.editor.model.edit.IModification;
import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
......@@ -49,6 +50,8 @@ import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
import org.eclipse.xtext.ui.editor.quickfix.ReplaceModification;
import org.eclipse.xtext.validation.Issue;
import com.google.inject.Inject;
public class RoomQuickfixProvider extends FSMQuickfixProvider {
/**
......@@ -70,6 +73,8 @@ public class RoomQuickfixProvider extends FSMQuickfixProvider {
kv.setValue(sl);
}
}
@Inject QualifiedNameValueConverter fqnConverter;
@Override
public List<IssueResolution> getResolutions(Issue issue) {
......@@ -92,7 +97,7 @@ public class RoomQuickfixProvider extends FSMQuickfixProvider {
@Fix(RoomJavaValidator.WRONG_MODEL_NAME)
public void renameModel(final Issue issue, IssueResolutionAcceptor acceptor) {
String replacement = issue.getData()[1];
String replacement = fqnConverter.toString(issue.getData()[1]);
acceptor.accept(issue, "Rename model", "Replace model name with its location on the modelpath \nfollowed by its file name",
"correction_change.gif", new ReplaceModification(issue, replacement));
}
......
......@@ -55,6 +55,11 @@ public class ETricePreferencePage
"Auto-save textual model when focus changes",
getFieldEditorParent());
addField(autoSaveText);
BooleanFieldEditor foldImportsText = new BooleanFieldEditor(
RoomPreferenceConstants.AUTO_FOLD_IMPORTS,
"Auto-fold imports",
getFieldEditorParent());
addField(foldImportsText);
addLabel("");
addLabel("Diagram Editors");
......
......@@ -32,6 +32,7 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer {
public void initializeDefaultPreferences() {
IPreferenceStore store = UIBaseActivator.getDefault().getPreferenceStore();
store.setDefault(RoomPreferenceConstants.SAVE_TEXT_ON_FOCUS_LOST, true);
store.setDefault(RoomPreferenceConstants.AUTO_FOLD_IMPORTS, false);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment