From 2264a6d0090b6e8dab54705cf03523647fba74b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 12 Nov 2023 14:04:20 +0100 Subject: [PATCH] Add a ClasspathContributor for API tools annotations Currently it is quite cumbersome to use and discover the PDE own API tools annotations and requires some kind of workarounds. This adds a classpath contributor that makes the annotations available like already done for ds and bundle annotations. Fix https://github.com/eclipse-pde/eclipse.pde/issues/447 --- apitools/org.eclipse.pde.api.tools/plugin.xml | 6 ++ .../ApiAnnotationsClasspathContributor.java | 78 +++++++++++++++++++ .../pde/internal/core/ClasspathUtilCore.java | 27 +++++++ .../OSGiAnnotationsClasspathContributor.java | 17 +--- 4 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiAnnotationsClasspathContributor.java diff --git a/apitools/org.eclipse.pde.api.tools/plugin.xml b/apitools/org.eclipse.pde.api.tools/plugin.xml index ce7f17033d..3b795b4e9e 100644 --- a/apitools/org.eclipse.pde.api.tools/plugin.xml +++ b/apitools/org.eclipse.pde.api.tools/plugin.xml @@ -328,4 +328,10 @@ + + + + diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiAnnotationsClasspathContributor.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiAnnotationsClasspathContributor.java new file mode 100644 index 0000000000..9b21e56aa1 --- /dev/null +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiAnnotationsClasspathContributor.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich 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: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.api.tools.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; +import org.eclipse.pde.core.IClasspathContributor; +import org.eclipse.pde.core.plugin.IPluginModelBase; +import org.eclipse.pde.core.plugin.PluginRegistry; +import org.eclipse.pde.internal.core.ClasspathUtilCore; + +public class ApiAnnotationsClasspathContributor implements IClasspathContributor { + + private static final Collection API_TOOLS_ANNOTATIONS = List.of("org.eclipse.pde.api.tools.annotations"); //$NON-NLS-1$ + + @Override + public List getInitialEntries(BundleDescription project) { + IPluginModelBase model = PluginRegistry.findModel(project); + if (hasApiNature(model)) { + return ClasspathUtilCore.classpathEntries(annotations()).collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + + + private boolean hasApiNature(IPluginModelBase model) { + if (model != null) { + IResource resource = model.getUnderlyingResource(); + if (resource != null) { + try { + return resource.getProject().hasNature(ApiPlugin.NATURE_ID); + } catch (CoreException e) { + // assume not compatible project then... + } + } + } + return false; + } + + + + /** + * @return s stream of all current available annotations in the current plugin + * registry + */ + public static Stream annotations() { + return API_TOOLS_ANNOTATIONS.stream().map(PluginRegistry::findModel).filter(Objects::nonNull) + .filter(IPluginModelBase::isEnabled); + } + + @Override + public List getEntriesForDependency(BundleDescription project, BundleDescription addedDependency) { + return Collections.emptyList(); + } + +} diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ClasspathUtilCore.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ClasspathUtilCore.java index e4e2f97529..ce616caf81 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ClasspathUtilCore.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/ClasspathUtilCore.java @@ -17,11 +17,16 @@ import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Objects; +import java.util.stream.Stream; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.IAccessRule; +import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.JavaCore; import org.eclipse.osgi.service.resolver.BundleDescription; @@ -76,6 +81,28 @@ private static Collection collectLibraryEntries(IPluginModelBa return entries; } + public static Stream classpathEntries(Stream models) { + return models.flatMap(model -> { + String location = model.getInstallLocation(); + if (location == null) { + return Stream.empty(); + } + boolean isJarShape = new File(location).isFile(); + IPluginLibrary[] libraries = model.getPluginBase().getLibraries(); + if (isJarShape || libraries.length == 0) { + return Stream.of(IPath.fromOSString(location)); + } + return Arrays.stream(libraries).filter(library -> !IPluginLibrary.RESOURCE.equals(library.getType())) + .map(library -> { + String name = library.getName(); + String expandedName = ClasspathUtilCore.expandLibraryName(name); + IPath path = ClasspathUtilCore.getPath(model, expandedName, isJarShape); + return path; + }).filter(Objects::nonNull); + }).map(path -> JavaCore.newLibraryEntry(path, path, IPath.ROOT, new IAccessRule[0], new IClasspathAttribute[0], + false)); + } + private static void addLibraryEntry(IPluginLibrary library, Collection entries) { String name = library.getName(); diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/annotations/OSGiAnnotationsClasspathContributor.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/annotations/OSGiAnnotationsClasspathContributor.java index b6b3dfbf47..b5e4b758a9 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/annotations/OSGiAnnotationsClasspathContributor.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/annotations/OSGiAnnotationsClasspathContributor.java @@ -20,15 +20,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.eclipse.core.runtime.IPath; -import org.eclipse.jdt.core.IAccessRule; -import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.JavaCore; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.pde.core.IClasspathContributor; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.PluginRegistry; +import org.eclipse.pde.internal.core.ClasspathUtilCore; /** * This makes the getInitialEntries(BundleDescription project) { IPluginModelBase model = PluginRegistry.findModel(project); if (model != null) { - return entries().collect(Collectors.toList()); + return ClasspathUtilCore.classpathEntries(annotations()).collect(Collectors.toList()); } return Collections.emptyList(); } - static Stream entries() { - return annotations().map(IPluginModelBase::getInstallLocation).filter(Objects::nonNull).map(IPath::fromOSString) - .map(path -> JavaCore.newLibraryEntry(path, path, IPath.ROOT, new IAccessRule[0], - new IClasspathAttribute[0], false)); - } - /** - * @return s stream of all current aviable annotations in the current plugin - * registry + * @return s stream of all current available annotations in the current + * plugin registry */ public static Stream annotations() { return OSGI_ANNOTATIONS.stream().map(PluginRegistry::findModel).filter(Objects::nonNull)