IDEA-29246 Debug with alternative JRE - JDK source is incorrect

This commit is contained in:
Egor.Ushakov
2016-08-24 12:23:31 +03:00
parent 61fe8a8a78
commit 277392251b
8 changed files with 196 additions and 8 deletions
@@ -18,6 +18,7 @@ package com.intellij.debugger;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,6 +37,11 @@ public interface DebugEnvironment {
@NotNull
GlobalSearchScope getSearchScope();
@Nullable
default Sdk getAlternativeJre() {
return null;
}
boolean isRemote();
RemoteConnection getRemoteConnection();
@@ -15,14 +15,17 @@
*/
package com.intellij.debugger;
import com.intellij.debugger.impl.AlternativeJreIndexHelper;
import com.intellij.debugger.impl.DebuggerManagerImpl;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class DefaultDebugEnvironment implements DebugEnvironment {
private final GlobalSearchScope mySearchScope;
@@ -87,4 +90,10 @@ public class DefaultDebugEnvironment implements DebugEnvironment {
public String getSessionName() {
return environment.getRunProfile().getName();
}
@Nullable
@Override
public Sdk getAlternativeJre() {
return AlternativeJreIndexHelper.getAlternativeJre(environment.getRunProfile());
}
}
@@ -20,13 +20,16 @@ import com.intellij.debugger.NoDataException;
import com.intellij.debugger.PositionManager;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.impl.AlternativeJreIndexHelper;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Ref;
@@ -35,8 +38,11 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.compiled.ClsClassImpl;
import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.DocumentUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -351,13 +357,39 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
//}
final String originalQName = refType.name();
final GlobalSearchScope searchScope = myDebugProcess.getSearchScope();
PsiClass psiClass = DebuggerUtils.findClass(originalQName, project, searchScope); // try to lookup original name first
PsiClass psiClass = null;
// first check alternative jre if any
Sdk alternativeJre = myDebugProcess.getSession().getAlternativeJre();
if (alternativeJre != null) {
try {
psiClass = ContainerUtil.getFirstItem(StubIndex.getElements(JavaStubIndexKeys.CLASS_FQN,
originalQName.hashCode(),
project,
AlternativeJreIndexHelper.getSearchScope(alternativeJre),
PsiClass.class));
if (psiClass instanceof ClsClassImpl) { //try to find sources
PsiFile psiSource = findSourceFile((ClsClassImpl)psiClass, alternativeJre);
if (psiSource != null) {
return psiSource;
}
}
}
catch (IndexNotReadyException ignored) {
}
}
if (psiClass == null) {
int dollar = originalQName.indexOf('$');
if (dollar > 0) {
final String qName = originalQName.substring(0, dollar);
psiClass = DebuggerUtils.findClass(qName, project, searchScope);
GlobalSearchScope searchScope = myDebugProcess.getSearchScope();
psiClass = DebuggerUtils.findClass(originalQName, project, searchScope); // try to lookup original name first
if (psiClass == null) {
int dollar = originalQName.indexOf('$');
if (dollar > 0) {
final String qName = originalQName.substring(0, dollar);
psiClass = DebuggerUtils.findClass(qName, project, searchScope);
}
}
}
@@ -393,6 +425,24 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
return null;
}
@Nullable
private static PsiFile findSourceFile(ClsClassImpl psiClass, Sdk alternativeJre) {
String sourceFileName = psiClass.getSourceFileName();
String packageName = ((PsiClassOwner)psiClass.getContainingFile()).getPackageName();
String relativePath = packageName.isEmpty() ? sourceFileName : packageName.replace('.', '/') + '/' + sourceFileName;
for (VirtualFile file : AlternativeJreIndexHelper.getSourceRoots(alternativeJre)) {
VirtualFile source = file.findFileByRelativePath(relativePath);
if (source != null && source.isValid()) {
PsiFile psiSource = psiClass.getManager().findFile(source);
if (psiSource instanceof PsiClassOwner) {
return psiSource;
}
}
}
return null;
}
@NotNull
public List<ReferenceType> getAllClasses(@NotNull final SourcePosition position) throws NoDataException {
return ApplicationManager.getApplication().runReadAction(new Computable<List<ReferenceType>>() {
@@ -0,0 +1,87 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.impl;
import com.intellij.execution.RunManager;
import com.intellij.execution.configurations.ConfigurationWithAlternativeJre;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.NonClasspathDirectoriesScope;
import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.indexing.IndexableSetContributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
/**
* @author egor
*/
public class AlternativeJreIndexHelper extends IndexableSetContributor {
@NotNull
@Override
public Set<VirtualFile> getAdditionalRootsToIndex() {
return Collections.emptySet();
}
@NotNull
@Override
public Set<VirtualFile> getAdditionalProjectRootsToIndex(@NotNull Project project) {
SmartHashSet<VirtualFile> res = new SmartHashSet<>();
for (RunConfiguration configuration : RunManager.getInstance(project).getAllConfigurationsList()) {
Sdk jre = getAlternativeJre(configuration);
if (jre != null) {
res.addAll(getClassRoots(jre));
}
}
return res;
}
@Nullable
public static Sdk getAlternativeJre(RunProfile profile) {
if (profile instanceof ConfigurationWithAlternativeJre) {
ConfigurationWithAlternativeJre appConfig = (ConfigurationWithAlternativeJre)profile;
if (appConfig.isAlternativeJrePathEnabled()) {
return ProjectJdkTable.getInstance().findJdk(appConfig.getAlternativeJrePath());
}
}
return null;
}
@Nullable
private static Collection<VirtualFile> getClassRoots(@NotNull Sdk jre) {
return Arrays.asList(jre.getRootProvider().getFiles(OrderRootType.CLASSES));
}
@NotNull
public static Collection<VirtualFile> getSourceRoots(@NotNull Sdk jre) {
return Arrays.asList(jre.getRootProvider().getFiles(OrderRootType.SOURCES));
}
@Nullable
public static GlobalSearchScope getSearchScope(@NotNull Sdk jre) {
return new NonClasspathDirectoriesScope(getClassRoots(jre));
}
}
@@ -33,7 +33,9 @@ import com.intellij.execution.runners.JavaPatchableProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.indexing.UnindexedFilesUpdater;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
@@ -117,6 +119,11 @@ public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDeb
final DebugProcessImpl debugProcess = debuggerSession.getProcess();
// index alternative jdk if needed
if (AlternativeJreIndexHelper.getAlternativeJre(env.getRunProfile()) != null) {
DumbService.getInstance(debuggerSession.getProject()).queueTask(new UnindexedFilesUpdater(debuggerSession.getProject(), false));
}
return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
@Override
@NotNull
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunConfigurationModule>
implements CommonJavaRunConfigurationParameters, SingleClassConfiguration, RefactoringListenerProvider {
implements CommonJavaRunConfigurationParameters, SingleClassConfiguration, RefactoringListenerProvider, ConfigurationWithAlternativeJre {
public String MAIN_CLASS_NAME;
public String VM_PARAMETERS;
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.configurations;
import org.jetbrains.annotations.Nullable;
/**
* @author egor
*/
public interface ConfigurationWithAlternativeJre {
boolean isAlternativeJrePathEnabled();
@Nullable
String getAlternativeJrePath();
}
+1
View File
@@ -1627,6 +1627,7 @@
<debugger.syntheticProvider implementation="com.intellij.debugger.engine.DefaultSyntheticProvider"/>
<debugger.sourcePositionProvider implementation="com.intellij.debugger.engine.DefaultSourcePositionProvider" order="last"/>
<debugger.sourcePositionHighlighter implementation="com.intellij.debugger.engine.JavaSourcePositionHighlighter"/>
<indexedRootsProvider implementation="com.intellij.debugger.impl.AlternativeJreIndexHelper"/>
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.ColorObjectRenderer"/>
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.ImageObjectRenderer"/>