From c6be567f240e5b55b303d6bc6e5a82522f27ff85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 8 Oct 2023 13:25:41 +0200 Subject: [PATCH] Workaround for eclipse-pde/eclipse.pde#789 and eclipse-pde/eclipse.pde#791 --- .../eclipse/tycho/apitools/ApiAnalysis.java | 40 ++++++++++++++++++- .../tycho/test/apitools/ApiToolsTest.java | 38 +++++++++++++----- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/tycho-apitools-plugin/src/main/java/org/eclipse/tycho/apitools/ApiAnalysis.java b/tycho-apitools-plugin/src/main/java/org/eclipse/tycho/apitools/ApiAnalysis.java index c5c027cca2..d0c0ca3117 100644 --- a/tycho-apitools-plugin/src/main/java/org/eclipse/tycho/apitools/ApiAnalysis.java +++ b/tycho-apitools-plugin/src/main/java/org/eclipse/tycho/apitools/ApiAnalysis.java @@ -27,6 +27,7 @@ import java.util.concurrent.Callable; import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; @@ -36,7 +37,11 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; import org.eclipse.osgi.service.resolver.ResolverError; import org.eclipse.pde.api.tools.internal.BundleListTargetLocation; import org.eclipse.pde.api.tools.internal.FilterStore; @@ -56,6 +61,8 @@ import org.eclipse.pde.core.target.ITargetPlatformService; import org.eclipse.pde.core.target.LoadTargetDefinitionJob; import org.eclipse.pde.core.target.TargetBundle; +import org.eclipse.pde.internal.core.ICoreConstants; +import org.eclipse.pde.internal.core.PDECore; import org.eclipse.pde.internal.core.target.TargetPlatformService; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; @@ -86,6 +93,7 @@ public ApiAnalysis(Collection baselineBundles, Collection dependency @Override public ApiAnalysisResult call() throws Exception { ApiAnalysisResult result = new ApiAnalysisResult(); + Platform.addLogListener((status, plugin) -> debug(status.toString())); printVersion(); disableAutoBuild(); setTargetPlatform(); @@ -124,9 +132,14 @@ private BundleComponent importProject() throws CoreException, IOException { .loadProjectDescription(projectDescriptionFile); projectDescription.setLocation(projectPath); projectDescription.setBuildSpec(new ICommand[0]); - IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectDescription.getName()); + // FIXME ApiTools wrongly assumes that the location matches the project name + // see: https://github.com/eclipse-pde/eclipse.pde/issues/789 + // therefore we here must not use projectDescription.getName() but + // projectPath.lastSegment() ... + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectPath.lastSegment()); project.create(projectDescription, new NullProgressMonitor()); project.open(new NullProgressMonitor()); + createOutputFolder(project, projectPath); IApiBaseline workspaceBaseline = ApiPlugin.getDefault().getApiBaselineManager().getWorkspaceBaseline(); IApiComponent component = workspaceBaseline.getApiComponent(project); if (component instanceof ProjectComponent projectComponent) { @@ -156,6 +169,29 @@ private BundleComponent importProject() throws CoreException, IOException { throw new RuntimeException("Can't import project"); } + private void createOutputFolder(IProject project, IPath projectPath) throws IOException, CoreException { + // FIXME see bug https://github.com/eclipse-pde/eclipse.pde/issues/791 + IJavaProject javaProject = JavaCore.create(project); + if (javaProject != null) { + makeOutputFolder(javaProject.getOutputLocation(), projectPath); + IClasspathEntry[] classpath = javaProject.getRawClasspath(); + for (IClasspathEntry entry : classpath) { + makeOutputFolder(entry.getOutputLocation(), projectPath); + } + } + } + + private void makeOutputFolder(IPath outputLocation, IPath projectPath) throws CoreException, IOException { + if (outputLocation != null) { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IFolder folder = workspace.getRoot().getFolder(outputLocation); + if (!folder.exists()) { + folder.create(true, true, new NullProgressMonitor()); + } + } + + } + private void deleteAllProjects() throws CoreException { for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT | IResource.FORCE, new NullProgressMonitor()); @@ -167,6 +203,8 @@ private void disableAutoBuild() throws CoreException { IWorkspaceDescription desc = workspace.getDescription(); desc.setAutoBuilding(false); workspace.setDescription(desc); + PDECore.getDefault().getPreferencesManager().setValue(ICoreConstants.DISABLE_API_ANALYSIS_BUILDER, false); + PDECore.getDefault().getPreferencesManager().setValue(ICoreConstants.RUN_API_ANALYSIS_AS_JOB, false); } private Properties getPreferences() throws IOException { diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/apitools/ApiToolsTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/apitools/ApiToolsTest.java index d142dca7f2..e484e4cfb5 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/apitools/ApiToolsTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/apitools/ApiToolsTest.java @@ -14,11 +14,12 @@ package org.eclipse.tycho.test.apitools; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; import java.util.List; +import java.util.stream.Collectors; import org.apache.maven.it.VerificationException; import org.apache.maven.it.Verifier; @@ -48,17 +49,36 @@ public void testVerify() throws Exception { File repo = ResourceUtil.resolveTestResource("repositories/api-tools"); verifier.addCliOption("-DbaselineRepo=" + repo.toURI()); - assertThrows("No API errors where detected!", VerificationException.class, - () -> verifier.executeGoals(List.of("clean", "verify"))); - + assertThrows(VerificationException.class, () -> verifier.executeGoals(List.of("clean", "verify")), () -> { + String msg = "No API errors where detected!"; + try { + return msg + System.lineSeparator() + + verifier.loadFile(verifier.getBasedir(), verifier.getLogFileName(), false).stream() + .collect(Collectors.joining(System.lineSeparator())); + } catch (VerificationException e) { + return msg; + } + }); + // check summary output verifier.verifyTextInLog("4 API ERRORS"); verifier.verifyTextInLog("0 API warnings"); - verifier.verifyTextInLog("The type bundle.ApiInterface has been removed from api-bundle"); - verifier.verifyTextInLog("The type bundle.InterfaceA has been removed from api-bundle"); - verifier.verifyTextInLog("The type bundle.ClassA has been removed from api-bundle"); + // check error output has source references and lines verifier.verifyTextInLog( - "The major version should be incremented in version 0.0.1, since API breakage occurred since version 0.0.1"); - + "File ApiInterface.java at line 2: The type bundle.ApiInterface has been removed from api-bundle"); + verifier.verifyTextInLog("File ClassA.java at line 5: The type bundle.ClassA has been removed from api-bundle"); + verifier.verifyTextInLog( + "File MANIFEST.MF at line 0: The type bundle.InterfaceA has been removed from api-bundle"); + verifier.verifyTextInLog( + "File MANIFEST.MF at line 5: The major version should be incremented in version 0.0.1, since API breakage occurred since version 0.0.1"); + // now check for the build error output + verifier.verifyTextInLog("on project api-bundle-1: There are API errors:"); + verifier.verifyTextInLog( + "src/bundle/ApiInterface.java:2 The type bundle.ApiInterface has been removed from api-bundle"); + verifier.verifyTextInLog( + "src/bundle/ClassA.java:5 The type bundle.ClassA has been removed from api-bundle-1_0.0.1"); + verifier.verifyTextInLog("META-INF/MANIFEST.MF:0 The type bundle.InterfaceA has been removed from api-bundle"); + verifier.verifyTextInLog( + "META-INF/MANIFEST.MF:5 The major version should be incremented in version 0.0.1, since API breakage occurred since version 0.0.1"); // TODO: check with api-filter // TODO: check with second plugin with BREE? }