Skip to content

Commit

Permalink
More tests, fixed parameter indices.
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte committed Dec 20, 2023
1 parent 65ebb80 commit 0be1061
Show file tree
Hide file tree
Showing 15 changed files with 819 additions and 281 deletions.
128 changes: 10 additions & 118 deletions src/main/java/ApplyParchmentToSourceJar.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,4 @@
import com.intellij.core.CoreApplicationEnvironment;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.core.JavaCoreProjectEnvironment;
import com.intellij.lang.jvm.facade.JvmElementProvider;
import com.intellij.mock.MockProject;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionGuardImpl;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.openapi.vfs.impl.ZipHandler;
import com.intellij.pom.java.InternalPersistentJavaLanguageLevelReaderService;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaModuleSystem;
import com.intellij.psi.PsiElementFinder;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiNameHelper;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.PsiElementFinderImpl;
import com.intellij.psi.impl.PsiNameHelperImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessor;
import com.intellij.psi.impl.source.tree.JavaTreeGenerator;
import com.intellij.psi.impl.source.tree.TreeGenerator;
import com.intellij.psi.util.JavaClassSupers;
import modules.CoreJrtFileSystem;
import namesanddocs.NameAndDocSourceLoader;
import namesanddocs.NamesAndDocsDatabase;
import org.jetbrains.annotations.NotNull;
Expand All @@ -49,50 +21,16 @@
*/
public class ApplyParchmentToSourceJar implements AutoCloseable {
private final NamesAndDocsDatabase namesAndDocs;

private final Path tempDir;
private final MockProject project;
private final JavaCoreProjectEnvironment javaEnv;
private final PsiManager psiManager;
private final IntelliJEnvironment ijEnv = new IntelliJEnvironment();
private int maxQueueDepth = 50;
private boolean enableJavadoc = true;
private final Disposable rootDisposable;

public ApplyParchmentToSourceJar(Path javaHome, NamesAndDocsDatabase namesAndDocs) throws IOException {
public ApplyParchmentToSourceJar(NamesAndDocsDatabase namesAndDocs) throws IOException {
this.namesAndDocs = namesAndDocs;
tempDir = Files.createTempDirectory("applyparchment");
this.rootDisposable = Disposer.newDisposable();
System.setProperty("idea.home.path", tempDir.toAbsolutePath().toString());

// IDEA requires a config directory, even if it's empty
PathManager.setExplicitConfigPath(tempDir.toAbsolutePath().toString());
Registry.markAsLoaded(); // Avoids warnings about config not being loaded

var appEnv = new JavaCoreApplicationEnvironment(rootDisposable) {
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
};
initAppExtensionsAndServices(appEnv);

javaEnv = new JavaCoreProjectEnvironment(rootDisposable, appEnv);

ClasspathSetup.addJdkModules(javaHome, javaEnv);

project = javaEnv.getProject();

initProjectExtensionsAndServices(project);

LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(LanguageLevel.JDK_17);

psiManager = PsiManager.getInstance(project);
ijEnv.addCurrentJdkToClassPath();
}


public static void main(String[] args) throws Exception {
System.setProperty("java.awt.headless", "true");

Path inputPath = null, outputPath = null, namesAndDocsPath = null, librariesPath = null;
boolean enableJavadoc = true;
int queueDepth = 50;
Expand Down Expand Up @@ -158,13 +96,10 @@ public static void main(String[] args) throws Exception {

var namesAndDocs = NameAndDocSourceLoader.load(namesAndDocsPath);

// Add the Java Runtime we are currently running in
var javaHome = Paths.get(System.getProperty("java.home"));

try (var applyParchment = new ApplyParchmentToSourceJar(javaHome, namesAndDocs)) {
try (var applyParchment = new ApplyParchmentToSourceJar(namesAndDocs)) {
// Add external libraries to classpath
if (librariesPath != null) {
ClasspathSetup.addLibraries(librariesPath, applyParchment.javaEnv);
ClasspathSetup.addLibraries(librariesPath, applyParchment.ijEnv);
}

applyParchment.setMaxQueueDepth(queueDepth);
Expand All @@ -186,6 +121,8 @@ private static void printUsage(PrintStream out) {

public void apply(Path inputPath, Path outputPath) throws IOException, InterruptedException {

var javaEnv = ijEnv.getProjectEnv();

var sourceJarRoot = javaEnv.getEnvironment().getJarFileSystem().findFileByPath(inputPath + "!/");
if (sourceJarRoot == null) {
throw new FileNotFoundException("Cannot find JAR-File " + inputPath);
Expand Down Expand Up @@ -213,7 +150,7 @@ public void apply(Path inputPath, Path outputPath) throws IOException, Interrupt
}

void addJarToClassPath(Path jarFile) {
javaEnv.addJarToClassPath(jarFile.toFile());
ijEnv.addJarToClassPath(jarFile);
}

byte[] transformSource(VirtualFile contentRoot, String path, byte[] originalContentBytes) {
Expand All @@ -226,7 +163,7 @@ byte[] transformSource(VirtualFile contentRoot, String path, byte[] originalCont
System.err.println("Can't transform " + path + " since IntelliJ doesn't see it in the source jar.");
return originalContentBytes;
}
var psiFile = psiManager.findFile(sourceFile);
var psiFile = ijEnv.getPsiManager().findFile(sourceFile);
if (psiFile == null) {
System.err.println("Can't transform " + path + " since IntelliJ can't load it.");
return originalContentBytes;
Expand Down Expand Up @@ -281,48 +218,6 @@ private static String applyReplacements(CharSequence originalContent, List<Repla
return writer.toString();
}

/*
* When IntelliJ crashes after an update complaining about an extension point or extension not being available,
* check JavaPsiPlugin.xml for the name of that extension point. Then register it as it's defined in the XML
* by hand here.
*
* This method is responsible for anything in the XML that is:
* - A projectService
* - Extension points marked as area="IDEA_PROJECT"
* - Any extensions registered for extension points that are area="IDEA_PROJECT"
*/
private void initProjectExtensionsAndServices(MockProject project) {
project.registerService(PsiNameHelper.class, PsiNameHelperImpl.class);

var projectExtensions = project.getExtensionArea();
CoreApplicationEnvironment.registerExtensionPoint(projectExtensions, PsiTreeChangePreprocessor.EP.getName(), PsiTreeChangePreprocessor.class);
CoreApplicationEnvironment.registerExtensionPoint(projectExtensions, PsiElementFinder.EP.getName(), PsiElementFinder.class);
CoreApplicationEnvironment.registerExtensionPoint(projectExtensions, JvmElementProvider.EP_NAME, JvmElementProvider.class);
PsiElementFinder.EP.getPoint(project).registerExtension(new PsiElementFinderImpl(project), rootDisposable);
}

/*
* When IntelliJ crashes after an update complaining about an extension point or extension not being available,
* check JavaPsiPlugin.xml for the name of that extension point. Then register it as it's defined in the XML
* by hand here.
*
* This method is responsible for anything in the XML that is:
* - An applicationService
* - Extension points not marked as area="IDEA_PROJECT"
* - Any extensions registered for extension points that are not marked area="IDEA_PROJECT"
*/
private void initAppExtensionsAndServices(JavaCoreApplicationEnvironment appEnv) {
// When any service or extension point is missing, check JavaPsiPlugin.xml in classpath and grab the definition
appEnv.registerApplicationService(JavaClassSupers.class, new com.intellij.psi.impl.JavaClassSupersImpl());
appEnv.registerApplicationService(InternalPersistentJavaLanguageLevelReaderService.class, new InternalPersistentJavaLanguageLevelReaderService.DefaultImpl());
appEnv.registerApplicationService(TransactionGuard.class, new TransactionGuardImpl());

var appExtensions = appEnv.getApplication().getExtensionArea();
CoreApplicationEnvironment.registerExtensionPoint(appExtensions, PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
CoreApplicationEnvironment.registerExtensionPoint(appExtensions, JavaModuleSystem.EP_NAME, JavaModuleSystem.class);
CoreApplicationEnvironment.registerExtensionPoint(appExtensions, TreeGenerator.EP_NAME, TreeGenerator.class);
appExtensions.getExtensionPoint(TreeGenerator.EP_NAME).registerExtension(new JavaTreeGenerator(), rootDisposable);
}

public void setMaxQueueDepth(int maxQueueDepth) {
this.maxQueueDepth = maxQueueDepth;
Expand All @@ -334,10 +229,7 @@ public void setEnableJavadoc(boolean enableJavadoc) {

@Override
public void close() throws IOException {
// Releases cached ZipFiles within IntelliJ, allowing the tempdir to be deleted
ZipHandler.clearFileAccessorCache();
Disposer.dispose(rootDisposable);
Files.deleteIfExists(tempDir);
ijEnv.close();
}

}
12 changes: 6 additions & 6 deletions src/main/java/ClasspathSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Properties;

Expand Down Expand Up @@ -59,19 +59,19 @@ public static void addJdkModules(Path jdkHome, JavaCoreProjectEnvironment javaEn
System.out.println("Added " + moduleCount + " modules from " + jdkHome);
}

public static void addLibraries(Path librariesPath, JavaCoreProjectEnvironment javaEnv) throws IOException {
public static void addLibraries(Path librariesPath, IntelliJEnvironment ijEnv) throws IOException {
var libraryFiles = Files.readAllLines(librariesPath)
.stream()
.filter(l -> l.startsWith("-e="))
.map(l -> l.substring(3))
.map(File::new)
.map(Paths::get)
.toList();

for (var libraryFile : libraryFiles) {
if (!libraryFile.exists()) {
throw new UncheckedIOException(new FileNotFoundException(libraryFile.getAbsolutePath()));
if (!Files.exists(libraryFile)) {
throw new UncheckedIOException(new FileNotFoundException(libraryFile.toString()));
}
javaEnv.addJarToClassPath(libraryFile);
ijEnv.addJarToClassPath(libraryFile);
System.out.println("Added " + libraryFile);
}
}
Expand Down
Loading

0 comments on commit 0be1061

Please sign in to comment.