Patch initializing EmptySubstitutor service and fix null references

There's a cycle in service initialization and PsiSubstitutor 'clinit'
This commit is contained in:
Nikolay Krasko
2019-10-11 18:39:21 +03:00
parent c20bdd3c30
commit 79cb10a755
@@ -30,6 +30,7 @@ import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.util.KeyWithDefaultValue;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
@@ -52,6 +53,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* adapted from com.intellij.core.JavaCoreApplicationEnvironment
* TODO: initiate removal original from com.intellij.core since it seems that there are no usages left
@@ -109,7 +113,14 @@ public class KotlinCoreApplicationEnvironment extends CoreApplicationEnvironment
myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl());
EmptySubstitutorImpl emptySubstitutor = new EmptySubstitutorImpl();
myApplication.registerService(EmptySubstitutor.class, emptySubstitutor);
// Patch null values obtained because of cyclic dependency during initialization
updateInterfaceField(PsiSubstitutor.class, "KEY", KeyWithDefaultValue.create("SUBSTITUTOR", emptySubstitutor));
updateInterfaceField(PsiSubstitutor.class, "EMPTY", emptySubstitutor);
updateInterfaceField(PsiSubstitutor.class, "UNKNOWN", PsiSubstitutor.EMPTY);
myApplication.registerService(JavaDirectoryService.class, createJavaDirectoryService());
myApplication.registerService(JavaVersionService.class, new JavaVersionService());
@@ -147,4 +158,41 @@ public class KotlinCoreApplicationEnvironment extends CoreApplicationEnvironment
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
private static void updateInterfaceField(Class<?> klass, String name, Object value) {
try {
Field field = klass.getDeclaredField(name);
boolean wasAccessible = field.isAccessible();
try {
if (!wasAccessible) {
field.setAccessible(true);
}
Field modifiersField = Field.class.getDeclaredField("modifiers");
int modifiers = field.getModifiers();
try {
modifiersField.setAccessible(true);
modifiersField.setInt(field, modifiers & ~Modifier.FINAL);
field.set(null, value);
}
finally {
modifiersField.setInt(field, modifiers);
modifiersField.setAccessible(false);
}
}
finally {
if (!wasAccessible) {
field.setAccessible(false);
}
}
}
catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}