Skip to content

Commit e117328

Browse files
committed
Let PDE compute required packages using a CompilationParticipant
There are some case where the JDT concept of classpath restrictions do not match well the OSGi runtime handling of imported packages these include: - inlined constants are never visible at runtime and therefore no import required and no restriction issue - indirect references through super types are handled by the classpath of the providing bundle and not the consumer - methods inherited from superclasses are also not a problem at all This is now a radical change in how PDE handles the case and detects problems: - instead of using access restrictions that try to emulate the runtime behavior, it computes a full set of transitive classpath items and add them unrestricted (except for internal packages to get warnings there) - then during compilation we dynamically compute the actual set of required imports at runtime - if any of these imports are missing in the manifest we create a problem and suggest suitable quickfix This has the benefit that we are in full control over what is detected, how it is reported and where it is reported. It also gives much more flexibility in improving user experience, for example one might even want to have some "autoimport" feature that is adding /removing packages on demand so do not bother the user with doing this daunting task manually.
1 parent e7b608f commit e117328

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

ui/org.eclipse.pde.core/plugin.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,12 @@
439439
type="Repository">
440440
</targetLocation>
441441
</extension>
442+
<extension
443+
point="org.eclipse.jdt.core.compilationParticipant">
444+
<compilationParticipant
445+
class="org.eclipse.pde.internal.core.builders.PDECompilationParticipant"
446+
id="org.eclipse.pde.core.compilationParticipant"
447+
modifiesEnvironment="false">
448+
</compilationParticipant>
449+
</extension>
442450
</plugin>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.eclipse.pde.internal.core.builders;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
5+
import java.util.Optional;
6+
import java.util.Set;
7+
import java.util.stream.Collectors;
8+
9+
import org.eclipse.core.runtime.IPath;
10+
import org.eclipse.jdt.core.IJavaProject;
11+
import org.eclipse.jdt.core.compiler.BuildContext;
12+
import org.eclipse.jdt.core.compiler.CompilationParticipant;
13+
import org.eclipse.pde.internal.core.bnd.PdeProjectAnalyzer;
14+
import org.eclipse.pde.internal.core.natures.PluginProject;
15+
16+
import aQute.bnd.osgi.Analyzer;
17+
import aQute.bnd.osgi.Descriptors.PackageRef;
18+
import aQute.bnd.osgi.EmbeddedResource;
19+
import aQute.bnd.osgi.Packages;
20+
21+
public class PDECompilationParticipant extends CompilationParticipant {
22+
23+
24+
private ThreadLocal<IJavaProject> project = new ThreadLocal<>();
25+
private ThreadLocal<Analyzer> analyzer = new ThreadLocal<>();
26+
27+
@Override
28+
public int aboutToBuild(IJavaProject project) {
29+
this.project.set(project);
30+
System.out.println(
31+
String.format("---- PDECompilationParticipant.aboutToBuild(%s)", project.getProject().getName())); //$NON-NLS-1$
32+
return READY_FOR_BUILD;
33+
}
34+
35+
@Override
36+
public void buildFinished(IJavaProject project) {
37+
System.out.println(
38+
String.format("---- PDECompilationParticipant.buildFinished(%s)", project.getProject().getName())); //$NON-NLS-1$
39+
this.project.set(null);
40+
try (Analyzer analyzer = this.analyzer.get()) {
41+
if (analyzer != null) {
42+
try {
43+
analyzer.setImportPackage("*"); //$NON-NLS-1$
44+
analyzer.calcManifest();
45+
Packages imports = analyzer.getImports();
46+
if (imports == null) {
47+
System.out.println("No packages computed!");
48+
} else {
49+
Set<String> computedPackages = imports.keySet().stream().map(PackageRef::getFQN)
50+
.collect(Collectors.toSet());
51+
for (String pkg : computedPackages) {
52+
System.out.println(" - " + pkg);
53+
}
54+
}
55+
} catch (Exception e) {
56+
e.printStackTrace();
57+
}
58+
}
59+
} catch (IOException e) {
60+
}
61+
this.analyzer.set(null);
62+
}
63+
64+
@Override
65+
public void buildStarting(BuildContext[] files, boolean isBatch) {
66+
IJavaProject javaProject = project.get();
67+
System.out.println(
68+
String.format("PDECompilationParticipant.buildStarting(%s)", javaProject.getProject().getName())); //$NON-NLS-1$
69+
try {
70+
this.analyzer.set(new PdeProjectAnalyzer(javaProject.getProject(), true));
71+
} catch (Exception e) {
72+
e.printStackTrace();
73+
}
74+
}
75+
76+
@Override
77+
public void cleanStarting(IJavaProject project) {
78+
System.out.println(
79+
String.format("---- PDECompilationParticipant.cleanStarting(%s)", project.getProject().getName())); //$NON-NLS-1$
80+
}
81+
82+
@Override
83+
public boolean isActive(IJavaProject project) {
84+
System.out.println(String.format("PDECompilationParticipant.isActive(%s)", project.getProject().getName())); //$NON-NLS-1$
85+
return PluginProject.isPluginProject(project.getProject());
86+
}
87+
88+
@Override
89+
public boolean isPostProcessor() {
90+
return true;
91+
}
92+
93+
@Override
94+
public Optional<byte[]> postProcess(BuildContext file, ByteArrayInputStream bytes) {
95+
IJavaProject javaProject = project.get();
96+
Analyzer projectAnalyzer = analyzer.get();
97+
IPath projectRelativePath = file.getFile().getProjectRelativePath();
98+
String relativePath = projectRelativePath.toString();
99+
String base = relativePath.substring(javaProject.getProject().getProjectRelativePath().toString().length());
100+
System.out.println(String.format("PDECompilationParticipant.postProcess(%s)", file.getFile())); //$NON-NLS-1$
101+
if (base.startsWith("src/")) {
102+
// TODO build context should supply the binary name
103+
base = base.substring("src/".length());
104+
}
105+
String name = base.replace(".java", ".class");
106+
System.out.println(base);
107+
projectAnalyzer.getJar().putResource(name,
108+
new EmbeddedResource(bytes.readAllBytes(), System.currentTimeMillis()));
109+
return super.postProcess(file, bytes);
110+
}
111+
112+
}

0 commit comments

Comments
 (0)