From bcc8129381b03619ff5d34af002aab9461c7e90c Mon Sep 17 00:00:00 2001 From: Remi Schnekenburger Date: Tue, 15 Dec 2020 23:01:59 +0100 Subject: Bug 568495 - Create static profile builder extension - update framework with the common version - fix an issue with error resolution on specific attribute (index error) - add the problem id in the error report - add additional information to the report (free from internal API with a simple map) - fix for ecore missing extension was adding pathmap specific path where a simple plugin relative path was expected - add support for quick fixes (binary build missing) - add soft requirement support (warning when extension point is not found) - update junit tests based on current implementation - update use cases --- .../plugin.xml | 4 +- .../toolsmiths/plugin/builder/Activator.java | 22 +- .../builder/StaticProfileExtensionsBuilder.java | 80 --- .../builder/StaticProfileManifestBuilder.java | 68 --- .../plugin/builder/helper/StaticProfileHelper.java | 18 +- .../builder/quickfix/MarkerResolutionUtils.java | 4 +- .../MissingUriAttributeMarkerResolution.java | 4 +- .../NoEcoreGenPackageMarkerResolution.java | 4 +- ...urceMissingFromBinaryBuildMarkerResolution.java | 4 +- .../StaticProfileMarkerResolutionGenerator.java | 18 +- .../checkers/ArchitecturePluginChecker.java | 2 +- .../META-INF/MANIFEST.MF | 5 +- .../common/checkers/BuildPropertiesChecker.java | 16 +- .../common/checkers/IPluginChecker2.java | 19 + .../common/internal/utils/PluginErrorReporter.java | 147 +++++- .../validation/common/utils/MarkersService.java | 11 + .../common/utils/ModelResourceMapper.java | 20 + .../checkers/ElementTypesPluginChecker.java | 2 +- .../checkers/ElementTypesPluginXMLValidator.java | 2 +- .../META-INF/MANIFEST.MF | 4 +- .../RequirementsProfileValidation.usecases | 11 +- .../plugin.xml | 5 +- .../checkers/ProfilePluginCheckerService.java | 6 +- .../ProfilePluginValidationConstants.java | 18 +- .../checkers/ProfileDefinitionChecker.java | 2 +- .../checkers/ProfileExtensionsChecker.java | 100 ---- .../internal/checkers/ProfilePluginChecker.java | 227 +++++---- .../checkers/ProfilePluginXMLValidator.java | 321 ++++++++++++ .../checkers/SelectiveDeleteErrorReporter.java | 160 ------ .../checkers/StaticProfilePluginErrorReporter.java | 539 --------------------- .../handlers/ValidateProfilePluginHandler.java | 35 +- .../profile/tests/ProfilePluginValidationTest.java | 14 +- 32 files changed, 787 insertions(+), 1105 deletions(-) delete mode 100644 plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileExtensionsBuilder.java delete mode 100644 plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileManifestBuilder.java delete mode 100644 plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileExtensionsChecker.java create mode 100644 plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginXMLValidator.java delete mode 100644 plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/SelectiveDeleteErrorReporter.java delete mode 100644 plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/StaticProfilePluginErrorReporter.java diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/plugin.xml b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/plugin.xml index 7642ee9066a..80904cb26bc 100755 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/plugin.xml +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/plugin.xml @@ -79,7 +79,7 @@ point="org.eclipse.ui.ide.markerResolution"> + markerType="org.eclipse.papyrus.toolsmiths.validation.profile.diagnostic"> + markerType="org.eclipse.papyrus.toolsmiths.validation.profile.diagnostic"> mapProfilesResources(IProject project) { + ModelResourceMapper mapper = new ModelResourceMapper<>(project); + return mapper.map(StaticProfileHelper.umlWithGenmodel(), resourceSets(), rootsOfType(Profile.class)); + } + + private ListMultimap mapAllProfilesResources(IProject project) { + ModelResourceMapper mapper = new ModelResourceMapper<>(project); + return mapper.map(StaticProfileHelper.umlWithGenmodel(), resourceSets(), allElementsOfType(Profile.class)); + } + private ListMultimap mapArchitectureResources(IProject project) { ModelResourceMapper mapper = new ModelResourceMapper<>(project); return mapper.map(byExtension(ARCHITECTURE_EXTENSION), diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileExtensionsBuilder.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileExtensionsBuilder.java deleted file mode 100644 index b4df30bd187..00000000000 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileExtensionsBuilder.java +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2020 CEA LIST, EclipseSource and others. - * - * 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 - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Remi Schnekenburger (EclipseSource) - Initial API and implementation - * - *****************************************************************************/ -package org.eclipse.papyrus.toolsmiths.plugin.builder; - -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.papyrus.toolsmiths.plugin.builder.helper.StaticProfileHelper; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfileExtensionsChecker; -import org.eclipse.pde.core.plugin.IPluginExtension; -import org.eclipse.pde.core.plugin.IPluginModelBase; -import org.eclipse.pde.core.plugin.PluginRegistry; -import org.eclipse.pde.internal.core.builders.PDEMarkerFactory; -import org.eclipse.uml2.uml.Profile; - -/** - * Builder that checks extensions for the plugin.xml file when project contains a static profile. - */ -@SuppressWarnings("restriction") -public class StaticProfileExtensionsBuilder extends AbstractPapyrusBuilder { - - @Override - public IProject[] build(IProject builtProject, PapyrusPluginBuilder papyrusBuilder, int kind, Map args, IProgressMonitor monitor) throws CoreException { - - if (papyrusBuilder.isInterrupted() || monitor.isCanceled()) { - return null; - } - // check static profile presence? - Map> profiles = StaticProfileHelper.findStaticProfiles(builtProject, true); - - if (profiles.entrySet().isEmpty()) { - return null; - } - // retrieve information from plugin extensions, warning, this iterates several time on the same parser with different file. Check that clean does not happen between various profiles - for (Entry> entry : profiles.entrySet()) { - ProfileExtensionsChecker profileExtensionsChecker = new ProfileExtensionsChecker(builtProject, entry.getKey(), entry.getValue()); - profileExtensionsChecker.check(monitor); - } - - return null; - - } - - @Override - public void clean(IProgressMonitor monitor, IProject project) throws CoreException { - super.clean(monitor, project); - - final IPluginModelBase pluginModelBase = PluginRegistry.findModel(project); - if (pluginModelBase == null) { - return; - } - - // clean the kind of markers created by the specific plugin error reporter. - pluginModelBase.getUnderlyingResource().deleteMarkers(PDEMarkerFactory.MARKER_ID, true, IResource.DEPTH_INFINITE); - for (IPluginExtension extenstion : pluginModelBase.getExtensions().getExtensions()) { - extenstion.getModel().getUnderlyingResource().deleteMarkers(PDEMarkerFactory.MARKER_ID, true, IResource.DEPTH_INFINITE); - - // clean only once the plugin.xml file - break; - } - } -} diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileManifestBuilder.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileManifestBuilder.java deleted file mode 100644 index 3352822932a..00000000000 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/StaticProfileManifestBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2020 CEA LIST, EclipseSource, Christian W. Damus, and others. - * - * 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 - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Remi Schnekenburger - Initial API and implementation - * Christian W. Damus - bug 569357 - * - *****************************************************************************/ - -package org.eclipse.papyrus.toolsmiths.plugin.builder; - -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.papyrus.toolsmiths.plugin.builder.helper.StaticProfileHelper; -import org.eclipse.papyrus.toolsmiths.validation.common.checkers.BuildPropertiesChecker; -import org.eclipse.papyrus.toolsmiths.validation.common.checkers.ModelDependenciesChecker; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfilePluginChecker; -import org.eclipse.uml2.uml.Profile; - -/** - * Builder that checks manifest for static profiles within a Papyrus plugin. - */ -public class StaticProfileManifestBuilder extends AbstractPapyrusBuilder { - - @Override - public IProject[] build(IProject builtProject, PapyrusPluginBuilder papyrusBuilder, int kind, Map args, IProgressMonitor monitor) throws CoreException { - if (papyrusBuilder.isInterrupted() || monitor.isCanceled()) { - return null; - } - - // check static profile presence? - Map> profiles = StaticProfileHelper.findStaticProfiles(builtProject, false); - - if (profiles.entrySet().isEmpty()) { - return null; - } - - // retrieve information from plugin extensions, warning, this iterates several time on the same parser with different file. Check that clean does not happen between various profiles - for (Entry> entry : profiles.entrySet()) { - Resource resource = entry.getValue().size() > 0 ? entry.getValue().get(0).eResource() : null; - if (resource == null) { - return null; - } - ModelDependenciesChecker profileDependenciesChecker = ProfilePluginChecker.createProfileDependenciesChecker(builtProject, entry.getKey(), resource); - profileDependenciesChecker.check(monitor); - - BuildPropertiesChecker profileBuildChecker = new BuildPropertiesChecker(builtProject, entry.getKey()).withEMFGeneratorModels(); - profileBuildChecker.check(monitor); - } - - return new IProject[] { builtProject }; - } - -} diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/helper/StaticProfileHelper.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/helper/StaticProfileHelper.java index 45625fa68e4..b99ee6b8cc2 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/helper/StaticProfileHelper.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/helper/StaticProfileHelper.java @@ -31,6 +31,7 @@ import org.eclipse.papyrus.infra.core.resource.ModelSet; import org.eclipse.papyrus.infra.core.resource.NotFoundException; import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel; import org.eclipse.papyrus.toolsmiths.validation.common.utils.ModelResourceMapper; +import org.eclipse.papyrus.uml.tools.model.UmlModel; import org.eclipse.papyrus.uml.tools.model.UmlUtils; import org.eclipse.papyrus.uml.tools.utils.PackageUtil; import org.eclipse.uml2.uml.Profile; @@ -62,7 +63,7 @@ public class StaticProfileHelper { return Multimaps.asMap(mapper.map(diWithGenmodel(), modelSets(), modelSet -> getProfiles(modelSet, includeSubProfiles))); } - static Predicate diWithGenmodel() { + public static Predicate diWithGenmodel() { return byExtension(DiModel.DI_FILE_EXTENSION).and(file -> hasGenmodel(file)); } @@ -80,9 +81,9 @@ public class StaticProfileHelper { if (!includeSubProfiles) { return Stream.of(profile); + } else { + return profileWithSubProfiles(profile); } - - return Stream.concat(Stream.of(profile), PackageUtil.getSubProfiles(profile).stream()); } } catch (NotFoundException e) { // Nothing to return @@ -91,4 +92,15 @@ public class StaticProfileHelper { return Stream.empty(); } + static public Stream profileWithSubProfiles(Profile profile) { + return Stream.concat(Stream.of(profile), PackageUtil.getSubProfiles(profile).stream()); + } + + /** + * @return + */ + public static Predicate umlWithGenmodel() { + return byExtension(UmlModel.UML_FILE_EXTENSION).and(file -> hasGenmodel(file)); + } + } diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MarkerResolutionUtils.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MarkerResolutionUtils.java index 5e2f095149f..72704e98902 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MarkerResolutionUtils.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MarkerResolutionUtils.java @@ -28,7 +28,7 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.papyrus.toolsmiths.plugin.builder.helper.StaticProfileHelper; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.StaticProfilePluginErrorReporter; +import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; import org.eclipse.papyrus.uml.tools.utils.StaticProfileUtil; import org.eclipse.ui.IMarkerResolution; import org.eclipse.uml2.uml.Profile; @@ -84,7 +84,7 @@ public final class MarkerResolutionUtils { /** Returns the profile name stored in the marker attribute {@link StaticProfilePluginErrorReporter#STATIC_PROFILE_MARKER_ATTRIBUTE} or null if the attribute does not exist. */ public static String getProfileName(IMarker marker) { - return marker.getAttribute(StaticProfilePluginErrorReporter.STATIC_PROFILE_MARKER_ATTRIBUTE, null); + return marker.getAttribute(ProfilePluginValidationConstants.STATIC_PROFILE_MARKER_ATTRIBUTE, null); } /** diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MissingUriAttributeMarkerResolution.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MissingUriAttributeMarkerResolution.java index afddf316cf5..1ee7db28852 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MissingUriAttributeMarkerResolution.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/MissingUriAttributeMarkerResolution.java @@ -16,7 +16,7 @@ package org.eclipse.papyrus.toolsmiths.plugin.builder.quickfix; import org.eclipse.papyrus.toolsmiths.plugin.builder.Messages; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.StaticProfilePluginErrorReporter; +import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; /** * Resolution for markers created for missing genModel attributes in the extension point. @@ -41,6 +41,6 @@ public class MissingUriAttributeMarkerResolution @Override protected String getAttributeValue() { - return getMarker().getAttribute(StaticProfilePluginErrorReporter.STATIC_PROFILE_STEREOTYPE_URI, ""); //$NON-NLS-1$ + return getMarker().getAttribute(ProfilePluginValidationConstants.STATIC_PROFILE_STEREOTYPE_URI, ""); //$NON-NLS-1$ } } diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/NoEcoreGenPackageMarkerResolution.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/NoEcoreGenPackageMarkerResolution.java index 655ee8e7669..06d88e1cb29 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/NoEcoreGenPackageMarkerResolution.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/NoEcoreGenPackageMarkerResolution.java @@ -18,6 +18,7 @@ package org.eclipse.papyrus.toolsmiths.plugin.builder.quickfix; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.papyrus.infra.emf.utils.ResourceUtils; import org.eclipse.papyrus.toolsmiths.plugin.builder.Activator; @@ -75,7 +76,8 @@ public class NoEcoreGenPackageMarkerResolution extends AbstractPapyrusMarkerReso extension.add(packageElement); IFile genModel = MarkerResolutionUtils.getGenModelFile(marker); if (genModel != null) { - packageElement.setAttribute("genModel", ResourceUtils.mapAndEncodePath(genModel)); //$NON-NLS-1$ + IPath relativePath = genModel.getProjectRelativePath(); + packageElement.setAttribute("genModel", ResourceUtils.getStringURI(relativePath)); //$NON-NLS-1$ } String uri = MarkerResolutionUtils.getStereotypeUri(marker); if (uri != null) { diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/ResourceMissingFromBinaryBuildMarkerResolution.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/ResourceMissingFromBinaryBuildMarkerResolution.java index e62d2ba72b4..0b815aa4450 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/ResourceMissingFromBinaryBuildMarkerResolution.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/ResourceMissingFromBinaryBuildMarkerResolution.java @@ -18,7 +18,7 @@ package org.eclipse.papyrus.toolsmiths.plugin.builder.quickfix; import org.eclipse.core.resources.IMarker; import org.eclipse.papyrus.eclipse.project.editors.file.BuildEditor; import org.eclipse.papyrus.toolsmiths.plugin.builder.Messages; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.StaticProfilePluginErrorReporter; +import org.eclipse.papyrus.toolsmiths.validation.common.checkers.BuildPropertiesChecker; /** * Resolution that adds the missing file to the binary build. @@ -39,7 +39,7 @@ public class ResourceMissingFromBinaryBuildMarkerResolution extends AbstractPapy public void run(IMarker marker) { BuildEditor buildEditor = new BuildEditor(marker.getResource().getProject()); buildEditor.init(); - buildEditor.addToBuild(marker.getAttribute(StaticProfilePluginErrorReporter.STATIC_PROFILE_BINARY_BUILD_PATH, "")); //$NON-NLS-1$ + buildEditor.addToBuild(marker.getAttribute(BuildPropertiesChecker.BINARY_BUILD_PATH, "")); //$NON-NLS-1$ buildEditor.save(); } diff --git a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/StaticProfileMarkerResolutionGenerator.java b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/StaticProfileMarkerResolutionGenerator.java index 3c2980e4afe..6271fc9df62 100644 --- a/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/StaticProfileMarkerResolutionGenerator.java +++ b/plugins/toolsmiths/builder/org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/quickfix/StaticProfileMarkerResolutionGenerator.java @@ -16,7 +16,7 @@ package org.eclipse.papyrus.toolsmiths.plugin.builder.quickfix; import org.eclipse.core.resources.IMarker; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.StaticProfilePluginErrorReporter; +import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; import org.eclipse.pde.internal.core.builders.PDEMarkerFactory; import org.eclipse.ui.IMarkerResolution; import org.eclipse.ui.IMarkerResolutionGenerator; @@ -33,21 +33,21 @@ public class StaticProfileMarkerResolutionGenerator implements IMarkerResolution public IMarkerResolution[] getResolutions(IMarker marker) { int problemId = marker.getAttribute(PDEMarkerFactory.PROBLEM_ID, PDEMarkerFactory.NO_RESOLUTION); switch (problemId) { - case StaticProfilePluginErrorReporter.NO_GENMODEL_MARKER_ID: + case ProfilePluginValidationConstants.NO_GENMODEL_MARKER_ID: return new IMarkerResolution[] { new MissingGenModelAttributeMarkerResolution() }; - case StaticProfilePluginErrorReporter.NO_URI_MARKER_ID: + case ProfilePluginValidationConstants.NO_URI_MARKER_ID: return new IMarkerResolution[] { new MissingUriAttributeMarkerResolution() }; - case StaticProfilePluginErrorReporter.NO_ECORE_GEN_PACKAGE_MARKER_ID: + case ProfilePluginValidationConstants.NO_ECORE_GEN_PACKAGE_MARKER_ID: return new IMarkerResolution[] { new NoEcoreGenPackageMarkerResolution() }; - case StaticProfilePluginErrorReporter.NO_UML2_GEN_PACKAGE_MARKER_ID: + case ProfilePluginValidationConstants.NO_UML2_GEN_PACKAGE_MARKER_ID: return new IMarkerResolution[] { new NoUMLGenPackageMarkerResolution() }; - case StaticProfilePluginErrorReporter.NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID: + case ProfilePluginValidationConstants.NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID: return new IMarkerResolution[] { new NoLocationUMLGenPackageMarkerResolution() }; - case StaticProfilePluginErrorReporter.PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID: + case ProfilePluginValidationConstants.PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID: return new IMarkerResolution[] { new PapyrusProfileExtensionMissingNameMarkerResolution() }; - case StaticProfilePluginErrorReporter.NO_PAPYRUS_PROFILE_MARKER_ID: + case ProfilePluginValidationConstants.NO_PAPYRUS_PROFILE_MARKER_ID: return new IMarkerResolution[] { new NoPapyrusProfileExtensionMarkerResolution() }; - case StaticProfilePluginErrorReporter.MISSING_FROM_BINARY_BUILD_MARKER_ID: + case ProfilePluginValidationConstants.MISSING_FROM_BINARY_BUILD_MARKER_ID: return new IMarkerResolution[] { new ResourceMissingFromBinaryBuildMarkerResolution() }; default: return NO_RESOLUTIONS; diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.architecture/src/org/eclipse/papyrus/toolsmiths/validation/architecture/internal/checkers/ArchitecturePluginChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.architecture/src/org/eclipse/papyrus/toolsmiths/validation/architecture/internal/checkers/ArchitecturePluginChecker.java index e2f6ef483cc..2a059ee2146 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.architecture/src/org/eclipse/papyrus/toolsmiths/validation/architecture/internal/checkers/ArchitecturePluginChecker.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.architecture/src/org/eclipse/papyrus/toolsmiths/validation/architecture/internal/checkers/ArchitecturePluginChecker.java @@ -192,7 +192,7 @@ public class ArchitecturePluginChecker { ArchitecturePluginXMLValidator validator = new ArchitecturePluginXMLValidator(modelFile); return new PluginErrorReporter<>(pluginXML, modelFile, model, ARCHITECTURE_PLUGIN_VALIDATION_MARKER_TYPE, domain -> domain.getId()) - .requireExtensionPoint(ARCHITECTURE_EXTENSION_POINT_IDENTIFIER, validator::matchExtension, null); + .requireExtensionPoint(ARCHITECTURE_EXTENSION_POINT_IDENTIFIER, validator::matchExtension, null, null); } /** diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/META-INF/MANIFEST.MF b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/META-INF/MANIFEST.MF index 2c4d6ab21a0..4169f780bc1 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/META-INF/MANIFEST.MF +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/META-INF/MANIFEST.MF @@ -10,10 +10,11 @@ Require-Bundle: org.eclipse.emf.transaction;bundle-version="[1.9.0,2.0.0)", org.eclipse.papyrus.infra.architecture;bundle-version="[3.0.0,4.0.0)", org.eclipse.papyrus.infra.core.architecture;bundle-version="[3.0.0,4.0.0)", org.eclipse.papyrus.infra.core;bundle-version="[4.0.0,5.0.0)", - org.eclipse.papyrus.infra.tools;bundle-version="[4.0.0,5.0.0)" + org.eclipse.papyrus.infra.tools;bundle-version="[4.0.0,5.0.0)", + org.eclipse.papyrus.emf;bundle-version="[2.0.0,3.0.0)" Export-Package: org.eclipse.papyrus.toolsmiths.validation.common, org.eclipse.papyrus.toolsmiths.validation.common.checkers, - org.eclipse.papyrus.toolsmiths.validation.common.internal.utils;x-friends:="org.eclipse.papyrus.toolsmiths.validation.elementtypes,org.eclipse.papyrus.toolsmiths.validation.architecture", + org.eclipse.papyrus.toolsmiths.validation.common.internal.utils;x-friends:="org.eclipse.papyrus.toolsmiths.validation.elementtypes,org.eclipse.papyrus.toolsmiths.validation.architecture,org.eclipse.papyrus.toolsmiths.validation.profile", org.eclipse.papyrus.toolsmiths.validation.common.utils Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/BuildPropertiesChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/BuildPropertiesChecker.java index 37ac76f652e..f301882125b 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/BuildPropertiesChecker.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/BuildPropertiesChecker.java @@ -75,6 +75,8 @@ public class BuildPropertiesChecker extends AbstractPluginChecker { private static final String GENMODEL_EXTENSION = "genmodel"; //$NON-NLS-1$ private static final String ECORE_EXTENSION = "ecore"; //$NON-NLS-1$ + public static final int MISSING_FROM_BINARY_BUILD_MARKER_ID = 0xff1009; + public static final String BINARY_BUILD_PATH = "binaryBuildPath"; //$NON-NLS-1$ private final Resource modelResource; @@ -226,7 +228,7 @@ public class BuildPropertiesChecker extends AbstractPluginChecker { // Create marker for every required resource that wasn't matched List errors = new ArrayList<>(requiredResources.size()); for (IResource next : requiredResources) { - errors.add(new BuildError(getMarkerType(), NLS.bind(Messages.BuildPropertiesChecker_3, next.getProjectRelativePath()), Diagnostic.ERROR, IBuildEntry.BIN_INCLUDES)); + errors.add(new BuildError(getMarkerType(), NLS.bind(Messages.BuildPropertiesChecker_3, next.getProjectRelativePath()), Diagnostic.ERROR, IBuildEntry.BIN_INCLUDES, next.getProjectRelativePath().toString())); } reportErrors(diagnostics, errors); } @@ -365,7 +367,7 @@ public class BuildPropertiesChecker extends AbstractPluginChecker { BuildModel textBuildModel = prepareTextBuildModel(buildPropertiesFile); errors.stream().forEach(error -> { - reportBuildError(diagnostics, buildPropertiesFile, textBuildModel, error.type, error.message, error.severity, error.entry); + reportBuildError(diagnostics, buildPropertiesFile, textBuildModel, error.type, error.message, error.severity, error.entry, error.missingValue); }); } @@ -385,13 +387,15 @@ public class BuildPropertiesChecker extends AbstractPluginChecker { * @param header * the header entry of the build file on which marker is created. */ - private void reportBuildError(DiagnosticChain diagnostics, IFile buildFile, BuildModel textBuildModel, String type, String message, int severity, String entry) { + private void reportBuildError(DiagnosticChain diagnostics, IFile buildFile, BuildModel textBuildModel, String type, String message, int severity, String entry, String missingValue) { Diagnostic diagnostic; if (textBuildModel != null) { diagnostic = createDiagnostic(buildFile, severity, 0, message, IPluginChecker2.markerType(type), - IPluginChecker2.lineNumber(getLineNumber(textBuildModel.getBuild().getEntry(entry)))); + IPluginChecker2.lineNumber(getLineNumber(textBuildModel.getBuild().getEntry(entry))), + IPluginChecker2.problem(MISSING_FROM_BINARY_BUILD_MARKER_ID), + IPluginChecker2.missingBinInclude(missingValue)); } else { diagnostic = createDiagnostic(buildFile, severity, 0, message, IPluginChecker2.markerType(type)); @@ -484,12 +488,14 @@ public class BuildPropertiesChecker extends AbstractPluginChecker { public final int severity; public final String message; public final String type; + public final String missingValue; - public BuildError(String type, String message, int severity, String entry) { + public BuildError(String type, String message, int severity, String entry, String missingValue) { this.type = type; this.message = message; this.severity = severity; this.entry = entry; + this.missingValue = missingValue; } } } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/IPluginChecker2.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/IPluginChecker2.java index 57e078fd9e9..e9aaa0ab399 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/IPluginChecker2.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/checkers/IPluginChecker2.java @@ -35,6 +35,7 @@ import org.eclipse.emf.common.util.DiagnosticChain; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.emf.validation.DependencyValidationUtils; import org.eclipse.papyrus.infra.emf.utils.ResourceUtils; import org.eclipse.papyrus.toolsmiths.validation.common.Activator; @@ -148,6 +149,22 @@ public interface IPluginChecker2 { return new MarkerAttribute(IMarker.LINE_NUMBER, line); } + static MarkerAttribute missingDependency(String missingDependency) { + return new MarkerAttribute(DependencyValidationUtils.MISSING_DEPENDENCIES, missingDependency); + } + + static MarkerAttribute missingBinInclude(String missingEntry) { + return new MarkerAttribute(BuildPropertiesChecker.BINARY_BUILD_PATH, missingEntry); + } + + /** + * Create a token to put in the {@linkplain Diagnostic#getData() data list} of a {@link Diagnostic} to indicate the problem id to + * set in the resource marker for further resolutions. + */ + static MarkerAttribute problem(int problemID) { + return new MarkerAttribute("problemId", problemID); + } + /** * Create a token to put in the {@linkplain Diagnostic#getData() data list} of a {@link Diagnostic} to indicate the start offset to * set in the resource marker. @@ -675,4 +692,6 @@ public interface IPluginChecker2 { } + + } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/internal/utils/PluginErrorReporter.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/internal/utils/PluginErrorReporter.java index a5c1a5250f1..5798a879766 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/internal/utils/PluginErrorReporter.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/internal/utils/PluginErrorReporter.java @@ -46,6 +46,7 @@ import org.eclipse.pde.internal.core.builders.IncrementalErrorReporter.VirtualMa import org.eclipse.pde.internal.core.builders.ManifestErrorReporter; import org.eclipse.pde.internal.core.builders.PDEMarkerFactory; import org.eclipse.pde.internal.core.builders.XMLErrorReporter; +import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -70,7 +71,9 @@ public class PluginErrorReporter extends ManifestErrorReporte private final Map> requiredExtensionPoints = new HashMap<>(); private final Multimap> extensionCheckers = HashMultimap.create(); + private final Map> extensionFixProviders = new HashMap<>(); private final Set architectureImpliedExtensionPoints = new HashSet<>(); + private final Set softRequiredExtensionPoints = new HashSet<>(); private final Set foundExtensionPoints = new HashSet<>(); private final Map localURIMappings = new HashMap<>(); @@ -82,6 +85,8 @@ public class PluginErrorReporter extends ManifestErrorReporte private String sourceID; + private Function nameFunction; + /** * Constructor. * @@ -118,6 +123,7 @@ public class PluginErrorReporter extends ManifestErrorReporte this.modelFile = modelFile; this.model = model; this.markerType = markerType; + this.nameFunction = nameFunction; this.problems = new ProblemReportImpl(); sourceID = sourceID(modelFile, model, nameFunction); } @@ -142,11 +148,26 @@ public class PluginErrorReporter extends ManifestErrorReporte * * @return myself, for convenience of call chaining */ - public PluginErrorReporter requireExtensionPoint(String point, ExtensionMatcher matcher, ExtensionChecker checker) { + public PluginErrorReporter requireExtensionPoint(String point, ExtensionMatcher matcher, ExtensionChecker checker, ExtensionFixProvider fixProvider) { requiredExtensionPoints.put(point, matcher); if (checker != null) { extensionCheckers.put(point, checker); } + if (fixProvider != null) { + extensionFixProviders.put(point, fixProvider); + } + return this; + } + + public PluginErrorReporter softRequireExtensionPoint(String point, ExtensionMatcher matcher, ExtensionChecker checker, ExtensionFixProvider fixProvider) { + requiredExtensionPoints.put(point, matcher); + softRequiredExtensionPoints.add(point); + if (checker != null) { + extensionCheckers.put(point, checker); + } + if (fixProvider != null) { + extensionFixProviders.put(point, fixProvider); + } return this; } @@ -274,9 +295,13 @@ public class PluginErrorReporter extends ManifestErrorReporte // Only report this as a warning because perhaps the architecture model just isn't available in the workspace or PDE Target severity = CompilerFlags.WARNING; } + if (softRequiredExtensionPoints.contains(point)) { + severity = CompilerFlags.WARNING; + } - reportProblem(NLS.bind(Messages.PluginErrorReporter_0, point, getModelFile().getProjectRelativePath()), - 1, severity, "missing_extensions"); //$NON-NLS-1$ + VirtualMarker marker = reportProblem(NLS.bind("Missing extension on point ''{0}'' for ''{2}'' [{1}].", new Object[] { point, getModelFile().getProjectRelativePath(), nameFunction.apply(model) }), + 1, severity, extensionFixProviders.get(point) != null ? extensionFixProviders.get(point).problemId(point, model) : 0, null, null, "missing_extensions"); //$NON-NLS-1$ + marker.setAttribute("staticProfile", nameFunction.apply(model)); } protected void validateElement(Element element) { @@ -321,6 +346,60 @@ public class PluginErrorReporter extends ManifestErrorReporte return marker; } + /** + * Overrides super version with a new version of the {@link #generateLocationPath(Node, String)} method that was mismatching the nodes + *

+ * Text nodes were also added in the index, and not only elements as expected by the missing attribute marker resolution) + *

+ * + * @see org.eclipse.pde.internal.core.builders.XMLErrorReporter#report(java.lang.String, int, int, int, org.w3c.dom.Element, java.lang.String, java.lang.String) + */ + @Override + public VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, + String category) { + VirtualMarker marker = report(message, line, severity, fixId, category); + if (marker == null) { + return null; + } + marker.setAttribute(PDEMarkerFactory.MPK_LOCATION_PATH, generateLocationPath(element, attrName)); + return marker; + } + + private String generateLocationPath(Node node, String attrName) { + if (node == null) { + return ""; // //$NON-NLS-1$ + } + + int childIndex = 0; + for (Node previousSibling = node.getPreviousSibling(); previousSibling != null; previousSibling = previousSibling.getPreviousSibling()) { + if ((previousSibling instanceof Element)) { + // filter text + childIndex += 1; + } + } + + StringBuilder sb = new StringBuilder(); + Node parent = node.getParentNode(); + if (parent != null && !(parent instanceof Document)) { + sb.append(generateLocationPath(parent, null)); + sb.append(F_CHILD_SEP); + } + composeNodeString(node, childIndex, attrName, sb); + return sb.toString(); + } + + private String composeNodeString(Node node, int index, String attrName, StringBuilder sb) { + sb.append('('); + sb.append(index); + sb.append(')'); + sb.append(node.getNodeName()); + if (attrName != null) { + sb.append(F_ATT_PREFIX); + sb.append(attrName); + } + return sb.toString(); + } + protected VirtualMarker reportProblem(String message, int line, int severity, String category) { VirtualMarker marker = report(message, line, severity, category); addMarkerID(marker); @@ -334,6 +413,8 @@ public class PluginErrorReporter extends ManifestErrorReporte addMarkerAttribute(marker, DiagnosticErrorReporter.SOURCE_ID, sourceID); } + + protected String decodePath(String path) { if (path == null) { return null; @@ -484,8 +565,10 @@ public class PluginErrorReporter extends ManifestErrorReporte * the ID of a fix for the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - void reportProblem(int severity, Element element, String attrName, String message, int fixId, String category); + void reportProblem(int severity, Element element, String attrName, String message, int fixId, String category, Map data); /** * Report a problem in some attribute of an {@code element} of the plugin.xml. @@ -500,8 +583,10 @@ public class PluginErrorReporter extends ManifestErrorReporte * a description of the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - void reportProblem(int severity, Element element, String attrName, String message, String category); + void reportProblem(int severity, Element element, String attrName, String message, String category, Map data); /** * Report a fixable problem in some {@code element} of the plugin.xml. @@ -516,9 +601,11 @@ public class PluginErrorReporter extends ManifestErrorReporte * the ID of a fix for the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - default void reportProblem(int severity, Element element, String message, int fixId, String category) { - reportProblem(severity, element, null, message, fixId, category); + default void reportProblem(int severity, Element element, String message, int fixId, String category, Map data) { + reportProblem(severity, element, null, message, fixId, category, data); } /** @@ -532,9 +619,11 @@ public class PluginErrorReporter extends ManifestErrorReporte * a description of the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - default void reportProblem(int severity, Element element, String message, String category) { - reportProblem(severity, element, null, message, category); + default void reportProblem(int severity, Element element, String message, String category, Map data) { + reportProblem(severity, element, null, message, category, data); } /** @@ -548,8 +637,10 @@ public class PluginErrorReporter extends ManifestErrorReporte * the ID of a fix for the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - void reportProblem(int severity, String message, int fixId, String category); + void reportProblem(int severity, String message, int fixId, String category, Map data); /** * Report a problem on the plugin.xml as a whole. @@ -560,21 +651,25 @@ public class PluginErrorReporter extends ManifestErrorReporte * a description of the problem * @param category * the problem category + * @param data + * additional data to pass with the problem */ - void reportProblem(int severity, String message, String category); + void reportProblem(int severity, String message, String category, Map data); } private class ProblemReportImpl implements ProblemReport { @Override - public void reportProblem(int severity, Element element, String attrName, String message, int fixId, String category) { - PluginErrorReporter.this.reportProblem(message, getLine(element, attrName), toCompilerSeverity(severity), fixId, element, attrName, category); + public void reportProblem(int severity, Element element, String attrName, String message, int fixId, String category, Map data) { + VirtualMarker problem = PluginErrorReporter.this.reportProblem(message, getLine(element, attrName), toCompilerSeverity(severity), fixId, element, attrName, category); + applyData(problem, data); } @Override - public void reportProblem(int severity, Element element, String attrName, String message, String category) { - PluginErrorReporter.this.reportProblem(message, getLine(element, attrName), toCompilerSeverity(severity), category); + public void reportProblem(int severity, Element element, String attrName, String message, String category, Map data) { + VirtualMarker problem = PluginErrorReporter.this.reportProblem(message, getLine(element, attrName), toCompilerSeverity(severity), category); + applyData(problem, data); } private int getLine(Element element, String attrName) { @@ -582,13 +677,23 @@ public class PluginErrorReporter extends ManifestErrorReporte } @Override - public void reportProblem(int severity, String message, int fixId, String category) { - PluginErrorReporter.this.report(message, 1, toCompilerSeverity(severity), fixId, category); + public void reportProblem(int severity, String message, int fixId, String category, Map data) { + VirtualMarker problem = PluginErrorReporter.this.report(message, 1, toCompilerSeverity(severity), fixId, category); + applyData(problem, data); } @Override - public void reportProblem(int severity, String message, String category) { - PluginErrorReporter.this.report(message, 1, toCompilerSeverity(severity), category); + public void reportProblem(int severity, String message, String category, Map data) { + VirtualMarker problem = PluginErrorReporter.this.report(message, 1, toCompilerSeverity(severity), category); + applyData(problem, data); + } + + void applyData(VirtualMarker problem, Map data) { + if (data != null) { + data.forEach((k, v) -> { + problem.setAttribute(k, v); + }); + } } private int toCompilerSeverity(int diagnosticSeverity) { @@ -607,4 +712,8 @@ public class PluginErrorReporter extends ManifestErrorReporte } + public interface ExtensionFixProvider { + int problemId(String point, T model); + } + } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/MarkersService.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/MarkersService.java index f9b1ff350ef..826b9bed861 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/MarkersService.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/MarkersService.java @@ -25,6 +25,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EValidator; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.emf.validation.DependencyValidationUtils; import org.eclipse.papyrus.toolsmiths.validation.common.Activator; import org.eclipse.papyrus.toolsmiths.validation.common.checkers.IPluginChecker2; import org.eclipse.papyrus.toolsmiths.validation.common.internal.utils.MarkersManagementUtils; @@ -88,6 +89,7 @@ public class MarkersService { String target = null; StringBuilder related = null; + String missingDependency = null; for (Object next : diagnostic.getData()) { if (next instanceof EObject) { @@ -108,6 +110,11 @@ public class MarkersService { related.append(URI.encodeFragment(uri, false)); } break; + } else if (next instanceof IPluginChecker2.MarkerAttribute) { + IPluginChecker2.MarkerAttribute attr = (IPluginChecker2.MarkerAttribute) next; + if (DependencyValidationUtils.MISSING_DEPENDENCIES.equals(attr.getName())) { + missingDependency = (String) attr.getValue(); + } } } @@ -121,6 +128,10 @@ public class MarkersService { if (related != null) { result.setAttribute(EValidator.RELATED_URIS_ATTRIBUTE, related.toString()); } + + if (missingDependency != null) { + result.setAttribute(DependencyValidationUtils.MISSING_DEPENDENCIES, missingDependency); + } } catch (CoreException e) { Activator.log.error("Failed to set attributes of problem marker.", e); //$NON-NLS-1$ } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/ModelResourceMapper.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/ModelResourceMapper.java index 1c9f26e4668..07ee31bc672 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/ModelResourceMapper.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.common/src/org/eclipse/papyrus/toolsmiths/validation/common/utils/ModelResourceMapper.java @@ -266,6 +266,11 @@ public class ModelResourceMapper { return resourceSet -> Iterators2.stream(Iterators2.filter(roots(resourceSet), type)); } + public static Function> allElementsOfType(Class type) { + return resourceSet -> Iterators2.stream(Iterators2.filter(allElements(resourceSet), type)); + } + + @SuppressWarnings("serial") private static TreeIterator roots(ResourceSet resourceSet) { return new AbstractTreeIterator<>(resourceSet.getResources(), false) { @@ -280,4 +285,19 @@ public class ModelResourceMapper { }; } + @SuppressWarnings("serial") + private static TreeIterator allElements(ResourceSet resourceSet) { + return new AbstractTreeIterator<>(resourceSet.getResources(), false) { + @Override + protected Iterator getChildren(Object object) { + return object instanceof Resource + ? ((Resource) object).getAllContents() + : object instanceof Collection + ? ((Collection) object).iterator() + : Collections.emptyIterator(); + } + }; + } + + } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginChecker.java index 4adb6c9f838..a2051131ede 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginChecker.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginChecker.java @@ -188,7 +188,7 @@ public class ElementTypesPluginChecker { ElementTypesPluginXMLValidator validator = new ElementTypesPluginXMLValidator(modelFile); return new PluginErrorReporter<>(pluginXML, modelFile, model, ELEMENTTYPES_PLUGIN_VALIDATION_MARKER_TYPE, set -> set.getIdentifier()) - .requireExtensionPoint(ELEMENTTYPES_EXTENSION_POINT_IDENTIFIER, validator::matchExtension, validator::checkExtension) + .requireExtensionPoint(ELEMENTTYPES_EXTENSION_POINT_IDENTIFIER, validator::matchExtension, validator::checkExtension, null) .impliedByArchitectureContexts(ELEMENTTYPES_EXTENSION_POINT_IDENTIFIER); } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginXMLValidator.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginXMLValidator.java index 6e0344fdd37..aabe9b4e13e 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginXMLValidator.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.elementtypes/src/org/eclipse/papyrus/toolsmiths/validation/elementtypes/internal/checkers/ElementTypesPluginXMLValidator.java @@ -80,7 +80,7 @@ final class ElementTypesPluginXMLValidator { case ELEMENT_TYPE_SET: String clientContextID = element.getAttribute(CLIENT_CONTEXT_ID); if (clientContextID == null || clientContextID.isBlank()) { - problems.reportProblem(Diagnostic.ERROR, element, Messages.ElementTypesPluginXMLValidator_0, CATEGORY); + problems.reportProblem(Diagnostic.ERROR, element, Messages.ElementTypesPluginXMLValidator_0, CATEGORY, null); } break; default: diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/META-INF/MANIFEST.MF b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/META-INF/MANIFEST.MF index 0ac32ce6431..8541cdc054f 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/META-INF/MANIFEST.MF +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/META-INF/MANIFEST.MF @@ -14,7 +14,9 @@ Require-Bundle: org.eclipse.core.expressions;bundle-version="[3.6.0,4.0.0)", org.eclipse.core.filebuffers;bundle-version="[3.6.1000,4.0.0)", org.eclipse.papyrus.uml.tools.utils;bundle-version="[4.0.0,5.0.0)", org.eclipse.emf.codegen.ecore;bundle-version="[2.22.0,3.0.0)", - org.eclipse.jdt.core;bundle-version="[3.24.0,4.0.0)" + org.eclipse.jdt.core;bundle-version="[3.24.0,4.0.0)", + org.eclipse.papyrus.infra.emf;bundle-version="[4.0.0,5.0.0)", + org.eclipse.papyrus.emf;bundle-version="[2.0.0,3.0.0)" Export-Package: org.eclipse.papyrus.toolsmiths.validation.profile, org.eclipse.papyrus.toolsmiths.validation.profile.checkers, org.eclipse.papyrus.toolsmiths.validation.profile.constants, diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/RequirementsProfileValidation.usecases b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/RequirementsProfileValidation.usecases index 5a5d012f6ab..21c9799b9c6 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/RequirementsProfileValidation.usecases +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/RequirementsProfileValidation.usecases @@ -14,14 +14,17 @@ Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/ec Requirement: ReqTechnical_Extensions_Checker_ProfileValidation_001: A checker for the extensions must be implemented Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileExtensionsChecker.java -Requirement: ReqTechnical_Definition_Profile_Checker_ProfileValidation_002: A checker for the definition profile must be implemented -Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDefinitionChecker.java +# General Technical Requirements +Requirement: ReqTechnical_Extensions_Checker_ProfileValidation_002: An automatic checker for the profile plugins shall be provided +Code instruction: - org.eclipse.papyrus.toolsmiths.plugin.builder/src/org/eclipse/papyrus/toolsmiths/plugin/builder/Activator.java Requirement: ReqTechnical_Build_Checker_ProfileValidation_003: A checker for the build must be implemented -Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileBuildChecker.java +Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java +METHOD?: org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfilePluginChecker.createBuildPropertiesChecker(IProject, IFile, Resource) Requirement: ReqTechnical_Dependencies_Checker_ProfileValidation_004: A checker for the dependencies must be implemented -Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDependenciesChecker.java +Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java +METHOD?: org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfilePluginChecker.modelDependenciesCheckerFactory() Requirement: ReqTechnical_Profile_Plugin_Checker_ProfileValidation_005: A method to call the profile plug-in validation must be available Code instruction: - org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/checkers/ProfilePluginCheckerService.java diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/plugin.xml b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/plugin.xml index 29300bcc47a..cc00cad642c 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/plugin.xml +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/plugin.xml @@ -63,11 +63,14 @@
+ + diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/checkers/ProfilePluginCheckerService.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/checkers/ProfilePluginCheckerService.java index 8137eef7d01..355d8810222 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/checkers/ProfilePluginCheckerService.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/checkers/ProfilePluginCheckerService.java @@ -16,6 +16,8 @@ package org.eclipse.papyrus.toolsmiths.validation.profile.checkers; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfilePluginChecker; /** @@ -29,8 +31,8 @@ public class ProfilePluginCheckerService { * @param project * The current project to check. */ - public static void checkProfilePlugin(final IProject project) { - ProfilePluginChecker.checkProfilePlugin(project); + public static void checkProfilePlugin(final IProject project, IProgressMonitor monitor) { + ProfilePluginChecker.checkProfilePlugin(project, monitor == null ? new NullProgressMonitor() : monitor); } } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/constants/ProfilePluginValidationConstants.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/constants/ProfilePluginValidationConstants.java index 71360bf45d9..107640f918d 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/constants/ProfilePluginValidationConstants.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/constants/ProfilePluginValidationConstants.java @@ -23,7 +23,7 @@ public class ProfilePluginValidationConstants { /** * The type for the validation of profile plugin. */ - public static final String PROFILE_PLUGIN_VALIDATION_TYPE = "org.eclipse.papyrus.toolsmiths.validation.profile.diagnostic"; //$NON-NLS-1$ + public static final String PROFILE_PLUGIN_VALIDATION_MARKER_TYPE = "org.eclipse.papyrus.toolsmiths.validation.profile.diagnostic"; //$NON-NLS-1$ /** * The UMLProfile extension point identifier. @@ -44,4 +44,20 @@ public class ProfilePluginValidationConstants { * The EMF Ecore URI mapping extension point identifier. */ public static final String ECORE_URI_MAPPING_EXTENSION_POINT = "org.eclipse.emf.ecore.uri_mapping"; //$NON-NLS-1$ + + /** additional marker attributes */ + public static final String STATIC_PROFILE_MARKER_ATTRIBUTE = "staticProfile"; //$NON-NLS-1$ + public static final String STATIC_PROFILE_STEREOTYPE_URI = "staticProfileStereotypeUri"; //$NON-NLS-1$ + + /** Problem IDs for the markers generated by the profile error reporters. */ + public static final int NO_GENMODEL_MARKER_ID = 0xff1001; + public static final int PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID = 0xff1002; + public static final int MISSING_UML_EXTENSION_MARKER_ID = 0xff1003; + public static final int NO_URI_MARKER_ID = 0xff1004; + public static final int NO_ECORE_GEN_PACKAGE_MARKER_ID = 0xff1005; + public static final int NO_UML2_GEN_PACKAGE_MARKER_ID = 0xff1006; + public static final int NO_PAPYRUS_PROFILE_MARKER_ID = 0xff1007; + public static final int NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID = 0xff1008; + public static final int MISSING_FROM_BINARY_BUILD_MARKER_ID = 0xff1009; + } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDefinitionChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDefinitionChecker.java index ee5c6a29265..07dae379e02 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDefinitionChecker.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileDefinitionChecker.java @@ -92,7 +92,7 @@ public class ProfileDefinitionChecker implements IPluginChecker { for (final Profile profile : profiles) { MarkersService.createMarker( profileFile, - ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_TYPE, + ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_MARKER_TYPE, "The profile '" + profile.getName() + "' contain a definition but should not", //$NON-NLS-1$ //$NON-NLS-2$ IMarker.SEVERITY_ERROR); } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileExtensionsChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileExtensionsChecker.java deleted file mode 100644 index e4006979ab9..00000000000 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfileExtensionsChecker.java +++ /dev/null @@ -1,100 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2019, 2020 CEA LIST, EclipseSource and others. - * - * 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 - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Initial API and implementation - * Remi Schnekenburger (EclipseSource) - Bug 568495 - * - *****************************************************************************/ -package org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers; - -import java.util.Collection; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.osgi.util.NLS; -import org.eclipse.papyrus.toolsmiths.validation.common.checkers.IPluginChecker; -import org.eclipse.papyrus.toolsmiths.validation.common.utils.MarkersService; -import org.eclipse.papyrus.toolsmiths.validation.common.utils.ProjectManagementService; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.messages.Messages; -import org.eclipse.pde.internal.core.builders.DefaultSAXParser; -import org.eclipse.pde.internal.core.builders.PDEMarkerFactory; -import org.eclipse.uml2.uml.Profile; - -/** - * This class allows to check the extensions of the 'plugin.xml' needed for the profiles. - */ -@SuppressWarnings("restriction") -public class ProfileExtensionsChecker implements IPluginChecker { - - /** - * The current project resource. - */ - private final IProject project; - - /** - * The file of the UML profile. - */ - private final IFile profileFile; - - /** - * The existing profiles in the UML file. - */ - private final Collection existingProfiles; - - /** - * Constructor. - * - * @param project - * The current project to check. - * @param profileFile - * The file of the UML profile. - * @param existingProfiles - * The existing profiles in the UML file. - */ - public ProfileExtensionsChecker(final IProject project, final IFile profileFile, final Collection existingProfiles) { - this.project = project; - this.profileFile = profileFile; - this.existingProfiles = existingProfiles; - } - - /** - * This allows to check the extensions of the profile. - * {@inheritDoc} - * - * @see org.eclipse.papyrus.toolsmiths.validation.common.checkers.IPluginChecker#check(org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - public void check(final IProgressMonitor monitor) { - - if (monitor != null && monitor.isCanceled()) { - return; - } - - final IFile pluginXML = ProjectManagementService.getPluginXMLFile(project); - - if (pluginXML == null) { - MarkersService.createMarker(profileFile, PDEMarkerFactory.MARKER_ID, Messages.ProfileExtensionsChecker_noExternsionsDeclared, IMarker.SEVERITY_ERROR); - return; - } - monitor.subTask(NLS.bind(Messages.StaticProfileExtensionsBuilder_subTask_checkingFile, profileFile)); - for (Profile profile : existingProfiles) { - StaticProfilePluginErrorReporter reporter = new StaticProfilePluginErrorReporter(pluginXML, profile, profileFile); - DefaultSAXParser.parse(pluginXML, reporter); - reporter.validateContent(monitor); - } - if (null != monitor) { - monitor.worked(1); - } - } - -} diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java index 25d340ee8fb..7bc59d2e98e 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginChecker.java @@ -16,133 +16,198 @@ package org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers; -import java.lang.reflect.InvocationTargetException; +import static org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_MARKER_TYPE; + +import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; 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.jdt.core.IJavaModelMarker; -import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.emf.helpers.BundleResourceURIHelper; import org.eclipse.papyrus.toolsmiths.validation.common.checkers.BuildPropertiesChecker; +import org.eclipse.papyrus.toolsmiths.validation.common.checkers.CustomModelChecker; +import org.eclipse.papyrus.toolsmiths.validation.common.checkers.ExtensionsChecker; +import org.eclipse.papyrus.toolsmiths.validation.common.checkers.IPluginChecker2; import org.eclipse.papyrus.toolsmiths.validation.common.checkers.ModelDependenciesChecker; +import org.eclipse.papyrus.toolsmiths.validation.common.checkers.ModelValidationChecker; +import org.eclipse.papyrus.toolsmiths.validation.common.internal.utils.PluginErrorReporter; import org.eclipse.papyrus.toolsmiths.validation.common.utils.MarkersService; import org.eclipse.papyrus.toolsmiths.validation.common.utils.PluginValidationService; import org.eclipse.papyrus.toolsmiths.validation.common.utils.ProjectManagementService; -import org.eclipse.papyrus.toolsmiths.validation.profile.Activator; import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.messages.Messages; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; +import org.eclipse.papyrus.uml.tools.utils.PackageUtil; import org.eclipse.uml2.uml.Profile; +import org.eclipse.uml2.uml.UMLPackage; /** - * This allows to check a profile plug-in (extensions, builds, dependencies). + * This allows to check an profile plug-in (extensions, builds, dependencies, ...). */ public class ProfilePluginChecker { + private static final Set ADDITIONAL_REQUIREMENTS = Set.of("org.eclipse.uml2.uml.resources"); //$NON-NLS-1$ + /** * This allows to check the profile plug-in. * * @param project * The current project to check. + * @param A + * monitor to report progress */ - public static void checkProfilePlugin(final IProject project) { + public static void checkProfilePlugin(final IProject project, IProgressMonitor monitor) { + final Collection profileFiles = ProjectManagementService.getFilesFromProject(project, "profile.uml", true); //$NON-NLS-1$ + monitor.beginTask("Validate Profile plug-in", 1 + (profileFiles.size() * 3)); // $NON-NLS-1$ - // Get the shell to manage the validation in an UI - final Shell shell = Display.getCurrent().getActiveShell(); + monitor.subTask("Prepare plug-in validation"); //$NON-NLS-1$ + // First of all, delete the existing markers for project + MarkersService.deleteMarkers(project, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE); - try { - // Open the progress monitor dialog - new ProgressMonitorDialog(shell).run(true, true, monitor -> { - final Collection profileFiles = ProjectManagementService.getFilesFromProject(project, "profile.uml", true); //$NON-NLS-1$ - monitor.beginTask(Messages.ProfilePluginChecker_validateProfilePluginTask, 1 + (profileFiles.size() * 4)); // $NON-NLS-1$ + // Create the plug-in validation service + final PluginValidationService pluginValidationService = new PluginValidationService(); - monitor.subTask("Prepare validation."); //$NON-NLS-1$ - // First of all, delete the existing markers for project - MarkersService.deleteMarkers(project, ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_TYPE); - monitor.worked(1); + // First, check the static dependencies needed + pluginValidationService.addPluginChecker(createModelDependenciesChecker(project)); - // Create the plug-in validation service - final PluginValidationService pluginValidationService = new PluginValidationService(); + // For all profile files in the plug-in + for (final IFile profileFile : profileFiles) { + if (monitor.isCanceled()) { + return; + } - // For all profiles files in the plug-in - for (final IFile profileFile : profileFiles) { + // Get the resource + final URI profileFileURI = URI.createPlatformResourceURI(profileFile.getFullPath().toOSString(), true); + final Resource resource = new ResourceSetImpl().getResource(profileFileURI, true); - // get the existing profiles - final URI profileFileURI = URI.createPlatformResourceURI(profileFile.getFullPath().toOSString(), true); - final Collection profiles = loadProfiles(profileFileURI); + // Check the validation of the element types file + pluginValidationService.addPluginChecker(createModelValidationChecker(project, profileFile, resource)); - if (!profiles.isEmpty()) { - // First, create the extensions checker - pluginValidationService.addPluginChecker(new ProfileExtensionsChecker(project, profileFile, profiles)); + // Check the extension point + pluginValidationService.addPluginChecker(createExtensionsChecker(project, profileFile, resource)); - // Create the profile definition checker (no definition must be done for static profiles) - pluginValidationService.addPluginChecker(new ProfileDefinitionChecker(profileFile, profiles)); + // Check the external dependencies needed + pluginValidationService.addPluginChecker(createModelDependenciesChecker(project, profileFile, resource)); + pluginValidationService.addPluginChecker(createBuildPropertiesChecker(project, profileFile, resource)); + } - // Create the dependencies checker (depending to the external profile references) - Resource resource = profiles.iterator().next().eResource(); - pluginValidationService.addPluginChecker(createProfileDependenciesChecker(project, profileFile, resource)); - } + monitor.worked(1); - // Create the build checker - pluginValidationService.addPluginChecker(new BuildPropertiesChecker(project, profileFile).withEMFGeneratorModels()); - } + // Call the validate + pluginValidationService.validate(monitor); + } - monitor.worked(1); + /** + * Obtain a dependencies checker factory for the specified bundle dependencies validation. + * + * @return the dependencies checker factory + */ + public static IPluginChecker2.Factory modelDependenciesCheckerFactory() { + // When checking the project, we have some additional requirements that aren't model-specific + return IPluginChecker2.Factory.forProject(ProfilePluginChecker::createModelDependenciesChecker) + .or(IPluginChecker2.Factory.forEMFResource(ProfilePluginChecker::createModelDependenciesChecker)); + } - // Call the validate - pluginValidationService.validate(monitor); - }); - } catch (InvocationTargetException e) { - Activator.log.error(e); - } catch (InterruptedException e) { - // Do nothing, just cancelled by user - } + private static ModelDependenciesChecker createModelDependenciesChecker(IProject project) { + // When checking the project, we have some additional requirements that aren't model-specific + return new ModelDependenciesChecker(project, null, null, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE) + .addRequirements(ADDITIONAL_REQUIREMENTS) + .withSeverityFunction(bundle -> ADDITIONAL_REQUIREMENTS.contains(bundle) ? Diagnostic.WARNING : Diagnostic.ERROR); + } + + private static ModelDependenciesChecker createModelDependenciesChecker(IProject project, IFile modelFile, Resource resource) { + return new ModelDependenciesChecker(project, modelFile, resource, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE) + .withAdditionalRequirements(r -> ProfilePluginChecker.getBundlesFromExternalResources(r, project)); + } + + private static Collection getBundlesFromExternalResources(Resource resource, IProject project) { + EcoreUtil.resolveAll(resource); + return resource.getResourceSet().getResources().stream() + .map(BundleResourceURIHelper.INSTANCE::getBundleNameFromResource) + .filter(Objects::nonNull) + .filter(name -> !name.equals(project.getName())) // no self importing. + .collect(Collectors.toList()); } /** - * Loads the EObject from the given URI. + * Obtain a model validation checker factory. * - * @param uri - * The URI from which the EObject is loaded. - * @return - * The profiles available in the model (can be empty if no profile or if an error occurred). + * @return the model validation checker factory */ - private static Collection loadProfiles(final URI uri) { - final Collection profiles = new HashSet<>(); - - final ResourceSet resourceSet = new ResourceSetImpl(); - try { - final Resource resource = resourceSet.getResource(uri, true); - if (null != resource) { - if (!resource.getContents().isEmpty()) { - final Iterator contentIt = resource.getAllContents(); - while (contentIt.hasNext()) { - final EObject content = contentIt.next(); - if (content instanceof Profile) { - profiles.add((Profile) content); - } - } - } - } - } catch (final Exception ex) { - Activator.log.error("Cannot load file: " + uri.toString(), ex); //$NON-NLS-1$ + public static IPluginChecker2.Factory modelValidationCheckerFactory() { + return IPluginChecker2.Factory.forEMFResource(ProfilePluginChecker::createModelValidationChecker); + } + + private static ModelValidationChecker createModelValidationChecker(IProject project, IFile modelFile, Resource resource) { + return new ModelValidationChecker(modelFile, resource, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE); + } + + /** + * Obtain a build properties checker factory. + * + * @return the build properties checker factory + */ + public static IPluginChecker2.Factory buildPropertiesCheckerFactory() { + return IPluginChecker2.Factory.forEMFResource(ProfilePluginChecker::createBuildPropertiesChecker); + } + + private static BuildPropertiesChecker createBuildPropertiesChecker(IProject project, IFile modelFile, Resource resource) { + return new BuildPropertiesChecker(project, modelFile, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE) + .withEMFGeneratorModels(); + } + + /** + * Obtain a plugin.xml extensions checker factory. + * + * @return the extensions checker factory + */ + public static IPluginChecker2.Factory extensionsCheckerFactory() { + return IPluginChecker2.Factory.forEMFResource(ProfilePluginChecker::createExtensionsChecker); + } + + private static ExtensionsChecker> createExtensionsChecker( + IProject project, IFile modelFile, Resource resource) { + + Collection sets = EcoreUtil.getObjectsByType(resource.getContents(), UMLPackage.Literals.PROFILE); + Collection allProfiles = new ArrayList<>(); + for (Profile profile : sets) { + allProfiles.add(profile); + allProfiles.addAll(PackageUtil.getSubProfiles(profile)); + } + return new ExtensionsChecker<>(project, modelFile, allProfiles, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE, ProfilePluginChecker::createPluginErrorReporter); + } + + private static PluginErrorReporter createPluginErrorReporter(IFile pluginXML, IFile modelFile, Profile model) { + ProfilePluginXMLValidator validator = new ProfilePluginXMLValidator(modelFile); + + PluginErrorReporter reporter = new PluginErrorReporter<>(pluginXML, modelFile, model, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE, profile -> profile.getName()) + .requireExtensionPoint(ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT, validator::matchExtension, validator::checkExtension, validator::problemId) + .requireExtensionPoint(ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT, validator::matchExtension, validator::checkExtension, validator::problemId); + + if (model.getNestingPackage() == null) { + return reporter.softRequireExtensionPoint(ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT, validator::matchExtension, validator::checkExtension, validator::problemId); } + return reporter; + } - return profiles; + /** + * Obtain a checker factory for custom model validation rules. + * + * @return the custom model checker factory + */ + public static IPluginChecker2.Factory customModelCheckerFactory() { + return IPluginChecker2.Factory.forEMFResource(ProfilePluginChecker::createCustomModelChecker); } - public static ModelDependenciesChecker createProfileDependenciesChecker(IProject project, IFile profileFile, Resource profileResource) { - // TODO(569357): For now, continue using the Java Model Marker for compatibility until this is all refactored - return new ModelDependenciesChecker(project, profileFile, profileResource, IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER) - .withSeverityFunction(ModelDependenciesChecker.warningsFor("org.eclipse.uml2.uml.resources")); //$NON-NLS-1$ + private static CustomModelChecker createCustomModelChecker(IProject project, IFile modelFile, Resource resource) { + return new CustomModelChecker(modelFile, resource, PROFILE_PLUGIN_VALIDATION_MARKER_TYPE); } } diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginXMLValidator.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginXMLValidator.java new file mode 100644 index 00000000000..fd5416c1b10 --- /dev/null +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/ProfilePluginXMLValidator.java @@ -0,0 +1,321 @@ +/***************************************************************************** + * Copyright (c) 2020 CEA LIST, EclipseSource and others. + * + * 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 + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Remi Schnekenburger - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers; + +import static org.eclipse.papyrus.toolsmiths.validation.common.checkers.BuildPropertiesChecker.BINARY_BUILD_PATH; +import static org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants.STATIC_PROFILE_MARKER_ATTRIBUTE; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.impl.URIMappingRegistryImpl; +import org.eclipse.emf.ecore.xmi.XMIResource; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.emf.utils.ResourceUtils; +import org.eclipse.papyrus.toolsmiths.validation.common.internal.utils.PluginErrorReporter; +import org.eclipse.papyrus.toolsmiths.validation.common.utils.ProjectManagementService; +import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; +import org.eclipse.papyrus.toolsmiths.validation.profile.internal.messages.Messages; +import org.eclipse.papyrus.uml.tools.model.UmlModel; +import org.eclipse.papyrus.uml.tools.utils.StaticProfileUtil; +import org.eclipse.pde.core.build.IBuild; +import org.eclipse.pde.core.build.IBuildEntry; +import org.eclipse.pde.core.build.IBuildModel; +import org.eclipse.uml2.uml.Profile; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Validation of the plugin.xml for static profiles extensions. + */ +final class ProfilePluginXMLValidator { + + public static final String CATEGORY = "profile"; //$NON-NLS-1$ + private static final String PACKAGE = "package"; //$NON-NLS-1$ + private static final String GEN_MODEL_ATTRIBUTE = "genModel"; //$NON-NLS-1$ + private static final String GENMODEL_EXTENSION = "genmodel"; //$NON-NLS-1$ + private static final String URI = "uri"; //$NON-NLS-1$ + private static final String PROFILE = "profile"; //$NON-NLS-1$ + private static final String LOCATION = "location"; //$NON-NLS-1$ + private static final String NAME = "name"; //$NON-NLS-1$ + private static final String PATH = "path"; //$NON-NLS-1$ + private static final String ICONPATH = "iconpath"; //$NON-NLS-1$ + private static final String PATH_SEPARATOR = "/"; //$NON-NLS-1$ + /** Problem IDs for the markers generated by this error reporter. */ + public static final int NO_GENMODEL_MARKER_ID = 0xff1001; + public static final int PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID = 0xff1002; + public static final int MISSING_UML_EXTENSION_MARKER_ID = 0xff1003; + public static final int NO_URI_MARKER_ID = 0xff1004; + public static final int NO_ECORE_GEN_PACKAGE_MARKER_ID = 0xff1005; + public static final int NO_UML2_GEN_PACKAGE_MARKER_ID = 0xff1006; + public static final int NO_PAPYRUS_PROFILE_MARKER_ID = 0xff1007; + public static final int NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID = 0xff1008; + public static final int MISSING_FROM_BINARY_BUILD_MARKER_ID = 0xff1009; + + private static final String PATHMAP = "pathmap://"; //$NON-NLS-1$ + private static final String PLATFORM_PLUGIN = "platform:/plugin/"; //$NON-NLS-1$ + + private final IFile profileFile; + + /** + * Initializes me with the model file that I validate. + * + * @param modelFile + * the model file + */ + ProfilePluginXMLValidator(IFile profileFile) { + super(); + this.profileFile = profileFile; + } + + Optional matchExtension(Element element, String point, Profile profile) { + switch (point) { + case ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT: + NodeList children = element.getElementsByTagName(PACKAGE); + for (int i = 0; i < children.getLength(); i++) { + Element package_ = (Element) children.item(i); + if (matchEcorePackage(package_, profile)) { + return Optional.of(package_); + } + } + break; + case ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT: + NodeList profiles = element.getElementsByTagName(PROFILE); + for (int i = 0; i < profiles.getLength(); i++) { + Element profileElement = (Element) profiles.item(i); + if (matchUML2Package(profileElement, profile)) { + return Optional.of(profileElement); + } + } + break; + case ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT: + if (profile.getNestingPackage() != null) { + break; + } + profiles = element.getElementsByTagName(PROFILE); + for (int i = 0; i < profiles.getLength(); i++) { + Element profileElement = (Element) profiles.item(i); + if (matchPapyrusProfile(profileElement, profile)) { + return Optional.of(profileElement); + } + } + break; + default: + break; + } + + return Optional.empty(); + } + + private boolean matchPapyrusProfile(Element profileElement, Profile profile) { + String profilePath = profileFile.getProjectRelativePath().removeFileExtension().addFileExtension(UmlModel.UML_FILE_EXTENSION).toString(); + String path = decodePath(profileElement.getAttribute(PATH)); + // check path + return profilePath.equals(path); + } + + private boolean matchUML2Package(Element profileElement, Profile profile) { + String extensionNsURI = profileElement.getAttribute(URI); + String stereotypeNsURI = profileURI(profile); + if (stereotypeNsURI == null || stereotypeNsURI.isBlank()) { + // can't check this profile + return false; + } + return Objects.equals(stereotypeNsURI, extensionNsURI); + } + + boolean matchEcorePackage(Element element, Profile profile) { + // warning, should be decoded + String extensionGenModel = decodePath(element.getAttribute(GEN_MODEL_ATTRIBUTE)); + + // retrieve profile file path and compare with given path in extension point + IPath projectRelativePath = profileFile.getProjectRelativePath(); + IPath genModelFilePath = projectRelativePath.removeFileExtension().addFileExtension(GENMODEL_EXTENSION); + String genModelFile = genModelFilePath.toString(); + // compare with profile genmodel + if (Objects.equals(genModelFile, extensionGenModel)) { + String extensionNsURI = element.getAttribute(URI); + String stereotypeNsURI = profileURI(profile); + if (Objects.equals(stereotypeNsURI, extensionNsURI)) { + return true; + } + } + return false; + } + + void checkExtension(Element element, String point, Profile profile, PluginErrorReporter.ProblemReport problems) { + switch (point) { + case ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT: + String extensionNsURI = element.getAttribute(URI); + if (extensionNsURI == null || extensionNsURI.isBlank()) { + problems.reportProblem(Diagnostic.ERROR, element, URI, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, URI), NO_URI_MARKER_ID, CATEGORY, + Collections.singletonMap(STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel())); + } + break; + case ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT: + String extensionlocation = element.getAttribute(LOCATION); + if (extensionlocation == null || extensionlocation.isBlank()) { + problems.reportProblem(Diagnostic.ERROR, element, LOCATION, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, LOCATION), + ProfilePluginValidationConstants.NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID, + CATEGORY, Collections.singletonMap(STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel())); + } + final String profileId = ((XMIResource) profile.eResource()).getID(profile); + String uml2ProfileFile = profileFile.getProjectRelativePath().removeFileExtension().addFileExtension(UmlModel.UML_FILE_EXTENSION).lastSegment(); + + if (!extensionlocation.endsWith(uml2ProfileFile + "#" + profileId)) { //$NON-NLS-1$ + problems.reportProblem(Diagnostic.ERROR, element, LOCATION, NLS.bind(Messages.StaticProfilePluginErrorReporter_wrongLocationForProfile, profile.getLabel()), + MISSING_UML_EXTENSION_MARKER_ID, + CATEGORY, Collections.singletonMap(STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel())); + } + break; + case ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT: + String name = element.getAttribute(NAME); + if (name == null || name.isEmpty()) { + problems.reportProblem(Diagnostic.WARNING, element, NAME, NLS.bind(Messages.StaticProfilePluginErrorReporter_uiLabelIsNull, profile.getLabel()), + ProfilePluginValidationConstants.PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID, + CATEGORY, Collections.singletonMap(STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel())); + } + + // make sure icon is in the binary build + String iconPath = element.getAttribute(ICONPATH); + if (iconPath != null && !iconPath.isBlank()) { + IFile iconFile = profileFile.getProject().getFile(iconPath); + if (iconFile.exists() && !binaryBuildContains(iconFile.getProjectRelativePath())) { + final Map data = new HashMap<>(); + data.put(STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); + data.put(BINARY_BUILD_PATH, iconPath); + problems.reportProblem(Diagnostic.ERROR, element, ICONPATH, NLS.bind(Messages.StaticProfilePluginErrorReporter_resourceMissingFromBinaryBuild, iconPath), + ProfilePluginValidationConstants.MISSING_FROM_BINARY_BUILD_MARKER_ID, + CATEGORY, data); + } + } + break; + default: + break; + } + } + + private static String profileURI(Profile profile) { + return new StaticProfileUtil(profile).getDefinition().getNsURI(); + } + + int problemId(String point, Profile profile) { + switch (point) { + case ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT: + return ProfilePluginValidationConstants.NO_ECORE_GEN_PACKAGE_MARKER_ID; + case ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT: + return ProfilePluginValidationConstants.NO_UML2_GEN_PACKAGE_MARKER_ID; + case ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT: + return ProfilePluginValidationConstants.NO_PAPYRUS_PROFILE_MARKER_ID; + default: + break; + + } + return 0; + } + + private String decodePath(String path) { + if (path == null) { + return null; + } + + // check pathmap, relative URI or platform based uri + if (path.startsWith(PATHMAP)) { + // try to decode using uri mappers extensions + return decodePathmapPath(path); + } else if (path.startsWith(PLATFORM_PLUGIN)) { + // check if path is valid within the plugin + return decodePlatformPath(path); + } + + // relative path? + return path; + } + + private String decodePlatformPath(String path) { + return cutPluginPath(path); + } + + private String decodePathmapPath(String path) { + String decodePath = null; + // check first local mappings + for (Entry entry : ResourceUtils.getLocalUriMappings(profileFile.getProject()).entrySet()) { + String sourceURI = entry.getKey().toString(); + if (path.startsWith(sourceURI)) { + String targetURI = entry.getValue(); + decodePath = replaceString(path, sourceURI, targetURI); + return cutPluginPath(decodePath); + } + } + for (Entry entry : URIMappingRegistryImpl.INSTANCE.entrySet()) { + String sourceURI = entry.getKey().toString(); + if (path.startsWith(sourceURI)) { + String targetURI = entry.getValue().toString(); + decodePath = replaceString(path, sourceURI, targetURI); + return cutPluginPath(decodePath); + } + } + + // cut platform:/plugin/ to get a project relative path + return path; + } + + private String cutPluginPath(String decodePath) { + if (decodePath.startsWith(PLATFORM_PLUGIN)) { + String cutPath = decodePath.substring(PLATFORM_PLUGIN.length()); + int index = cutPath.indexOf(PATH_SEPARATOR); + cutPath = cutPath.substring(index + 1); // remove initial '/' + return cutPath; + } + return decodePath; + } + + private String replaceString(String path, String sourceURI, String targetURI) { + String newPath = path.substring(sourceURI.length(), path.length()); + if (!targetURI.endsWith(PATH_SEPARATOR)) { + newPath = PATH_SEPARATOR.concat(newPath); + } + newPath = targetURI.concat(newPath); + return newPath; + } + + + private boolean binaryBuildContains(IPath path) { + final IBuildModel buildModel = ProjectManagementService.getPluginBuild(profileFile.getProject()); + final IBuild build = buildModel.getBuild(); + final IBuildEntry buildEntry = build.getEntry(IBuildEntry.BIN_INCLUDES); + final String[] tokens = buildEntry.getTokens(); + + if (path.segmentCount() > 1) { + String containingFolder = path.removeLastSegments(1).addTrailingSeparator().toString(); + boolean foundFolder = Arrays.stream(tokens).anyMatch(containingFolder::equals); + if (foundFolder) { + return true; + } + } + return Arrays.stream(tokens).anyMatch(path.toString()::equals); + } + +} diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/SelectiveDeleteErrorReporter.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/SelectiveDeleteErrorReporter.java deleted file mode 100644 index e99e09f2467..00000000000 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/SelectiveDeleteErrorReporter.java +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 Julian Honnen, EclipseSource and others. - * - * 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: - * Julian Honnen - initial API and implementation - * Remi Schnekenburger (EclipseSource) - Bug 568495 - * - *******************************************************************************/ -package org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.papyrus.toolsmiths.validation.common.utils.MarkersService; -import org.eclipse.papyrus.toolsmiths.validation.profile.Activator; -import org.eclipse.pde.internal.core.PDECore; -import org.eclipse.pde.internal.core.builders.IncrementalErrorReporter; -import org.eclipse.pde.internal.core.builders.PDEMarkerFactory; - -/** - * Local copy of the {@link IncrementalErrorReporter} from PDE. - *

- * Overrides marker deletion to delete only some selected markers by id) - *

- */ -@SuppressWarnings("restriction") -public class SelectiveDeleteErrorReporter extends IncrementalErrorReporter { - - public static final String SOURCE_ID = "source_id"; //$NON-NLS-1$ - private final IResource fResource; - private final Collection fReportedMarkers = new ArrayList<>(); - private int fErrorCount; - private final String sourceID; - - public SelectiveDeleteErrorReporter(IResource file, String sourceID) { - super(file); - fResource = file; - this.sourceID = sourceID; - } - - @Override - public VirtualMarker addMarker(String message, int lineNumber, int severity, int problemID, String category) { - - if (lineNumber == -1) { - lineNumber = 1; - } - - if (severity == IMarker.SEVERITY_ERROR) { - fErrorCount++; - } - - VirtualMarker marker = new VirtualMarker(); - marker.setAttribute(PDEMarkerFactory.PROBLEM_ID, problemID); - marker.setAttribute(PDEMarkerFactory.CAT_ID, category); - marker.setAttribute(IMarker.MESSAGE, message); - marker.setAttribute(IMarker.SEVERITY, severity); - marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); - - fReportedMarkers.add(marker); - - return marker; - } - - @Override - public void applyMarkers() { - IMarker[] existingMarkers; - try { - // This seem to be for compatibility with some legacy code, - // PDE builders don't create markers with this type anymore - fResource.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_ZERO); - existingMarkers = fResource.findMarkers(PDEMarkerFactory.MARKER_ID, false, IResource.DEPTH_ZERO); - } catch (CoreException e) { - PDECore.logException(e); - // If we can't read existing, let delete them before we create new - existingMarkers = new IMarker[0]; - try { - fResource.deleteMarkers(PDEMarkerFactory.MARKER_ID, false, IResource.DEPTH_ZERO); - } catch (CoreException e1) { - PDECore.logException(e1); - } - } - - // iterate over existing markers to check which are resolved now - for (IMarker marker : existingMarkers) { - boolean resolved = true; - Map existingAttributes = null; - - // Iterate over new markers to filter out all we already know - for (Iterator it = fReportedMarkers.iterator(); it.hasNext();) { - VirtualMarker reportedMarker = it.next(); - if (existingAttributes == null) { - try { - existingAttributes = marker.getAttributes(); - } catch (Exception e) { - PDECore.logException(e); - // assume the marker is not accessible, can be deleted - break; - } - } - // Same marker is found, no need to create again - if (reportedMarker.getAttributes().equals(existingAttributes)) { - resolved = false; - it.remove(); - break; - } - } - - // The marker was not reported again, the old one can be deleted - // this matchSource was added to allow for multiple passes of the xml parser - if (resolved && matchSource(marker)) { - try { - marker.delete(); - } catch (CoreException e) { - PDECore.logException(e); - } - } - } - - // Create only new markers - for (VirtualMarker reportedMarker : fReportedMarkers) { - try { - IMarker marker = MarkersService.createMarker(fResource, PDEMarkerFactory.MARKER_ID); - if (marker != null) { - marker.setAttributes(reportedMarker.getAttributes()); - } - } catch (CoreException e) { - PDECore.logException(e); - } - } - } - - private boolean matchSource(IMarker marker) { - String markerID = null; - try { - markerID = (String) marker.getAttribute(SOURCE_ID); - } catch (CoreException e) { - Activator.log.error(e); - } - return this.sourceID.equals(markerID); - } - - @Override - public int getErrorCount() { - return fErrorCount; - } - - -} diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/StaticProfilePluginErrorReporter.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/StaticProfilePluginErrorReporter.java deleted file mode 100644 index af59e839779..00000000000 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/checkers/StaticProfilePluginErrorReporter.java +++ /dev/null @@ -1,539 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2020 CEA LIST, EclipseSource and others. - * - * 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 - * http://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Remi Schnekenburger (EclipseSource) - Initial API and implementation - * - *****************************************************************************/ -package org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.resource.impl.URIMappingRegistryImpl; -import org.eclipse.emf.ecore.xmi.XMIResource; -import org.eclipse.osgi.util.NLS; -import org.eclipse.papyrus.toolsmiths.validation.common.utils.ProjectManagementService; -import org.eclipse.papyrus.toolsmiths.validation.profile.Activator; -import org.eclipse.papyrus.toolsmiths.validation.profile.constants.ProfilePluginValidationConstants; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.messages.Messages; -import org.eclipse.papyrus.uml.tools.model.UmlModel; -import org.eclipse.papyrus.uml.tools.utils.StaticProfileUtil; -import org.eclipse.pde.core.build.IBuild; -import org.eclipse.pde.core.build.IBuildEntry; -import org.eclipse.pde.core.build.IBuildModel; -import org.eclipse.pde.internal.core.builders.CompilerFlags; -import org.eclipse.pde.internal.core.builders.IncrementalErrorReporter.VirtualMarker; -import org.eclipse.pde.internal.core.builders.PluginBaseErrorReporter; -import org.eclipse.pde.internal.core.builders.XMLErrorReporter; -import org.eclipse.uml2.uml.Profile; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * Error reporter for specific extensions for static profiles. - */ -@SuppressWarnings("restriction") -public class StaticProfilePluginErrorReporter extends PluginBaseErrorReporter { - - /** Problem IDs for the markers generated by this error reporter. */ - public static final int NO_GENMODEL_MARKER_ID = 0xff1001; - public static final int PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID = 0xff1002; - public static final int MISSING_UML_EXTENSION_MARKER_ID = 0xff1003; - public static final int NO_URI_MARKER_ID = 0xff1004; - public static final int NO_ECORE_GEN_PACKAGE_MARKER_ID = 0xff1005; - public static final int NO_UML2_GEN_PACKAGE_MARKER_ID = 0xff1006; - public static final int NO_PAPYRUS_PROFILE_MARKER_ID = 0xff1007; - public static final int NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID = 0xff1008; - public static final int MISSING_FROM_BINARY_BUILD_MARKER_ID = 0xff1009; - - /** Attributes of markers created by this error reporter */ - public static final String STATIC_PROFILE_STEREOTYPE_URI = "staticProfileStereotypeUri"; //$NON-NLS-1$ - public static final String STATIC_PROFILE_MARKER_ATTRIBUTE = "staticProfile"; //$NON-NLS-1$ - public static final String STATIC_PROFILE_BINARY_BUILD_PATH = "binaryBuildPath"; //$NON-NLS-1$ - - private static final String NAME = "name"; //$NON-NLS-1$ - private static final String PATH = "path"; //$NON-NLS-1$ - private static final String LOCATION = "location"; //$NON-NLS-1$ - private static final String URI = "uri"; //$NON-NLS-1$ - private static final String GEN_MODEL_ATTRIBUTE = "genModel"; //$NON-NLS-1$ - private static final String PACKAGE = "package"; //$NON-NLS-1$ - private static final String ICONPATH = "iconpath"; //$NON-NLS-1$ - private static final String MAPPING = "mapping"; //$NON-NLS-1$ - private static final String GENMODEL_EXTENSION = "genmodel"; //$NON-NLS-1$ - private static final String PROFILE = "profile"; //$NON-NLS-1$ - private static final String TARGET = "target"; //$NON-NLS-1$ - private static final String SOURCE = "source"; //$NON-NLS-1$ - private static final String POINT = "point"; //$NON-NLS-1$ - - private static final String PATHMAP = "pathmap://"; //$NON-NLS-1$ - private static final String PLATFORM_PLUGIN = "platform:/plugin/"; //$NON-NLS-1$ - - private static final String STATIC_PROFILE_CATEGORY = "Papyrus-staticProfile";//$NON-NLS-1$ - - private static final String PATH_SEPARATOR = "/"; //$NON-NLS-1$ - private static final String ID_SEPARATOR = "_"; //$NON-NLS-1$ - - - private final List foundPoints = new ArrayList<>(); - - private final Map localURIMappings = new HashMap<>(); - - private Profile profile; - private IFile profileFile; - - private String sourceID; - - private List papyrusProfileExtensions = new ArrayList<>(); - - /** - * Constructor. - * - * @param file - * the plugin.xml file - * @param profile - * the profile model element - * @param profileFile - * the profile containing file. - */ - public StaticProfilePluginErrorReporter(IFile file, Profile profile, IFile profileFile) { - super(file); - this.profile = profile; - this.fFile = file; - this.profileFile = profileFile; - sourceID = sourceID(profileFile, profile); - replaceReporter(this, file); - - } - - /** - * Replace the reporter created by default on abstract class, to implement our specific one. - * - * @see SelectiveDeleteErrorReporter. - */ - private void replaceReporter(StaticProfilePluginErrorReporter reporter, IFile file) { - Field errorReporterField; - try { - errorReporterField = XMLErrorReporter.class.getDeclaredField("fErrorReporter"); //$NON-NLS-1$ - errorReporterField.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers");//$NON-NLS-1$ - modifiersField.setAccessible(true); - modifiersField.setInt(modifiersField, modifiersField.getModifiers() & ~Modifier.FINAL); - errorReporterField.set(reporter, new SelectiveDeleteErrorReporter(file, sourceID)); - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - Activator.log.error(e); - } - - } - - /** - * Returns a unique id for the specified profile model element in the given profile file. - * - * @param file - * the profile file - * @param profile - * the profile model element - * @return the unique identifier for this profile in the plugin, which will allow to identify markers associated to this profile on the plugin.xml - */ - private static String sourceID(IFile file, Profile profile) { - StringBuilder builder = new StringBuilder(); - builder.append("staticprofile"); //$NON-NLS-1$ - builder.append(ID_SEPARATOR); - builder.append(file.getProjectRelativePath().toString()); - builder.append(ID_SEPARATOR); - String name = profile.getQualifiedName(); - builder.append(name); - return builder.toString(); - } - - @Override - protected String getRootElementName() { - return "plugin"; //$NON-NLS-1$ - } - - @Override - public void validate(IProgressMonitor monitor) { - super.validate(monitor); - - postValidatePapyrusExtensions(); - - // now check the found extensions and throw error for inexisting ones - if (!foundPoints.contains(ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT)) { - reportNoEcoreGeneratedPackage(); - } - if (!foundPoints.contains(ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT)) { - reportNoUML2GeneratedPackage(); - } - if (!foundPoints.contains(ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT)) { - if (profile.getNestingPackage() == null) { - reportNoPapyrusProfile(); - } - } - } - - /** - * Validate the specific static profile extensions once the validation has visited all extensions in the plugin.xml file. - */ - private void postValidatePapyrusExtensions() { - if (profile.getNestingPackage() != null) { - return; - } - - String profilePath = profileFile.getProjectRelativePath().removeFileExtension().addFileExtension(UmlModel.UML_FILE_EXTENSION).toString(); - - for (Element papyrusProfileExtension : papyrusProfileExtensions) { - String name = papyrusProfileExtension.getAttribute(NAME); - String path = decodePath(papyrusProfileExtension.getAttribute(PATH)); - // check path - if (!profilePath.equals(path)) { - continue; - } - foundPoints.add(ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT); - // UI name shall not be null - if (name == null || name.isEmpty()) { - VirtualMarker marker = report(NLS.bind(Messages.StaticProfilePluginErrorReporter_uiLabelIsNull, profile.getLabel()), getLine(papyrusProfileExtension, NAME), CompilerFlags.ERROR, PAPYRUS_PROFILE_EXTENSION_NO_NAME_MARKER_ID, - papyrusProfileExtension, NAME, - STATIC_PROFILE_CATEGORY); - addMarkerAttribute(marker, STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); - } - - // make sure icon is in the binary build - String iconPath = papyrusProfileExtension.getAttribute(ICONPATH); - if (iconPath != null && !iconPath.isBlank()) { - IFile iconFile = profileFile.getProject().getFile(iconPath); - if (iconFile.exists() && !binaryBuildContains(iconFile.getProjectRelativePath())) { - VirtualMarker marker = addErrorMarker(papyrusProfileExtension, ICONPATH, NLS.bind(Messages.StaticProfilePluginErrorReporter_resourceMissingFromBinaryBuild, iconPath), MISSING_FROM_BINARY_BUILD_MARKER_ID); - marker.setAttribute(STATIC_PROFILE_BINARY_BUILD_PATH, iconPath); - } - } - } - } - - private boolean binaryBuildContains(IPath path) { - final IBuildModel buildModel = ProjectManagementService.getPluginBuild(profileFile.getProject()); - final IBuild build = buildModel.getBuild(); - final IBuildEntry buildEntry = build.getEntry(IBuildEntry.BIN_INCLUDES); - final String[] tokens = buildEntry.getTokens(); - - if (path.segmentCount() > 1) { - String containingFolder = path.removeLastSegments(1).addTrailingSeparator().toString(); - boolean foundFolder = Arrays.stream(tokens).anyMatch(containingFolder::equals); - if (foundFolder) { - return true; - } - } - return Arrays.stream(tokens).anyMatch(path.toString()::equals); - } - - /** - * Reports that no ECore generated package was found for the current profile. - */ - private void reportNoEcoreGeneratedPackage() { - VirtualMarker marker = reportForProfile(NLS.bind(Messages.StaticProfilePluginErrorReporter_noEcoreGeneratedPackageFound, profile.getLabel()), 1, CompilerFlags.ERROR, NO_ECORE_GEN_PACKAGE_MARKER_ID, STATIC_PROFILE_CATEGORY); - addMarkerAttribute(marker, STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); - } - - private VirtualMarker reportForProfile(String message, int line, int severity, int fixId, String category) { - VirtualMarker marker = report(message, line, severity, fixId, category); - addMarkerID(marker); - return marker; - } - - private void addMarkerID(VirtualMarker marker) { - if (marker == null) { - return; - } - addMarkerAttribute(marker, SelectiveDeleteErrorReporter.SOURCE_ID, sourceID); - } - - /** - * Reports that no UML2 generated package was found for the current profile. - */ - private void reportNoUML2GeneratedPackage() { - VirtualMarker marker = reportForProfile(NLS.bind(Messages.StaticProfilePluginErrorReporter_noUML2GeneratedPackage, profile.getLabel()), 1, CompilerFlags.ERROR, NO_UML2_GEN_PACKAGE_MARKER_ID, STATIC_PROFILE_CATEGORY); - addMarkerAttribute(marker, STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); - } - - /** - * Reports that no Papyrus profile extension was found for the current profile. - */ - private void reportNoPapyrusProfile() { - VirtualMarker marker = reportForProfile(NLS.bind(Messages.StaticProfilePluginErrorReporter_NoPapyrusProfileExtensionFound, profile.getLabel()), 1, CompilerFlags.WARNING, NO_PAPYRUS_PROFILE_MARKER_ID, STATIC_PROFILE_CATEGORY); - addMarkerAttribute(marker, STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); - } - - @Override - protected void validateExtension(Element element) { - // do not let default validation be done, this will be done by standard plugin builder - String pointID = element.getAttribute(POINT); - // find the correct checker - switch (pointID) { - case ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT: - if (foundPoints.contains(ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT)) { - // already found the extension that should be checked, so avoid checking others. - break; - } - // check if this is the correct profile to test - checkEcoreGeneratedPackage(element); - break; - case ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT: - if (foundPoints.contains(ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT)) { - break; - } - checkUML2GeneratedPackage(element); - break; - case ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT: - if (foundPoints.contains(ProfilePluginValidationConstants.UMLPROFILE_EXTENSION_POINT)) { - break; - } - checkPapyrusProfile(element); - break; - case ProfilePluginValidationConstants.ECORE_URI_MAPPING_EXTENSION_POINT: - collectMapping(element); - break; - default: - break; - } - - } - - private void collectMapping(Element element) { - for (int i = 0; i < element.getChildNodes().getLength(); i++) { - Node node = element.getChildNodes().item(i); - if (node instanceof Element && MAPPING.equals(((Element) node).getNodeName())) { - Element profileElement = (Element) node; - String sourceURI = profileElement.getAttribute(SOURCE); - String targetURI = profileElement.getAttribute(TARGET); - localURIMappings.put(sourceURI, targetURI); - } - } - } - - private void checkPapyrusProfile(Element element) { - /* - * - * - * - * - */ - // should check only for root profiles - if (profile.getNestingPackage() != null) { - return; - } - - for (int i = 0; i < element.getChildNodes().getLength(); i++) { - Node node = element.getChildNodes().item(i); - if (node instanceof Element && PROFILE.equals(((Element) node).getNodeName())) { - papyrusProfileExtensions.add((Element) node); - } - } - - } - - private void checkUML2GeneratedPackage(Element element) { - /* - * - * - * - * - */ - String stereotypeNsURI = profileURI(profile); - if (stereotypeNsURI == null || stereotypeNsURI.isBlank()) { - // can't check this profile - return; - } - for (int i = 0; i < element.getChildNodes().getLength(); i++) { - Node node = element.getChildNodes().item(i); - if (node instanceof Element && PROFILE.equals(((Element) node).getNodeName())) { - Element profileElement = (Element) node; - String extensionNsURI = profileElement.getAttribute(URI); - if (extensionNsURI == null || extensionNsURI.isBlank()) { - VirtualMarker marker = addErrorMarker(profileElement, URI, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, URI), NO_URI_MARKER_ID); - marker.setAttribute(STATIC_PROFILE_STEREOTYPE_URI, stereotypeNsURI); - } - String extensionlocation = profileElement.getAttribute(LOCATION); - if (extensionlocation == null || extensionlocation.isBlank()) { - addErrorMarker(profileElement, LOCATION, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, LOCATION), NO_UML2_GEN_PACKAGE_LOCATION_MARKER_ID); - } - // check this is the good extension point => genmodel should match first - if (Objects.equals(stereotypeNsURI, extensionNsURI)) { - foundPoints.add(ProfilePluginValidationConstants.UML_GENERATED_PACKAGE_EXTENSION_POINT); - - final String profileId = ((XMIResource) profile.eResource()).getID(profile); - String uml2ProfileFile = profileFile.getProjectRelativePath().removeFileExtension().addFileExtension(UmlModel.UML_FILE_EXTENSION).lastSegment(); - - if (!extensionlocation.endsWith(uml2ProfileFile + "#" + profileId)) { //$NON-NLS-1$ - addErrorMarker(profileElement, LOCATION, NLS.bind(Messages.StaticProfilePluginErrorReporter_wrongLocationForProfile, profile.getLabel()), MISSING_UML_EXTENSION_MARKER_ID); - } - } - } - } - - } - - private VirtualMarker reportForProfile(String message, int line, int severity, int fixId, Element element, String attrName, - String category) { - VirtualMarker marker = report(message, line, severity, fixId, element, attrName, category); - addMarkerID(marker); - return marker; - } - - private void checkEcoreGeneratedPackage(Element element) { - for (int i = 0; i < element.getChildNodes().getLength(); i++) { - Node node = element.getChildNodes().item(i); - if (node instanceof Element && PACKAGE.equals(((Element) node).getNodeName())) { - Element packageElement = (Element) node; - String extensionGenModel = packageElement.getAttribute(GEN_MODEL_ATTRIBUTE); - - // genmodel should be set - if (extensionGenModel == null || extensionGenModel.isBlank()) { - addErrorMarker(packageElement, GEN_MODEL_ATTRIBUTE, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, GEN_MODEL_ATTRIBUTE), NO_GENMODEL_MARKER_ID); - return; - } - - // retrieve profile file path and compare with given path in extension point - IPath projectRelativePath = profileFile.getProjectRelativePath(); - IPath genModelFilePath = projectRelativePath.removeFileExtension().addFileExtension(GENMODEL_EXTENSION); - String genModelFile = genModelFilePath.toString(); - // compare with profile genmodel - if (!Objects.equals(genModelFile, extensionGenModel)) { - // different profile, return - return; - } - - boolean genModelEntryFound = binaryBuildContains(genModelFilePath); - if (!genModelEntryFound) { - VirtualMarker marker = addErrorMarker(packageElement, GEN_MODEL_ATTRIBUTE, NLS.bind(Messages.StaticProfilePluginErrorReporter_resourceMissingFromBinaryBuild, genModelFile), MISSING_FROM_BINARY_BUILD_MARKER_ID); - marker.setAttribute(STATIC_PROFILE_BINARY_BUILD_PATH, genModelFile); - } - String stereotypeNsURI = profileURI(profile); - - // uri should be set - String extensionNsURI = packageElement.getAttribute(URI); - if (extensionNsURI == null || extensionNsURI.isBlank()) { - VirtualMarker marker = addErrorMarker(packageElement, URI, NLS.bind(Messages.StaticProfilePluginErrorReporter_missingExtensionPointAttribute, URI), NO_URI_MARKER_ID); - marker.setAttribute(STATIC_PROFILE_STEREOTYPE_URI, stereotypeNsURI); - return; - } - - // compare URI with profile uri in stereotype ecore::epackage - if (Objects.equals(stereotypeNsURI, extensionNsURI)) { - foundPoints.add(ProfilePluginValidationConstants.ECORE_GENERATED_PACKAGE_EXTENSION_POINT); - } - } - } - } - - private VirtualMarker addErrorMarker(Element element, String attribute, String message, int problemId) { - VirtualMarker marker = reportForProfile(message, - getLine(element, attribute), CompilerFlags.ERROR, problemId, element, attribute, STATIC_PROFILE_CATEGORY); - addMarkerAttribute(marker, STATIC_PROFILE_MARKER_ATTRIBUTE, profile.getLabel()); - return marker; - } - - @Override - protected int getLine(Element element, String attName) { - // when multiple elements with the same name exist, - // an incorrect line is returned from the super call if the attribute does not exist in the element - if (element.hasAttribute(attName)) { - return super.getLine(element, attName); - } - return getLine(element); - } - - private static String profileURI(Profile profile) { - return new StaticProfileUtil(profile).getDefinition().getNsURI(); - } - - private String decodePath(String path) { - if (path == null) { - return null; - } - - // check pathmap, relative URI or platform based uri - if (path.startsWith(PATHMAP)) { - // try to decode using uri mappers extensions - return decodePathmapPath(path); - } else if (path.startsWith(PLATFORM_PLUGIN)) { - // check if path is valid within the plugin - return decodePlatformPath(path); - } - - // relative path? - return path; - } - - private String decodePlatformPath(String path) { - return cutPluginPath(path); - } - - private String decodePathmapPath(String path) { - String decodePath = null; - // check first local mappings - for (Entry entry : localURIMappings.entrySet()) { - String sourceURI = entry.getKey().toString(); - if (path.startsWith(sourceURI)) { - String targetURI = entry.getValue(); - decodePath = replaceString(path, sourceURI, targetURI); - return cutPluginPath(decodePath); - } - } - for (Entry entry : URIMappingRegistryImpl.INSTANCE.entrySet()) { - String sourceURI = entry.getKey().toString(); - if (path.startsWith(sourceURI)) { - String targetURI = entry.getValue().toString(); - decodePath = replaceString(path, sourceURI, targetURI); - return cutPluginPath(decodePath); - } - } - - // cut platform:/plugin/ to get a project relative path - return path; - } - - private String cutPluginPath(String decodePath) { - if (decodePath.startsWith(PLATFORM_PLUGIN)) { - String cutPath = decodePath.substring(PLATFORM_PLUGIN.length()); - int index = cutPath.indexOf(PATH_SEPARATOR); - cutPath = cutPath.substring(index + 1); // remove initial '/' - return cutPath; - } - return decodePath; - } - - private String replaceString(String path, String sourceURI, String targetURI) { - String newPath = path.substring(sourceURI.length(), path.length()); - if (!targetURI.endsWith(PATH_SEPARATOR)) { - newPath = PATH_SEPARATOR.concat(newPath); - } - newPath = targetURI.concat(newPath); - return newPath; - } - -} diff --git a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/handlers/ValidateProfilePluginHandler.java b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/handlers/ValidateProfilePluginHandler.java index a3c38e574ed..b627e56cdf2 100644 --- a/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/handlers/ValidateProfilePluginHandler.java +++ b/plugins/toolsmiths/validation/org.eclipse.papyrus.toolsmiths.validation.profile/src/org/eclipse/papyrus/toolsmiths/validation/profile/internal/handlers/ValidateProfilePluginHandler.java @@ -15,13 +15,19 @@ package org.eclipse.papyrus.toolsmiths.validation.profile.internal.handlers; +import java.lang.reflect.InvocationTargetException; + import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.papyrus.toolsmiths.validation.profile.internal.checkers.ProfilePluginChecker; +import org.eclipse.papyrus.toolsmiths.validation.profile.Activator; +import org.eclipse.papyrus.toolsmiths.validation.profile.checkers.ProfilePluginCheckerService; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; /** @@ -42,12 +48,27 @@ public class ValidateProfilePluginHandler extends AbstractHandler { return null; } - final StructuredSelection structuredSelection = (StructuredSelection) selection; - for (final Object selectedElement : structuredSelection.toList()) { - if (selectedElement instanceof IProject) { - final IProject project = (IProject) selectedElement; - ProfilePluginChecker.checkProfilePlugin(project); - } + final Shell shell = HandlerUtil.getActiveShell(event); + + try { + new ProgressMonitorDialog(shell).run(true, true, monitor -> { + final StructuredSelection structuredSelection = (StructuredSelection) selection; + monitor.beginTask("Validate Profiles", structuredSelection.size()); + for (final Object selectedElement : structuredSelection.toList()) { + if (monitor.isCanceled()) { + return; + } + if (selectedElement instanceof IProject) { + final IProject project = (IProject) selectedElement; + ProfilePluginCheckerService.checkProfilePlugin(project, SubMonitor.convert(monitor)); + } + SubMonitor.done(monitor); + } + }); + } catch (InvocationTargetException e) { + Activator.log.error(e); + } catch (InterruptedException e) { + // Do nothing, just cancelled by user } return null; diff --git a/tests/junit/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths.validation.profile.tests/src/org/eclipse/papyrus/toolsmiths/validation/profile/tests/ProfilePluginValidationTest.java b/tests/junit/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths.validation.profile.tests/src/org/eclipse/papyrus/toolsmiths/validation/profile/tests/ProfilePluginValidationTest.java index 5238006842b..2a86284b9a9 100644 --- a/tests/junit/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths.validation.profile.tests/src/org/eclipse/papyrus/toolsmiths/validation/profile/tests/ProfilePluginValidationTest.java +++ b/tests/junit/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths.validation.profile.tests/src/org/eclipse/papyrus/toolsmiths/validation/profile/tests/ProfilePluginValidationTest.java @@ -71,37 +71,35 @@ public class ProfilePluginValidationTest extends AbstractPapyrusTest { @Test public void testProfilePluginValidation() { // First, run the validation - ProfilePluginCheckerService.checkProfilePlugin(fixture.getProject()); + ProfilePluginCheckerService.checkProfilePlugin(fixture.getProject(), null); // Get the markers List markers = null; try { - markers = Arrays.asList(fixture.getProject().findMarkers(ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_TYPE, true, IResource.DEPTH_INFINITE)); + markers = Arrays.asList(fixture.getProject().findMarkers(ProfilePluginValidationConstants.PROFILE_PLUGIN_VALIDATION_MARKER_TYPE, true, IResource.DEPTH_INFINITE)); } catch (CoreException e) { Assert.fail("Error with resource"); //$NON-NLS-1$ } // Now check the markers Assert.assertNotNull("The markers have to be found", markers); //$NON-NLS-1$ - Assert.assertEquals("The number of markers is not correct", 5, markers.size()); //$NON-NLS-1$ + Assert.assertEquals("The number of markers is not correct", 6, markers.size()); //$NON-NLS-1$ // Check the profile.uml markers final List profileFileMarkers = markers.stream().filter(marker -> marker.getResource().getFullPath().toString().endsWith("bookstore.profile.uml")).collect(Collectors.toList()); //$NON-NLS-1$ Assert.assertNotNull("Profile file markers are not found", profileFileMarkers); //$NON-NLS-1$ - Assert.assertEquals("The number of markers for profile file is not correct", 1, profileFileMarkers.size()); //$NON-NLS-1$ - Assert.assertTrue("The severity of profile marker is not correct", isMarkerSeverity(profileFileMarkers.get(0), IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ + Assert.assertEquals("The number of markers for profile file is not correct", 0, profileFileMarkers.size()); //$NON-NLS-1$ // Check the dependencies markers final List manifestMarkers = markers.stream().filter(marker -> marker.getResource().getFullPath().toString().endsWith("MANIFEST.MF")).collect(Collectors.toList()); //$NON-NLS-1$ Assert.assertNotNull("Dependencies markers are not found", manifestMarkers); //$NON-NLS-1$ - Assert.assertEquals("The number of markers for dependencies is not correct", 1, manifestMarkers.size()); //$NON-NLS-1$ + Assert.assertEquals("The number of markers for dependencies is not correct", 4, manifestMarkers.size()); //$NON-NLS-1$ Assert.assertTrue("The severity of profile marker is not correct", isMarkerSeverity(manifestMarkers.get(0), IMarker.SEVERITY_WARNING)); //$NON-NLS-1$ // Check the build markers final List buildMarkers = markers.stream().filter(marker -> marker.getResource().getFullPath().toString().endsWith("build.properties")).collect(Collectors.toList()); //$NON-NLS-1$ Assert.assertNotNull("Build markers are not found", buildMarkers); //$NON-NLS-1$ - Assert.assertEquals("The number of markers for build is not correct", 1, buildMarkers.size()); //$NON-NLS-1$ - Assert.assertTrue("The severity of profile marker is not correct", isMarkerSeverity(buildMarkers.get(0), IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ + Assert.assertEquals("The number of markers for build is not correct", 0, buildMarkers.size()); //$NON-NLS-1$ // Check the extensions markers final List extensionsMarkers = markers.stream().filter(marker -> marker.getResource().getFullPath().toString().endsWith("plugin.xml")).collect(Collectors.toList()); //$NON-NLS-1$ -- cgit v1.2.3