mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] IDEA-341317 Navigation into multi-release JARs
GitOrigin-RevId: 43612b6950fca72ab58af9b1eb5dc4940f90c501
This commit is contained in:
committed by
intellij-monorepo-bot
parent
de78307927
commit
c74bfa2e57
@@ -33,9 +33,11 @@ import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiElementFinder;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.search.JavaVersionBasedScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
@@ -79,7 +81,8 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
private final String mySessionName;
|
||||
private final DebugProcessImpl myDebugProcess;
|
||||
private final DebugEnvironment myDebugEnvironment;
|
||||
private final GlobalSearchScope mySearchScope;
|
||||
private final GlobalSearchScope myBaseScope;
|
||||
private GlobalSearchScope mySearchScope;
|
||||
private Sdk myAlternativeJre;
|
||||
private final Sdk myRunJre;
|
||||
|
||||
@@ -115,6 +118,7 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
|
||||
public void setAlternativeJre(Sdk sdk) {
|
||||
myAlternativeJre = sdk;
|
||||
updateScope();
|
||||
PsiElementFinder.EP.findExtension(AlternativeJreClassFinder.class, getProject()).clearCache();
|
||||
}
|
||||
|
||||
@@ -215,9 +219,23 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
myDebugProcess.addDebugProcessListener(new MyDebugProcessListener(debugProcess));
|
||||
ValueLookupManager.getInstance(getProject()).startListening();
|
||||
myDebugEnvironment = environment;
|
||||
mySearchScope = environment.getSearchScope();
|
||||
myBaseScope = environment.getSearchScope();
|
||||
myAlternativeJre = environment.getAlternativeJre();
|
||||
myRunJre = environment.getRunJre();
|
||||
updateScope();
|
||||
}
|
||||
|
||||
private void updateScope() {
|
||||
Sdk jre = myAlternativeJre;
|
||||
if (jre == null) jre = myRunJre;
|
||||
GlobalSearchScope scope = myBaseScope;
|
||||
if (jre != null) {
|
||||
LanguageLevel level = LanguageLevel.parse(jre.getVersionString());
|
||||
if (level != null) {
|
||||
scope = new JavaVersionBasedScope(getProject(), scope, level);
|
||||
}
|
||||
}
|
||||
mySearchScope = scope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -278,6 +278,7 @@ dialog.title.0.library.copy=Copy Library
|
||||
dialog.title.0.library.move=Move Library
|
||||
dialog.text.enter.common.prefix=Specify prefix for names of {0} selected modules:
|
||||
class.file.decompiled.text=Decompiled .class file
|
||||
class.file.multi.release.decompiled.text=Decompiled .class file from JDK-{0}-specific root
|
||||
class.file.decompiled.bytecode.version.text=bytecode version: {0}.{1}
|
||||
class.file.decompiled.sdk.version.text=(Java {0})
|
||||
settings.remote.repo.Maven.Repository.URL=maven Repository URL
|
||||
@@ -316,6 +317,7 @@ message.text.creating.deployment.descriptor=Creating Deployment Descriptor
|
||||
modules.order.export.scope.column=Scope
|
||||
choose.modules.dialog.title=Choose Modules
|
||||
class.file.open.source.action=Open source file
|
||||
class.file.open.source.version.specific.action=Open source file from the library root
|
||||
library.java.attach.files.description=Select files or directories in which library classes, sources, documentation or native libraries are located
|
||||
project.roots.project.banner.text=General Settings for Project ''{0}''
|
||||
library.attach.sources.action=Attach Sources
|
||||
|
||||
+34
-8
@@ -41,9 +41,11 @@ import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.compiled.ClsParsingUtil;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.ui.EditorNotificationProvider;
|
||||
import com.intellij.ui.EditorNotifications;
|
||||
@@ -96,13 +98,7 @@ final class AttachSourcesNotificationProvider implements EditorNotificationProvi
|
||||
VirtualFile sourceFile = JavaEditorFileSwapper.findSourceFile(project, file);
|
||||
if (sourceFile != null) {
|
||||
return notificationPanelCreator.andThen(panel -> {
|
||||
panel.createActionLabel(JavaUiBundle.message("class.file.open.source.action"), () -> {
|
||||
if (sourceFile.isValid()) {
|
||||
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, sourceFile);
|
||||
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
}
|
||||
});
|
||||
|
||||
appendOpenFileAction(project, panel, sourceFile, JavaUiBundle.message("class.file.open.source.action"));
|
||||
return panel;
|
||||
});
|
||||
}
|
||||
@@ -113,6 +109,20 @@ final class AttachSourcesNotificationProvider implements EditorNotificationProvi
|
||||
}
|
||||
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
|
||||
if (psiFile != null) {
|
||||
PsiFile baseFile = JavaMultiReleaseUtil.findBaseFile(psiFile);
|
||||
if (baseFile != null) {
|
||||
VirtualFile baseSource = JavaEditorFileSwapper.findSourceFile(project, baseFile.getVirtualFile());
|
||||
if (baseSource != null) {
|
||||
return notificationPanelCreator.andThen(panel -> {
|
||||
appendOpenFileAction(project, panel, baseSource, JavaUiBundle.message("class.file.open.source.version.specific.action"));
|
||||
return panel;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<? extends AttachSourcesProvider.AttachSourcesAction> actionsByFile = psiFile != null ?
|
||||
collectActions(libraries, psiFile) :
|
||||
List.of();
|
||||
@@ -148,6 +158,16 @@ final class AttachSourcesNotificationProvider implements EditorNotificationProvi
|
||||
});
|
||||
}
|
||||
|
||||
private static void appendOpenFileAction(@NotNull Project project, EditorNotificationPanel panel, VirtualFile sourceFile,
|
||||
@NotNull @Nls String title) {
|
||||
panel.createActionLabel(title, () -> {
|
||||
if (sourceFile.isValid()) {
|
||||
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, sourceFile);
|
||||
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("IncorrectParentDisposable")
|
||||
@RequiresEdt
|
||||
private static void findLibraryEntriesForFile(@NotNull Project project,
|
||||
@@ -208,7 +228,13 @@ final class AttachSourcesNotificationProvider implements EditorNotificationProvi
|
||||
|
||||
@RequiresBackgroundThread
|
||||
private static @NotNull @NlsContexts.Label String getTextWithClassFileInfo(@NotNull VirtualFile file) {
|
||||
@Nls StringBuilder info = new StringBuilder(JavaUiBundle.message("class.file.decompiled.text"));
|
||||
LanguageLevel level = JavaMultiReleaseUtil.getVersion(file);
|
||||
@Nls StringBuilder info = new StringBuilder();
|
||||
if (level != null) {
|
||||
info.append(JavaUiBundle.message("class.file.multi.release.decompiled.text", level.toJavaVersion().feature));
|
||||
} else {
|
||||
info.append(JavaUiBundle.message("class.file.decompiled.text"));
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] data = file.contentsToByteArray(false);
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<resolveScopeProvider implementation="com.intellij.psi.impl.file.impl.JavaOutOfSourcesResolveScopeProvider"/>
|
||||
<resolveScopeProvider implementation="com.intellij.psi.impl.file.impl.JavaResolveScopeProvider"/>
|
||||
<highlightingPassFactory implementation="com.intellij.codeInsight.daemon.impl.JavaTextBlockIndentPassFactory"/>
|
||||
<deadCode implementation="com.intellij.codeInspection.java19modules.Java9ModuleEntryPoint"/>
|
||||
<metaLanguage implementation="com.intellij.uast.UastMetaLanguage"/>
|
||||
|
||||
+11
-4
@@ -28,6 +28,7 @@ import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -119,10 +120,13 @@ public final class JavaFileManagerImpl implements JavaFileManager, Disposable {
|
||||
private boolean hasAcceptablePackage(@NotNull VirtualFile vFile) {
|
||||
if (FileTypeRegistry.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) {
|
||||
// See IDEADEV-5626
|
||||
VirtualFile root = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex().getClassRootForFile(vFile);
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex();
|
||||
boolean checkMultiRelease = index.isInLibrary(vFile);
|
||||
VirtualFile root = index.getClassRootForFile(vFile);
|
||||
VirtualFile parent = vFile.getParent();
|
||||
PsiNameHelper nameHelper = PsiNameHelper.getInstance(myManager.getProject());
|
||||
while (parent != null && !Comparing.equal(parent, root)) {
|
||||
while (parent != null && !Comparing.equal(parent, root) &&
|
||||
(!checkMultiRelease || JavaMultiReleaseUtil.getVersionForVersionRoot(root, parent) == null)) {
|
||||
if (!nameHelper.isIdentifier(parent.getName())) return false;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
@@ -211,8 +215,11 @@ public final class JavaFileManagerImpl implements JavaFileManager, Disposable {
|
||||
}
|
||||
|
||||
private static Collection<PsiJavaModule> upgradeModules(Collection<PsiJavaModule> modules, String moduleName, GlobalSearchScope scope) {
|
||||
if (modules.size() > 1 && PsiJavaModule.UPGRADEABLE.contains(moduleName) && scope instanceof ModuleWithDependenciesScope) {
|
||||
Module module = ((ModuleWithDependenciesScope)scope).getModule();
|
||||
if (scope instanceof DelegatingGlobalSearchScope delegatingScope) {
|
||||
scope = delegatingScope.unwrap();
|
||||
}
|
||||
if (modules.size() > 1 && PsiJavaModule.UPGRADEABLE.contains(moduleName) && scope instanceof ModuleWithDependenciesScope moduleScope) {
|
||||
Module module = moduleScope.getModule();
|
||||
boolean isModular = Stream.of(ModuleRootManager.getInstance(module).getSourceRoots(true))
|
||||
.filter(scope::contains)
|
||||
.anyMatch(root -> root.findChild(PsiJavaModule.MODULE_INFO_FILE) != null);
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.file.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.ResolveScopeProvider;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Limited resolve scope for all java files in module content, but not under source roots.
|
||||
* For example, java files from test data.
|
||||
* There is still a possibility to modify this scope choice with the ResolveScopeEnlarger.
|
||||
*/
|
||||
public final class JavaOutOfSourcesResolveScopeProvider extends ResolveScopeProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
// For java only! For other languages resolve may be implemented with different rules, requiring larger scope.
|
||||
FileType type = file.getFileType();
|
||||
if (type instanceof LanguageFileType && ((LanguageFileType)type).getLanguage() == JavaLanguage.INSTANCE) {
|
||||
ProjectFileIndex index = project.isDefault() ? null : ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (index == null) {
|
||||
return GlobalSearchScope.fileScope(project, file);
|
||||
}
|
||||
if (index.isInContent(file) && !index.isInSource(file)) {
|
||||
PsiFile psi = PsiManager.getInstance(project).findFile(file);
|
||||
if (psi == null || !JavaHighlightUtil.isJavaHashBangScript(psi)) {
|
||||
return GlobalSearchScope.fileScope(project, file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.file.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
|
||||
import com.intellij.ide.highlighter.JavaClassFileType;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.module.LanguageLevelUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.TestSourcesFilter;
|
||||
import com.intellij.openapi.roots.impl.LibraryScopeCache;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.ResolveScopeProvider;
|
||||
import com.intellij.psi.impl.search.JavaVersionBasedScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class JavaResolveScopeProvider extends ResolveScopeProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
// For java only! For other languages resolve may be implemented with different rules, requiring larger scope.
|
||||
FileType type = file.getFileType();
|
||||
if (type instanceof LanguageFileType langType && langType.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
ProjectFileIndex index = project.isDefault() ? null : ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (index == null) {
|
||||
return GlobalSearchScope.fileScope(project, file);
|
||||
}
|
||||
if (index.isInContent(file) && !index.isInSource(file)) {
|
||||
// Limited resolve scope for all java files in module content, but not under source roots.
|
||||
// For example, java files from test data.
|
||||
// There is still a possibility to modify this scope choice with the ResolveScopeEnlarger.
|
||||
PsiFile psi = PsiManager.getInstance(project).findFile(file);
|
||||
if (psi == null || !JavaHighlightUtil.isJavaHashBangScript(psi)) {
|
||||
return GlobalSearchScope.fileScope(project, file);
|
||||
}
|
||||
}
|
||||
Module module = index.getModuleForFile(file);
|
||||
if (module != null) {
|
||||
// Specify preferred language level to support multi-release Jars
|
||||
LanguageLevel level = LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
boolean includeTests = TestSourcesFilter.isTestSources(file, project);
|
||||
GlobalSearchScope baseScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests);
|
||||
return new JavaVersionBasedScope(project, baseScope, level);
|
||||
}
|
||||
if (file instanceof LightVirtualFile) {
|
||||
PsiFile psi = PsiManager.getInstance(project).findFile(file);
|
||||
if (psi != null) {
|
||||
PsiFile originalFile = psi.getOriginalFile();
|
||||
if (originalFile != psi && originalFile.getFileType().equals(JavaClassFileType.INSTANCE)) {
|
||||
return getClassFileScope(originalFile.getVirtualFile(), project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type.equals(JavaClassFileType.INSTANCE)) {
|
||||
return getClassFileScope(file, project);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JavaVersionBasedScope getClassFileScope(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
ProjectFileIndex index = project.isDefault() ? null : ProjectRootManager.getInstance(project).getFileIndex();
|
||||
LanguageLevel level = JavaMultiReleaseUtil.getVersion(file);
|
||||
if (level != null && index != null) {
|
||||
GlobalSearchScope baseScope = LibraryScopeCache.getInstance(project).getLibraryScope(index.getOrderEntriesForFile(file));
|
||||
return new JavaVersionBasedScope(project, baseScope, level);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ implicit.class.context.display=Implicit class
|
||||
anonymous.class.context.display=Anonymous in {0}
|
||||
anonymous.class.derived.display=Anonymous class derived from {0}
|
||||
aux.context.display=of {0}
|
||||
class.file.version=ver. {0}
|
||||
bound.not.expected=Unexpected bound
|
||||
catch.without.try='catch' without 'try'
|
||||
class.context.display={0} in {1}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.intellij.psi.impl.source.javadoc.PsiSnippetAttributeValueImpl;
|
||||
import com.intellij.psi.javadoc.PsiSnippetAttributeValue;
|
||||
import com.intellij.psi.javadoc.PsiSnippetDocTagValue;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
@@ -125,7 +126,24 @@ public final class JavaPsiImplementationHelperImpl extends JavaPsiImplementation
|
||||
String sourceFileName = ((ClsClassImpl)classes[0]).getSourceFileName();
|
||||
String packageName = clsFile.getPackageName();
|
||||
String relativePath = packageName.isEmpty() ? sourceFileName : packageName.replace('.', '/') + '/' + sourceFileName;
|
||||
finder = root -> root.findFileByRelativePath(relativePath);
|
||||
LanguageLevel level = JavaMultiReleaseUtil.getVersion(clsFile);
|
||||
if (level == null) {
|
||||
finder = root -> root.findFileByRelativePath(relativePath);
|
||||
}
|
||||
else {
|
||||
// Multi-release jar: assume that source file is placed in META-INF/versions/<ver>
|
||||
// fallback to default location only if there's no the same file in the root
|
||||
PsiFile baseFile = JavaMultiReleaseUtil.findBaseFile(clsFile);
|
||||
String versionPath = "META-INF/versions/" + level.toJavaVersion().feature + "/" + relativePath;
|
||||
if (baseFile != null) {
|
||||
finder = root -> root.findFileByRelativePath(versionPath);
|
||||
} else {
|
||||
finder = root -> {
|
||||
VirtualFile target = root.findFileByRelativePath(versionPath);
|
||||
return target == null ? root.findFileByRelativePath(relativePath) : target;
|
||||
};
|
||||
}
|
||||
}
|
||||
filter = PsiClassOwner.class::isInstance;
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public final class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaM
|
||||
}
|
||||
|
||||
public Collection<PsiJavaModule> getModules(@NotNull String name, @NotNull Project project, @NotNull GlobalSearchScope scope) {
|
||||
Collection<PsiJavaModule> modules = StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope, true), PsiJavaModule.class);
|
||||
Collection<PsiJavaModule> modules = StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope), PsiJavaModule.class);
|
||||
if (modules.size() > 1) {
|
||||
modules = filterVersions(project, modules);
|
||||
}
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public final class JavaFunctionalExpressionSearcher extends QueryExecutorBase<Ps
|
||||
MultiMap<VirtualFile, FunExprOccurrence> result = MultiMap.createLinkedSet();
|
||||
descriptors.get(0).dumbService.runReadActionInSmartMode(() -> {
|
||||
for (SamDescriptor descriptor : descriptors) {
|
||||
GlobalSearchScope scope = new JavaSourceFilterScope(descriptor.effectiveUseScope, false, true);
|
||||
GlobalSearchScope scope = new JavaSourceFilterScope(descriptor.effectiveUseScope, true);
|
||||
for (FunctionalExpressionKey key : descriptor.keys) {
|
||||
FileBasedIndex.getInstance().processValues(JavaFunctionalExpressionIndex.INDEX_ID, key, null, (file, infos) -> {
|
||||
result.putValues(file, ContainerUtil.map(infos, entry -> entry.occurrence));
|
||||
|
||||
+2
-23
@@ -6,7 +6,6 @@ import com.intellij.openapi.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -16,27 +15,21 @@ import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
|
||||
|
||||
public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
|
||||
private final @Nullable ProjectFileIndex myIndex;
|
||||
private final boolean myIncludeVersions;
|
||||
private final boolean myIncludeLibrarySources;
|
||||
|
||||
public JavaSourceFilterScope(@NotNull GlobalSearchScope delegate) {
|
||||
this(delegate, false);
|
||||
}
|
||||
|
||||
public JavaSourceFilterScope(@NotNull GlobalSearchScope delegate, boolean includeVersions) {
|
||||
this(delegate, includeVersions, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, the scope excludes version-specific classes of multi-release .jar files
|
||||
* (i.e. *.class files located under META-INF/versions/ directory).
|
||||
* Setting {@code includeVersions} parameter to {@code true} allows such files to pass the filter.
|
||||
*/
|
||||
public JavaSourceFilterScope(@NotNull GlobalSearchScope delegate, boolean includeVersions, boolean includeLibrarySources) {
|
||||
public JavaSourceFilterScope(@NotNull GlobalSearchScope delegate, boolean includeLibrarySources) {
|
||||
super(delegate);
|
||||
Project project = getProject();
|
||||
myIndex = project == null ? null : ProjectRootManager.getInstance(project).getFileIndex();
|
||||
myIncludeVersions = includeVersions;
|
||||
myIncludeLibrarySources = includeLibrarySources;
|
||||
}
|
||||
|
||||
@@ -51,24 +44,10 @@ public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
|
||||
}
|
||||
|
||||
if (FileTypeRegistry.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) {
|
||||
return myIndex.isInLibraryClasses(file) && (myIncludeVersions || !isVersioned(file, myIndex));
|
||||
return myIndex.isInLibraryClasses(file);
|
||||
}
|
||||
|
||||
return myIndex.isUnderSourceRootOfType(file, JavaModuleSourceRootTypes.SOURCES) ||
|
||||
(myIncludeLibrarySources || myBaseScope.isForceSearchingInLibrarySources()) && myIndex.isInLibrarySource(file);
|
||||
}
|
||||
|
||||
private static boolean isVersioned(VirtualFile file, ProjectFileIndex index) {
|
||||
VirtualFile root = index.getClassRootForFile(file);
|
||||
while ((file = file.getParent()) != null && !file.equals(root)) {
|
||||
if (Comparing.equal(file.getNameSequence(), "versions")) {
|
||||
VirtualFile parent = file.getParent();
|
||||
if (parent != null && Comparing.equal(parent.getNameSequence(), "META-INF")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A scope decorator that allows to prefer a particular Java class version from multi-release Jar dependencies
|
||||
*/
|
||||
public final class JavaVersionBasedScope extends DelegatingGlobalSearchScope {
|
||||
private final ProjectFileIndex myProjectFileIndex;
|
||||
private final LanguageLevel myLevel;
|
||||
|
||||
public JavaVersionBasedScope(@NotNull Project project,
|
||||
@NotNull GlobalSearchScope baseScope,
|
||||
@NotNull LanguageLevel desiredLevel) {
|
||||
super(project, baseScope);
|
||||
myProjectFileIndex = ProjectFileIndex.getInstance(project);
|
||||
// Set desired level to Java 8 if it's less than Java 8, to make all these scopes equal, so they could be deduplicated
|
||||
myLevel = desiredLevel.isLessThan(JavaMultiReleaseUtil.MIN_MULTI_RELEASE_VERSION)
|
||||
? JavaMultiReleaseUtil.MAX_NON_MULTI_RELEASE_VERSION
|
||||
: desiredLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull VirtualFile file) {
|
||||
if (!super.contains(file)) return false;
|
||||
VirtualFile baseFile = JavaMultiReleaseUtil.findBaseFile(file);
|
||||
if (myLevel.isLessThan(JavaMultiReleaseUtil.MIN_MULTI_RELEASE_VERSION)) {
|
||||
// In pre-multi-release
|
||||
return baseFile == null;
|
||||
}
|
||||
if (baseFile == null) {
|
||||
baseFile = file;
|
||||
}
|
||||
VirtualFile specificFile = JavaMultiReleaseUtil.findVersionSpecificFile(baseFile, myLevel);
|
||||
return file.equals(specificFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
JavaVersionBasedScope scope = (JavaVersionBasedScope)o;
|
||||
return myLevel == scope.myLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + Objects.hashCode(myLevel);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Java " + myLevel.toJavaVersion().feature + " @ " + myBaseScope;
|
||||
}
|
||||
}
|
||||
+6
@@ -9,9 +9,11 @@ import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassOwner;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.JavaMultiReleaseUtil;
|
||||
import com.intellij.ui.NewUiValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -34,6 +36,10 @@ public final class ClassPresentationProvider implements ItemPresentationProvider
|
||||
PsiClassOwner classOwner = (PsiClassOwner)file;
|
||||
String packageName = classOwner.getPackageName();
|
||||
if (packageName.isEmpty()) return null;
|
||||
LanguageLevel version = JavaMultiReleaseUtil.getVersion(file);
|
||||
if (version != null) {
|
||||
packageName += "/" + JavaPsiBundle.message("class.file.version", version.toJavaVersion().feature);
|
||||
}
|
||||
return NewUiValue.isEnabled() ? JavaPsiBundle.message("aux.context.display", packageName) : "(" + packageName + ")";
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.ide.highlighter.ArchiveFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Utility methods to support Multi-Release JARs (MR-JARs, <a href="https://openjdk.org/jeps/238">JEP 238</a>)
|
||||
*/
|
||||
public final class JavaMultiReleaseUtil {
|
||||
|
||||
/**
|
||||
* Maximal JDK version which does not support multi-release Jars
|
||||
*/
|
||||
public static final LanguageLevel MAX_NON_MULTI_RELEASE_VERSION = LanguageLevel.JDK_1_8;
|
||||
/**
|
||||
* Minimal JDK version which supports multi-release Jars
|
||||
*/
|
||||
public static final LanguageLevel MIN_MULTI_RELEASE_VERSION = LanguageLevel.JDK_1_9;
|
||||
|
||||
private static class VersionRootInfo {
|
||||
final @NotNull LanguageLevel level;
|
||||
final @NotNull VirtualFile versionRoot;
|
||||
final @NotNull VirtualFile classRoot;
|
||||
|
||||
private VersionRootInfo(@NotNull LanguageLevel level, @NotNull VirtualFile versionRoot, @NotNull VirtualFile classRoot) {
|
||||
this.level = level;
|
||||
this.versionRoot = versionRoot;
|
||||
this.classRoot = classRoot;
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable VersionRootInfo getVersionRootInfo(@NotNull VirtualFile file) {
|
||||
VirtualFile root = VfsUtilCore.getRootFile(file);
|
||||
if (!(root.getFileType() instanceof ArchiveFileType)) return null;
|
||||
|
||||
VirtualFile parent = file.getParent();
|
||||
while (parent != null && !parent.equals(root)) {
|
||||
LanguageLevel level = getVersionForVersionRoot(root, parent);
|
||||
if (level != null) {
|
||||
return new VersionRootInfo(level, parent, root);
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link LanguageLevel} that corresponds to the specified version root directory, relative to the specified root.
|
||||
* Version root directory is something like {@code META_INF/versions/9}
|
||||
* @param root root directory (the root of the JAR file)
|
||||
* @param directory version root directory
|
||||
* @return the {@link LanguageLevel} that corresponds to the specified version root directory. E.g., {@link LanguageLevel#JDK_1_9}
|
||||
* for {@code META_INF/versions/9}. Returns null if either root or directory is null, or the specified directory is not a
|
||||
* version root.
|
||||
*/
|
||||
@Contract("null, _ -> null; !null, null -> null")
|
||||
public static @Nullable LanguageLevel getVersionForVersionRoot(@Nullable VirtualFile root, @Nullable VirtualFile directory) {
|
||||
if (root == null || directory == null) return null;
|
||||
VirtualFile parent = directory.getParent();
|
||||
if (parent == null) return null;
|
||||
if (parent.getName().equals("versions")) {
|
||||
VirtualFile grandParent = parent.getParent();
|
||||
if (grandParent != null && grandParent.getName().equals("META-INF") && root.equals(grandParent.getParent())) {
|
||||
try {
|
||||
LanguageLevel level = LanguageLevel.forFeature(Integer.parseInt(directory.getName()));
|
||||
return level != null && level.isAtLeast(MIN_MULTI_RELEASE_VERSION) ? level : null;
|
||||
}
|
||||
catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param psiFile a PSI file that represents a version-specific file from an MR-JAR
|
||||
* @return a file representing the same class or resource from the JAR root; null if there's no corresponding resource in the JAR root,
|
||||
* or if the supplied file is not a version-specific file from an MR-JAR
|
||||
*/
|
||||
public static @Nullable PsiFile findBaseFile(@NotNull PsiFile psiFile) {
|
||||
VirtualFile file = psiFile.getVirtualFile();
|
||||
if (file == null) return null;
|
||||
Project project = psiFile.getProject();
|
||||
if (project.isDefault()) return null;
|
||||
VirtualFile target = findBaseFile(file);
|
||||
if (target == null) return null;
|
||||
return psiFile.getManager().findFile(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file virtual file that represents a version-specific file from an MR-JAR
|
||||
* @return a file representing the same class or resource from the JAR root; null if there's no corresponding resource in the JAR root,
|
||||
* or if the supplied file is not a version-specific file from an MR-JAR
|
||||
*/
|
||||
public static @Nullable VirtualFile findBaseFile(@NotNull VirtualFile file) {
|
||||
VersionRootInfo info = getVersionRootInfo(file);
|
||||
if (info == null) return null;
|
||||
VirtualFile versionRoot = info.versionRoot;
|
||||
VirtualFile classRoot = info.classRoot;
|
||||
String relativePath = VfsUtilCore.getRelativePath(file, versionRoot);
|
||||
if (relativePath == null) return null;
|
||||
return classRoot.findFileByRelativePath(relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file file that represents a non-version-specific file from an MR-JAR
|
||||
* @param level desired language level
|
||||
* @return a version of the file, which should be loaded on the specified language level. Returns
|
||||
* input file if there's no more-specific version of the file, or the input file is not located inside MR-JAR.
|
||||
*/
|
||||
public static @NotNull VirtualFile findVersionSpecificFile(@NotNull VirtualFile file, @NotNull LanguageLevel level) {
|
||||
VirtualFile root = VfsUtilCore.getRootFile(file);
|
||||
if (!(root.getFileType() instanceof ArchiveFileType)) return file;
|
||||
String relativePath = VfsUtilCore.getRelativePath(file, root);
|
||||
if (relativePath == null) return file;
|
||||
VirtualFile versions = root.findFileByRelativePath("META-INF/versions");
|
||||
if (versions == null) return file;
|
||||
int feature = level.toJavaVersion().feature;
|
||||
int minFeature = MIN_MULTI_RELEASE_VERSION.toJavaVersion().feature;
|
||||
while (feature >= minFeature) {
|
||||
VirtualFile versionRoot = versions.findChild(String.valueOf(feature));
|
||||
if (versionRoot != null) {
|
||||
VirtualFile target = versionRoot.findFileByRelativePath(relativePath);
|
||||
if (target != null) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
feature--;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param file PsiFile that represents a version-specific file from library
|
||||
* @return a version that corresponds for a specified file (e.g. {@link LanguageLevel#JDK_1_9} for a file from {@code META-INF/versions/9});
|
||||
* null if the given file is not a version-specific file from a library, or a corresponding version is not supported by current IDE.
|
||||
*/
|
||||
public static @Nullable LanguageLevel getVersion(@NotNull PsiFile file) {
|
||||
return getVersion(file.getVirtualFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file VirtualFile that represents a version-specific file from MR-JAR
|
||||
* @return a version that corresponds for a specified file (e.g. {@link LanguageLevel#JDK_1_9} for a file from {@code META-INF/versions/9});
|
||||
* null if the given file is not a version-specific file from a library, or a corresponding version is not supported by current IDE.
|
||||
*/
|
||||
public static @Nullable LanguageLevel getVersion(@NotNull VirtualFile file) {
|
||||
VersionRootInfo version = getVersionRootInfo(file);
|
||||
return version == null ? null : version.level;
|
||||
}
|
||||
}
|
||||
+131
-10
@@ -4,16 +4,21 @@ package com.intellij.java.codeInsight.daemon
|
||||
import com.intellij.codeInsight.completion.CompletionType
|
||||
import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiJavaReference
|
||||
import com.intellij.psi.impl.search.JavaVersionBasedScope
|
||||
import com.intellij.psi.search.FilenameIndex
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.intellij.psi.stubs.StubUpdatingIndex
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
||||
private const val CLASS_NAME = "com.example.MultiReleaseClass"
|
||||
|
||||
class MultiReleaseJarTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
private lateinit var scope: GlobalSearchScope
|
||||
|
||||
@@ -28,26 +33,132 @@ class MultiReleaseJarTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
}
|
||||
|
||||
fun testResolve() {
|
||||
myFixture.configureByText("a.java", "import com.example.*;\nclass a { <caret>MultiReleaseClass f; }")
|
||||
assertUnversioned((myFixture.getReferenceAtCaretPosition() as PsiJavaReference).multiResolve(false).map { it.element })
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_8) {
|
||||
myFixture.configureByText("a.java", "import com.example.*;\nclass a { <caret>MultiReleaseClass f; }")
|
||||
assertUnversioned((myFixture.getReferenceAtCaretPosition() as PsiJavaReference).multiResolve(false).map { it.element })
|
||||
}
|
||||
}
|
||||
|
||||
fun testResolve9() {
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_9) {
|
||||
myFixture.configureByText("a.java", "import com.example.*;\nclass a { <caret>MultiReleaseClass f; }")
|
||||
assertVersioned((myFixture.getReferenceAtCaretPosition() as PsiJavaReference).multiResolve(false).map { it.element })
|
||||
}
|
||||
}
|
||||
|
||||
fun testCompletion() {
|
||||
myFixture.configureByText("a.java", "class a { MultiReleaseClass<caret> f; }")
|
||||
assertUnversioned(myFixture.complete(CompletionType.BASIC).map { it.psiElement })
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_8) {
|
||||
myFixture.configureByText("a.java", "class a { MultiReleaseClass<caret> f; }")
|
||||
assertUnversioned(myFixture.complete(CompletionType.BASIC).map { it.psiElement })
|
||||
}
|
||||
}
|
||||
|
||||
fun testFindClassByFullName() =
|
||||
assertUnversioned(myFixture.javaFacade.findClass("com.example.MultiReleaseClass", scope))
|
||||
fun testCompletion9() {
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_9) {
|
||||
myFixture.configureByText("a.java", "class a { MultiReleaseClass<caret> f; }")
|
||||
assertVersioned(myFixture.complete(CompletionType.BASIC).map { it.psiElement })
|
||||
}
|
||||
}
|
||||
|
||||
fun testFindClassByShortName() =
|
||||
assertUnversioned(PsiShortNamesCache.getInstance(project).getClassesByName("MultiReleaseClass", scope).toList())
|
||||
fun testCompletionMethod() {
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_8) {
|
||||
myFixture.configureByText("a.java", """
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("jav<caret>");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.complete(CompletionType.BASIC)
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult("""
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("jav" +
|
||||
"");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
fun testCompletionMethod9() {
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_1_9) {
|
||||
myFixture.configureByText("a.java", """
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("jav<caret>");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.complete(CompletionType.BASIC)
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult("""
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("multiReleaseJava9Impl");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
fun testCompletionMethod11() {
|
||||
IdeaTestUtil.withLevel(module, LanguageLevel.JDK_11) {
|
||||
myFixture.configureByText("a.java", """
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("jav<caret>");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.complete(CompletionType.BASIC)
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult("""
|
||||
import com.example.MultiReleaseClass;
|
||||
class a {
|
||||
Object test() {
|
||||
return MultiReleaseClass.class.getDeclaredMethod("multiReleaseJava10Impl");
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
fun testFindClassByFullName() {
|
||||
assertUnversioned(myFixture.javaFacade.findClass(CLASS_NAME, scope8()))
|
||||
assertVersioned(myFixture.javaFacade.findClass(CLASS_NAME, scope9()))
|
||||
}
|
||||
|
||||
fun testClassPresentation() {
|
||||
assertEquals("(com.example)", myFixture.javaFacade.findClass(CLASS_NAME, scope8())!!.presentation!!.locationString)
|
||||
assertEquals("(com.example/ver. 9)", myFixture.javaFacade.findClass(CLASS_NAME, scope9())!!.presentation!!.locationString)
|
||||
assertEquals("(com.example/ver. 10)", myFixture.javaFacade.findClass(CLASS_NAME, scope10())!!.presentation!!.locationString)
|
||||
}
|
||||
|
||||
fun testFindClassByShortName() {
|
||||
assertUnversioned(PsiShortNamesCache.getInstance(project).getClassesByName("MultiReleaseClass", scope8()).toList())
|
||||
assertVersioned(PsiShortNamesCache.getInstance(project).getClassesByName("MultiReleaseClass", scope9()).toList())
|
||||
assertVersioned(PsiShortNamesCache.getInstance(project).getClassesByName("MultiReleaseClass", scope10()).toList())
|
||||
}
|
||||
|
||||
fun testFindMethod() {
|
||||
assertUnversioned(PsiShortNamesCache.getInstance(project).getMethodsByName("multiReleaseDefaultImpl", scope).toList())
|
||||
assertThat(PsiShortNamesCache.getInstance(project).getMethodsByName("multiReleaseJava9Impl", scope)).isEmpty()
|
||||
assertUnversioned(PsiShortNamesCache.getInstance(project).getMethodsByName("multiReleaseDefaultImpl", scope8()).toList())
|
||||
assertThat(PsiShortNamesCache.getInstance(project).getMethodsByName("multiReleaseJava9Impl", scope8())).isEmpty()
|
||||
assertVersioned(PsiShortNamesCache.getInstance(project).getMethodsByName("multiReleaseJava9Impl", scope9()).toList())
|
||||
}
|
||||
|
||||
private fun scope8() = JavaVersionBasedScope(project, scope, LanguageLevel.JDK_1_8)
|
||||
|
||||
private fun scope9() = JavaVersionBasedScope(project, scope, LanguageLevel.JDK_1_9)
|
||||
|
||||
private fun scope10() = JavaVersionBasedScope(project, scope, LanguageLevel.JDK_10)
|
||||
|
||||
fun testFindFile() {
|
||||
assertThat(getAllAvailableVersionClasses()).hasSize(3)
|
||||
}
|
||||
@@ -72,4 +183,14 @@ class MultiReleaseJarTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
assertThat(element).isNotNull
|
||||
assertThat(element!!.containingFile.virtualFile.path).doesNotContain("/META-INF/versions/")
|
||||
}
|
||||
|
||||
private fun assertVersioned(elements: List<PsiElement?>) {
|
||||
assertThat(elements).hasSize(1)
|
||||
assertVersioned(elements[0])
|
||||
}
|
||||
|
||||
private fun assertVersioned(element: PsiElement?) {
|
||||
assertThat(element).isNotNull
|
||||
assertThat(element!!.containingFile.virtualFile.path).contains("/META-INF/versions/")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user