Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/java/debugger/openapi/debugger-openapi.iml b/java/debugger/openapi/debugger-openapi.iml
new file mode 100644
index 0000000..52013f3
--- /dev/null
+++ b/java/debugger/openapi/debugger-openapi.iml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="execution-openapi" />
+ <orderEntry type="module" module-name="jsp-openapi" />
+ <orderEntry type="module" module-name="java-psi-api" />
+ <orderEntry type="module" module-name="resources-en" />
+ </component>
+ <component name="copyright">
+ <Base>
+ <setting name="state" value="0" />
+ </Base>
+ <LanguageOptions name="HTML">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright (c) &#36;today.year, Your Corporation. All Rights Reserved." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="JAVA">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="/* * Copyright 2000-2005 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. */" />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="JSP">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright (c) &#36;today.year, Your Corporation. All Rights Reserved." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="JavaScript">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright (c) &#36;today.year, Your Corporation. All Rights Reserved." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="Properties">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright (c) &#36;today.year, Your Corporation. All Rights Reserved." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="XML">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright (c) &#36;today.year, Your Corporation. All Rights Reserved." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="2" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ <LanguageOptions name="__TEMPLATE__">
+ <option name="templateOptions">
+ <value>
+ <option name="block" value="true" />
+ <option name="separateBefore" value="false" />
+ <option name="separateAfter" value="false" />
+ <option name="prefixLines" value="true" />
+ <option name="lenBefore" value="80" />
+ <option name="lenAfter" value="80" />
+ <option name="box" value="false" />
+ <option name="filler" value=" " />
+ </value>
+ </option>
+ <option name="notice" value="Copyright 2000-&#36;{today.year} 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." />
+ <option name="keyword" value="Copyright" />
+ <option name="fileTypeOverride" value="4" />
+ <option name="relativeBefore" value="true" />
+ <option name="addBlankAfter" value="true" />
+ <option name="fileLocation" value="1" />
+ <option name="useAlternate" value="false" />
+ </LanguageOptions>
+ </component>
+</module>
+
diff --git a/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java b/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java
new file mode 100644
index 0000000..179cf4a
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.CommonBundle;
+import com.intellij.execution.configurations.RemoteConnection;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+public class DebuggerBundle {
+ private static Reference<ResourceBundle> ourBundle;
+
+ @NonNls private static final String BUNDLE = "messages.DebuggerBundle";
+
+ private DebuggerBundle() {
+ }
+
+ public static String getAddressDisplayName(final RemoteConnection connection) {
+ return connection.isUseSockets() ? connection.getHostName() + ":" + connection.getAddress() : connection.getAddress();
+ }
+
+ public static String getTransportName(final RemoteConnection connection) {
+ return connection.isUseSockets() ? message("transport.name.socket") : message("transport.name.shared.memory");
+ }
+
+ public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = null;
+ if (ourBundle != null) bundle = ourBundle.get();
+ if (bundle == null) {
+ bundle = ResourceBundle.getBundle(BUNDLE);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
+ }
+ return bundle;
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/DebuggerContext.java b/java/debugger/openapi/src/com/intellij/debugger/DebuggerContext.java
new file mode 100644
index 0000000..d2c9180
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/DebuggerContext.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.debugger.engine.StackFrameContext;
+import com.intellij.debugger.engine.SuspendContext;
+import com.intellij.openapi.project.Project;
+
+public interface DebuggerContext extends StackFrameContext{
+ SuspendContext getSuspendContext();
+
+ Project getProject();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/DebuggerManager.java b/java/debugger/openapi/src/com/intellij/debugger/DebuggerManager.java
new file mode 100644
index 0000000..26b02c8
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/DebuggerManager.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.debugger.engine.DebugProcess;
+import com.intellij.debugger.engine.DebugProcessListener;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.JDOMExternalizable;
+import com.intellij.psi.PsiClass;
+import com.intellij.util.Function;
+
+/**
+ * @author lex
+ */
+public abstract class DebuggerManager implements ProjectComponent, JDOMExternalizable {
+ public static DebuggerManager getInstance(Project project) {
+ return project.getComponent(DebuggerManager.class);
+ }
+
+ public abstract DebugProcess getDebugProcess(ProcessHandler processHandler);
+
+ public abstract void addDebugProcessListener(ProcessHandler processHandler, DebugProcessListener listener);
+
+ public abstract void removeDebugProcessListener(ProcessHandler processHandler, DebugProcessListener listener);
+
+ public abstract boolean isDebuggerManagerThread();
+
+ public abstract void addClassNameMapper(NameMapper mapper);
+
+ public abstract void removeClassNameMapper(NameMapper mapper);
+
+ public abstract String getVMClassQualifiedName(PsiClass aClass);
+
+ /**
+ * @deprecated use PositionManagerFactory extension point instead
+ */
+ public abstract void registerPositionManagerFactory(Function<DebugProcess, PositionManager> factory);
+
+ public abstract void unregisterPositionManagerFactory(Function<DebugProcess, PositionManager> factory);
+
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/NameMapper.java b/java/debugger/openapi/src/com/intellij/debugger/NameMapper.java
new file mode 100644
index 0000000..4530806
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/NameMapper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Compilers of some java-based languages (like Scala) produce classes with names different from those declared in sources.
+ * If for some language qualified names of compiled classes differ from names declared in the sources, a NameMapper must be registered
+ * within the DebuggerManager class.
+ * Multiple registered mappers forms a "chain of responsibility" and the first non-null result is returned.
+ * If no mappers are registered or all mappers returned null, the result of
+ * PsiClass.getQualifiedName() will be used as a qualified name of the compiled class
+ */
+public interface NameMapper {
+ /**
+ * @param aClass a top-level class
+ * @return a qualified name of the corresponding compiled class or null if default machanism of getting qualified names must be used
+ */
+ String getQualifiedName(@NotNull PsiClass aClass);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/NoDataException.java b/java/debugger/openapi/src/com/intellij/debugger/NoDataException.java
new file mode 100644
index 0000000..b3f30af
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/NoDataException.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2009 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;
+
+public class NoDataException extends Exception{
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/PositionManager.java b/java/debugger/openapi/src/com/intellij/debugger/PositionManager.java
new file mode 100644
index 0000000..5713483
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/PositionManager.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.debugger.requests.ClassPrepareRequestor;
+import com.sun.jdi.Location;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.request.ClassPrepareRequest;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * Manages the correspondence between source positions and bytecode locations during JVM debugging.
+ * Instances of this class are created by the factory registered via the {@link PositionManagerFactory} extension point.
+ *
+ * @see com.intellij.debugger.engine.JSR45PositionManager
+ */
+public interface PositionManager {
+ /**
+ * Returns the source position corresponding to the specified bytecode location.
+ *
+ * @param location the bytecode location.
+ * @return the corresponding source position.
+ * @throws NoDataException if the location is not in the code managed by this {@code PositionManager}
+ */
+ @Nullable
+ SourcePosition getSourcePosition(@Nullable Location location) throws NoDataException;
+
+ /**
+ * Returns the list of all Java classes corresponding to the specified position in the source code.
+ *
+ * @param classPosition the source position.
+ * @return the list of corresponding Java classes.
+ * @throws NoDataException if the location is not in the code managed by this {@code PositionManager}
+ * @see com.intellij.debugger.engine.jdi.VirtualMachineProxy#classesByName
+ */
+ @NotNull
+ List<ReferenceType> getAllClasses(SourcePosition classPosition) throws NoDataException;
+
+ /**
+ * Returns the list of bytecode locations in a specific class corresponding to the specified position in the source code.
+ *
+ * @param type a Java class (one of the list returned by {@link #getAllClasses}).
+ * @param position the position in the source code.
+ * @return the list of corresponding bytecode locations.
+ * @throws NoDataException if the location is not in the code managed by this {@code PositionManager}
+ * @see ReferenceType#locationsOfLine(int)
+ */
+ @NotNull
+ List<Location> locationsOfLine(ReferenceType type, SourcePosition position) throws NoDataException;
+
+ /**
+ * Called to request the JVM to notify the debugger engine when a class corresponding to a breakpoint location is loaded.
+ * The implementation should calculate the pattern of the class files corresponding to the breakpoint location and call
+ * {@link com.intellij.debugger.requests.RequestManager#createClassPrepareRequest} to create the request.
+ *
+ * @param requestor the object to receive the notification from the JVM.
+ * @param position the location of a breakpoint.
+ * @return the prepare request, or null if the code is managed by this {@code PositionManager} but no class prepare notification is needed
+ * @throws NoDataException if the position is not in the code managed by this {@code PositionManager}
+ */
+ @Nullable
+ ClassPrepareRequest createPrepareRequest(ClassPrepareRequestor requestor, SourcePosition position) throws NoDataException;
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/PositionManagerFactory.java b/java/debugger/openapi/src/com/intellij/debugger/PositionManagerFactory.java
new file mode 100644
index 0000000..e89d423
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/PositionManagerFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2011 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;
+
+import com.intellij.debugger.engine.DebugProcess;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public abstract class PositionManagerFactory {
+ public static final ExtensionPointName<PositionManagerFactory> EP_NAME = ExtensionPointName.create("com.intellij.debugger.positionManagerFactory");
+
+ @Nullable
+ public abstract PositionManager createPositionManager(DebugProcess process);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java
new file mode 100644
index 0000000..9028b14
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2000-2009 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;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.Navigatable;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * User: lex
+ * Date: Oct 24, 2003
+ * Time: 8:23:06 PM
+ */
+public abstract class SourcePosition implements Navigatable{
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.SourcePosition");
+ @NotNull
+ public abstract PsiFile getFile();
+
+ public abstract PsiElement getElementAt();
+
+ /**
+ * @return a zero-based line number
+ */
+ public abstract int getLine();
+
+ public abstract int getOffset();
+
+ public abstract Editor openEditor(boolean requestFocus);
+
+ private abstract static class SourcePositionCache extends SourcePosition {
+ @NotNull private final PsiFile myFile;
+ private long myModificationStamp = -1L;
+
+ private PsiElement myPsiElement;
+ private Integer myLine;
+ private Integer myOffset;
+
+ public SourcePositionCache(@NotNull PsiFile file) {
+ myFile = file;
+ updateData();
+ }
+
+ @Override
+ @NotNull
+ public PsiFile getFile() {
+ return myFile;
+ }
+
+ @Override
+ public boolean canNavigate() {
+ return getFile().isValid();
+ }
+
+ @Override
+ public boolean canNavigateToSource() {
+ return canNavigate();
+ }
+
+ @Override
+ public void navigate(final boolean requestFocus) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!canNavigate()) {
+ return;
+ }
+ openEditor(requestFocus);
+ }
+ });
+ }
+
+ @Override
+ public Editor openEditor(final boolean requestFocus) {
+ final PsiFile psiFile = getFile();
+ final Project project = psiFile.getProject();
+ if (project.isDisposed()) {
+ return null;
+ }
+ final VirtualFile virtualFile = psiFile.getVirtualFile();
+ if (virtualFile == null || !virtualFile.isValid()) {
+ return null;
+ }
+ final int offset = getOffset();
+ if (offset < 0) {
+ return null;
+ }
+ return FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, virtualFile, offset), requestFocus);
+ }
+
+ private void updateData() {
+ if(dataUpdateNeeded()) {
+ myModificationStamp = myFile.getModificationStamp();
+ myLine = null;
+ myOffset = null;
+ myPsiElement = null;
+ }
+ }
+
+ private boolean dataUpdateNeeded() {
+ if (myModificationStamp != myFile.getModificationStamp()) {
+ return true;
+ }
+ final PsiElement psiElement = myPsiElement;
+ return psiElement != null && !psiElement.isValid();
+ }
+
+ @Override
+ public int getLine() {
+ updateData();
+ if (myLine == null) {
+ myLine = calcLine();
+ }
+ return myLine.intValue();
+ }
+
+ @Override
+ public int getOffset() {
+ updateData();
+ if (myOffset == null) {
+ myOffset = calcOffset();
+ }
+ return myOffset.intValue();
+ }
+
+ @Override
+ public PsiElement getElementAt() {
+ updateData();
+ if (myPsiElement == null) {
+ myPsiElement = calcPsiElement();
+ }
+ return myPsiElement;
+ }
+
+ protected int calcLine() {
+ final PsiFile file = getFile();
+ Document document = null;
+ try {
+ document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ if (document != null) {
+ try {
+ return document.getLineNumber(calcOffset());
+ }
+ catch (IndexOutOfBoundsException e) {
+ // may happen if document has been changed since the this SourcePosition was created
+ }
+ }
+ return -1;
+ }
+
+ protected int calcOffset() {
+ final PsiFile file = getFile();
+ final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ if (document != null) {
+ try {
+ return document.getLineStartOffset(calcLine());
+ }
+ catch (IndexOutOfBoundsException e) {
+ // may happen if document has been changed since the this SourcePosition was created
+ }
+ }
+ return -1;
+ }
+
+ @Nullable
+ protected PsiElement calcPsiElement() {
+ PsiFile psiFile = getFile();
+ int lineNumber = getLine();
+ if(lineNumber < 0) {
+ return psiFile;
+ }
+
+ final Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile);
+ if (document == null) {
+ return null;
+ }
+ if (lineNumber >= document.getLineCount()) {
+ return psiFile;
+ }
+ int startOffset = document.getLineStartOffset(lineNumber);
+ if(startOffset == -1) {
+ return null;
+ }
+
+ PsiElement rootElement = psiFile;
+
+ List<PsiFile> allFiles = psiFile.getViewProvider().getAllFiles();
+ if (allFiles.size() > 1) { // jsp & gsp
+ PsiClassOwner owner = ContainerUtil.findInstance(allFiles, PsiClassOwner.class);
+ if (owner != null) {
+ PsiClass[] classes = owner.getClasses();
+ if (classes.length == 1 && classes[0] instanceof SyntheticElement) {
+ rootElement = classes[0];
+ }
+ }
+ }
+
+ PsiElement element;
+ while(true) {
+ final CharSequence charsSequence = document.getCharsSequence();
+ for (; startOffset < charsSequence.length(); startOffset++) {
+ char c = charsSequence.charAt(startOffset);
+ if (c != ' ' && c != '\t') {
+ break;
+ }
+ }
+ element = rootElement.findElementAt(startOffset);
+
+ if(element instanceof PsiComment) {
+ startOffset = element.getTextRange().getEndOffset() + 1;
+ }
+ else{
+ break;
+ }
+ }
+
+ if (element != null && element.getParent() instanceof PsiForStatement) {
+ return ((PsiForStatement)element.getParent()).getInitialization();
+ }
+ return element;
+ }
+ }
+
+ public static SourcePosition createFromLineComputable(final PsiFile file, final Computable<Integer> line) {
+ return new SourcePositionCache(file) {
+ @Override
+ protected int calcLine() {
+ return line.compute();
+ }
+ };
+ }
+
+ public static SourcePosition createFromLine(final PsiFile file, final int line) {
+ return new SourcePositionCache(file) {
+ @Override
+ protected int calcLine() {
+ return line;
+ }
+ };
+ }
+
+ public static SourcePosition createFromOffset(final PsiFile file, final int offset) {
+ return new SourcePositionCache(file) {
+
+ @Override
+ protected int calcOffset() {
+ return offset;
+ }
+ };
+ }
+
+ public static SourcePosition createFromElement(PsiElement element) {
+ final PsiElement navigationElement = element.getNavigationElement();
+ final PsiFile psiFile;
+ if (JspPsiUtil.isInJspFile(navigationElement)) {
+ psiFile = JspPsiUtil.getJspFile(navigationElement);
+ }
+ else {
+ psiFile = navigationElement.getContainingFile();
+ }
+ return new SourcePositionCache(psiFile) {
+ @Override
+ protected PsiElement calcPsiElement() {
+ return navigationElement;
+ }
+
+ @Override
+ protected int calcOffset() {
+ return navigationElement.getTextOffset();
+ }
+ };
+ }
+
+ public boolean equals(Object o) {
+ if(o instanceof SourcePosition) {
+ SourcePosition sourcePosition = (SourcePosition)o;
+ return Comparing.equal(sourcePosition.getFile(), getFile()) && sourcePosition.getOffset() == getOffset();
+ }
+
+ return false;
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java
new file mode 100644
index 0000000..bca8159
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.debugger.PositionManager;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
+import com.intellij.debugger.engine.managerThread.DebuggerManagerThread;
+import com.intellij.debugger.requests.RequestManager;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.sun.jdi.*;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author lex
+ */
+public interface DebugProcess {
+ @NonNls String JAVA_STRATUM = "Java";
+
+ <T> T getUserData(Key<T> key);
+ <T> void putUserData(Key<T> key, T value);
+
+ Project getProject();
+
+ RequestManager getRequestsManager();
+
+ PositionManager getPositionManager();
+
+ VirtualMachineProxy getVirtualMachineProxy();
+
+ void addDebugProcessListener(DebugProcessListener listener);
+
+ void removeDebugProcessListener(DebugProcessListener listener);
+
+ void appendPositionManager(PositionManager positionManager);
+
+ void waitFor();
+
+ void waitFor(long timeout);
+
+ void stop(boolean forceTerminate);
+
+ ExecutionResult getExecutionResult();
+
+ DebuggerManagerThread getManagerThread();
+
+ Value invokeMethod(EvaluationContext evaluationContext,
+ ObjectReference objRef,
+ Method method,
+ List args) throws EvaluateException;
+
+ /**
+ * Is equivalent to invokeInstanceMethod(evaluationContext, classType, method, args, 0)
+ */
+ Value invokeMethod(EvaluationContext evaluationContext,
+ ClassType classType,
+ Method method,
+ List args) throws EvaluateException;
+
+ Value invokeInstanceMethod(EvaluationContext evaluationContext,
+ ObjectReference objRef,
+ Method method,
+ List args,
+ int invocationOptions) throws EvaluateException;
+
+ ReferenceType findClass(EvaluationContext evaluationContext,
+ String name,
+ ClassLoaderReference classLoader) throws EvaluateException;
+
+ ArrayReference newInstance(ArrayType arrayType,
+ int dimension) throws EvaluateException;
+
+ ObjectReference newInstance(EvaluationContext evaluationContext,
+ ClassType classType,
+ Method constructor,
+ List paramList) throws EvaluateException;
+
+ boolean isAttached();
+
+ boolean isDetached();
+
+ boolean isDetaching();
+
+ /**
+ * @return the search scope used by debugger to find sources corresponding to classes being executed
+ */
+ @NotNull
+ GlobalSearchScope getSearchScope();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessAdapter.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessAdapter.java
new file mode 100644
index 0000000..16c43c2
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessAdapter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RunProfileState;
+import com.sun.jdi.ThreadReference;
+
+public class DebugProcessAdapter implements DebugProcessListener{
+ //executed in manager thread
+ public void connectorIsReady() {
+ }
+
+ //executed in manager thread
+ public void paused(SuspendContext suspendContext) {
+
+ }
+
+ //executed in manager thread
+ public void resumed(SuspendContext suspendContext) {
+
+ }
+
+ //executed in manager thread
+ public void processDetached(DebugProcess process, boolean closedByUser) {
+
+ }
+
+ //executed in manager thread
+ public void processAttached(DebugProcess process) {
+
+ }
+
+ //executed in manager thread
+ public void threadStarted(DebugProcess proc, ThreadReference thread) {
+ }
+
+ //executed in manager thread
+ public void threadStopped(DebugProcess proc, ThreadReference thread) {
+ }
+
+ public void attachException(RunProfileState state, ExecutionException exception, RemoteConnection remoteConnection) {
+
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessListener.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessListener.java
new file mode 100644
index 0000000..e992f25
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcessListener.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RunProfileState;
+import com.sun.jdi.ThreadReference;
+
+import java.util.EventListener;
+
+
+public interface DebugProcessListener extends EventListener{
+ //executed in manager thread
+ void connectorIsReady();
+
+ //executed in manager thread
+ void paused(SuspendContext suspendContext);
+
+ //executed in manager thread
+ void resumed(SuspendContext suspendContext);
+
+ //executed in manager thread
+ void processDetached(DebugProcess process, boolean closedByUser);
+
+ //executed in manager thread
+ void processAttached(DebugProcess process);
+
+ void attachException(RunProfileState state, ExecutionException exception, RemoteConnection remoteConnection);
+
+ void threadStarted(DebugProcess proc, ThreadReference thread);
+
+ void threadStopped(DebugProcess proc, ThreadReference thread);
+}
+
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
new file mode 100644
index 0000000..418e442
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
@@ -0,0 +1,570 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.DebuggerContext;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
+import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.intellij.debugger.engine.evaluation.TextWithImports;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.LanguageLevelProjectExtension;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.StringBuilderSpinAllocator;
+import com.sun.jdi.*;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+public abstract class DebuggerUtils {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.DebuggerUtils");
+ private static final Key<Method> TO_STRING_METHOD_KEY = new Key<Method>("CachedToStringMethod");
+ public static final Set<String> ourPrimitiveTypeNames = new HashSet<String>(Arrays.asList(
+ "byte", "short", "int", "long", "float", "double", "boolean", "char"
+ ));
+
+ public static void cleanupAfterProcessFinish(DebugProcess debugProcess) {
+ debugProcess.putUserData(TO_STRING_METHOD_KEY, null);
+ }
+
+ @NonNls
+ public static String getValueAsString(final EvaluationContext evaluationContext, Value value) throws EvaluateException {
+ try {
+ if (value == null) {
+ return "null";
+ }
+ if (value instanceof StringReference) {
+ return ((StringReference)value).value();
+ }
+ if (isInteger(value)) {
+ long v = ((PrimitiveValue)value).longValue();
+ return String.valueOf(v);
+ }
+ if (isNumeric(value)) {
+ double v = ((PrimitiveValue)value).doubleValue();
+ return String.valueOf(v);
+ }
+ if (value instanceof BooleanValue) {
+ boolean v = ((PrimitiveValue)value).booleanValue();
+ return String.valueOf(v);
+ }
+ if (value instanceof CharValue) {
+ char v = ((PrimitiveValue)value).charValue();
+ return String.valueOf(v);
+ }
+ if (value instanceof ObjectReference) {
+ if (value instanceof ArrayReference) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (Iterator<Value> iterator = ((ArrayReference)value).getValues().iterator(); iterator.hasNext();) {
+ final Value element = iterator.next();
+ builder.append(getValueAsString(evaluationContext, element));
+ if (iterator.hasNext()) {
+ builder.append(",");
+ }
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+ final ObjectReference objRef = (ObjectReference)value;
+ final DebugProcess debugProcess = evaluationContext.getDebugProcess();
+ Method toStringMethod = debugProcess.getUserData(TO_STRING_METHOD_KEY);
+ if (toStringMethod == null) {
+ try {
+ ReferenceType refType = objRef.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT).get(0);
+ toStringMethod = findMethod(refType, "toString", "()Ljava/lang/String;");
+ debugProcess.putUserData(TO_STRING_METHOD_KEY, toStringMethod);
+ }
+ catch (Exception e) {
+ throw EvaluateExceptionUtil.createEvaluateException(
+ DebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
+ }
+ }
+ if (toStringMethod == null) {
+ throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
+ }
+ final StringReference stringReference = (StringReference)debugProcess.invokeInstanceMethod(evaluationContext, objRef, toStringMethod, Collections.emptyList(), 0);
+ return stringReference == null ? "null" : stringReference.value();
+ }
+ throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.unsupported.expression.type"));
+ }
+ catch (ObjectCollectedException e) {
+ throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
+ }
+ }
+
+ public static final int MAX_DISPLAY_LABEL_LENGTH = 1024/*kb*/ *1024 /*bytes*/ / 2; // 1 Mb string
+
+ public static String convertToPresentationString(String str) {
+ if (str.length() > MAX_DISPLAY_LABEL_LENGTH) {
+ str = translateStringValue(str.substring(0, MAX_DISPLAY_LABEL_LENGTH));
+ StringBuilder buf = new StringBuilder();
+ buf.append(str);
+ if (!str.endsWith("...")) {
+ buf.append("...");
+ }
+ return buf.toString();
+ }
+ return translateStringValue(str);
+ }
+
+ @Nullable
+ public static Method findMethod(ReferenceType refType, @NonNls String methodName, @NonNls String methodSignature) {
+ if (refType instanceof ArrayType) {
+ // for array types methodByName() in JDI always returns empty list
+ final Method method = findMethod(refType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT).get(0), methodName, methodSignature);
+ if (method != null) {
+ return method;
+ }
+ }
+
+ Method method = null;
+ if (methodSignature != null) {
+ if (refType instanceof ClassType) {
+ method = ((ClassType)refType).concreteMethodByName(methodName, methodSignature);
+ }
+ if (method == null) {
+ final List<Method> methods = refType.methodsByName(methodName, methodSignature);
+ if (methods.size() > 0) {
+ method = methods.get(0);
+ }
+ }
+ }
+ else {
+ List<Method> methods = null;
+ if (refType instanceof ClassType) {
+ methods = refType.methodsByName(methodName);
+ }
+ if (methods != null && methods.size() > 0) {
+ method = methods.get(0);
+ }
+ }
+ return method;
+ }
+
+ public static boolean isNumeric(Value value) {
+ return value != null &&
+ (isInteger(value) ||
+ value instanceof FloatValue ||
+ value instanceof DoubleValue
+ );
+ }
+
+ public static boolean isInteger(Value value) {
+ return value != null &&
+ (value instanceof ByteValue ||
+ value instanceof ShortValue ||
+ value instanceof LongValue ||
+ value instanceof IntegerValue
+ );
+ }
+
+ public static String translateStringValue(final String str) {
+ int length = str.length();
+ final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
+ try {
+ StringUtil.escapeStringCharacters(length, str, buffer);
+ if (str.length() > length) {
+ buffer.append("...");
+ }
+ return buffer.toString();
+ }
+ finally {
+ StringBuilderSpinAllocator.dispose(buffer);
+ }
+ }
+
+ protected static ArrayClass getArrayClass(String className) {
+ boolean searchBracket = false;
+ int dims = 0;
+ int pos;
+
+ for(pos = className.lastIndexOf(']'); pos >= 0; pos--){
+ char c = className.charAt(pos);
+
+ if (searchBracket) {
+ if (c == '[') {
+ dims++;
+ searchBracket = false;
+ }
+ else if (!Character.isWhitespace(c)) break;
+ }
+ else {
+ if (c == ']') {
+ searchBracket = true;
+ }
+ else if (!Character.isWhitespace(c)) break;
+ }
+ }
+
+ if (searchBracket) return null;
+
+ if(dims == 0) return null;
+
+ return new ArrayClass(className.substring(0, pos + 1), dims);
+ }
+
+ public static boolean instanceOf(String subType, String superType, Project project) {
+ if(project == null) {
+ return subType.equals(superType);
+ }
+
+ ArrayClass nodeClass = getArrayClass(subType);
+ ArrayClass rendererClass = getArrayClass(superType);
+ if (nodeClass == null || rendererClass == null) return false;
+
+ if (nodeClass.dims == rendererClass.dims) {
+ GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ PsiClass psiNodeClass = JavaPsiFacade.getInstance(project).findClass(nodeClass.className, scope);
+ PsiClass psiRendererClass = JavaPsiFacade.getInstance(project).findClass(rendererClass.className, scope);
+ return InheritanceUtil.isInheritorOrSelf(psiNodeClass, psiRendererClass, true);
+ }
+ else if (nodeClass.dims > rendererClass.dims) {
+ return rendererClass.className.equals(CommonClassNames.JAVA_LANG_OBJECT);
+ }
+ return false;
+ }
+
+ public static Type getSuperType(Type subType, String superType) {
+ if(CommonClassNames.JAVA_LANG_OBJECT.equals(superType)) {
+ List list = subType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT);
+ if(list.size() > 0) {
+ return (ReferenceType)list.get(0);
+ }
+ return null;
+ }
+
+ return getSuperTypeInt(subType, superType);
+ }
+
+ private static Type getSuperTypeInt(Type subType, String superType) {
+ Type result;
+ if (subType == null) {
+ return null;
+ }
+
+ if (subType.name().equals(superType)) {
+ return subType;
+ }
+
+ if (subType instanceof ClassType) {
+ result = getSuperType(((ClassType)subType).superclass(), superType);
+ if (result != null) {
+ return result;
+ }
+
+ List ifaces = ((ClassType)subType).allInterfaces();
+ for (Iterator iterator = ifaces.iterator(); iterator.hasNext();) {
+ InterfaceType interfaceType = (InterfaceType)iterator.next();
+ if (interfaceType.name().equals(superType)) {
+ return interfaceType;
+ }
+ }
+ return null;
+ }
+
+ if (subType instanceof InterfaceType) {
+ List ifaces = ((InterfaceType)subType).superinterfaces();
+ for (Iterator iterator = ifaces.iterator(); iterator.hasNext();) {
+ InterfaceType interfaceType = (InterfaceType)iterator.next();
+ result = getSuperType(interfaceType, superType);
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ else if (subType instanceof ArrayType) {
+ if (superType.endsWith("[]")) {
+ try {
+ String superTypeItem = superType.substring(0, superType.length() - 2);
+ Type subTypeItem = ((ArrayType)subType).componentType();
+ return instanceOf(subTypeItem, superTypeItem) ? subType : null;
+ }
+ catch (ClassNotLoadedException e) {
+ LOG.debug(e);
+ }
+ }
+ }
+ else if (subType instanceof PrimitiveType) {
+ //noinspection HardCodedStringLiteral
+ if(superType.equals("java.lang.Primitive")) {
+ return subType;
+ }
+ }
+
+ //only for interfaces and arrays
+ if(CommonClassNames.JAVA_LANG_OBJECT.equals(superType)) {
+ List list = subType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT);
+ if(list.size() > 0) {
+ return (ReferenceType)list.get(0);
+ }
+ }
+ return null;
+ }
+
+ public static boolean instanceOf(Type subType, String superType) {
+ return getSuperType(subType, superType) != null;
+ }
+
+ @Nullable
+ public static PsiClass findClass(final String className, Project project, final GlobalSearchScope scope) {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+ final PsiManager psiManager = PsiManager.getInstance(project);
+ final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(psiManager.getProject());
+ if (getArrayClass(className) != null) {
+ return javaPsiFacade.getElementFactory().getArrayClass(LanguageLevelProjectExtension.getInstance(psiManager.getProject()).getLanguageLevel());
+ }
+ if(project.isDefault()) {
+ return null;
+ }
+ final String _className = className.replace('$', '.');
+ PsiClass aClass = javaPsiFacade.findClass(_className, scope);
+ if (aClass == null) {
+ if (!_className.equals(className)) {
+ // try original name if it differs from the normalized name
+ aClass = javaPsiFacade.findClass(className, scope);
+ }
+ }
+ if (aClass == null) {
+ final GlobalSearchScope globalScope = GlobalSearchScope.allScope(project);
+ if (!globalScope.equals(scope)) {
+ aClass = javaPsiFacade.findClass(_className, globalScope);
+ if (aClass == null) {
+ if (!_className.equals(className)) {
+ // try original name with global scope if the original differs from the normalized name
+ aClass = javaPsiFacade.findClass(className, globalScope);
+ }
+ }
+ }
+ }
+ return aClass;
+ }
+
+ public static PsiType getType(String className, Project project) {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+
+ final PsiManager psiManager = PsiManager.getInstance(project);
+ try {
+ if (getArrayClass(className) != null) {
+ return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createTypeFromText(className, null);
+ }
+ if(project.isDefault()) {
+ return null;
+ }
+ final PsiClass aClass =
+ JavaPsiFacade.getInstance(psiManager.getProject()).findClass(className.replace('$', '.'), GlobalSearchScope.allScope(project));
+ return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(aClass);
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
+ return null;
+ }
+
+ public static void checkSyntax(PsiCodeFragment codeFragment) throws EvaluateException {
+ PsiElement[] children = codeFragment.getChildren();
+
+ if(children.length == 0) throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.empty.code.fragment"));
+ for (int i = 0; i < children.length; i++) {
+ PsiElement child = children[i];
+ if(child instanceof PsiErrorElement) {
+ throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", child.getText()));
+ }
+ }
+ }
+
+ public static boolean hasSideEffects(PsiElement element) {
+ return hasSideEffectsOrReferencesMissingVars(element, null);
+ }
+
+ public static boolean hasSideEffectsOrReferencesMissingVars(PsiElement element, @Nullable final Set<String> visibleLocalVariables) {
+ final Ref<Boolean> rv = new Ref<Boolean>(Boolean.FALSE);
+ element.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitPostfixExpression(final PsiPostfixExpression expression) {
+ rv.set(Boolean.TRUE);
+ }
+
+ @Override
+ public void visitReferenceExpression(final PsiReferenceExpression expression) {
+ final PsiElement psiElement = expression.resolve();
+ if (psiElement instanceof PsiLocalVariable) {
+ if (visibleLocalVariables != null) {
+ if (!visibleLocalVariables.contains(((PsiLocalVariable)psiElement).getName())) {
+ rv.set(Boolean.TRUE);
+ }
+ }
+ }
+ else if (psiElement instanceof PsiMethod) {
+ rv.set(Boolean.TRUE);
+ //final PsiMethod method = (PsiMethod)psiElement;
+ //if (!isSimpleGetter(method)) {
+ // rv.set(Boolean.TRUE);
+ //}
+ }
+ if (!rv.get().booleanValue()) {
+ super.visitReferenceExpression(expression);
+ }
+ }
+
+ @Override
+ public void visitPrefixExpression(final PsiPrefixExpression expression) {
+ final IElementType op = expression.getOperationTokenType();
+ if (JavaTokenType.PLUSPLUS.equals(op) || JavaTokenType.MINUSMINUS.equals(op)) {
+ rv.set(Boolean.TRUE);
+ }
+ else {
+ super.visitPrefixExpression(expression);
+ }
+ }
+
+ @Override
+ public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
+ rv.set(Boolean.TRUE);
+ }
+
+ @Override
+ public void visitCallExpression(final PsiCallExpression callExpression) {
+ rv.set(Boolean.TRUE);
+ //final PsiMethod method = callExpression.resolveMethod();
+ //if (method == null || !isSimpleGetter(method)) {
+ // rv.set(Boolean.TRUE);
+ //}
+ //else {
+ // super.visitCallExpression(callExpression);
+ //}
+ }
+ });
+ return rv.get().booleanValue();
+ }
+
+ public abstract String findAvailableDebugAddress(boolean useSockets) throws ExecutionException;
+
+ public static boolean isSynthetic(TypeComponent typeComponent) {
+ if (typeComponent == null) {
+ return false;
+ }
+ VirtualMachine machine = typeComponent.virtualMachine();
+ return machine != null && machine.canGetSyntheticAttribute() && typeComponent.isSynthetic();
+ }
+
+ public static boolean isSimpleGetter(PsiMethod method){
+ final PsiCodeBlock body = method.getBody();
+ if(body == null){
+ return false;
+ }
+
+ final PsiStatement[] statements = body.getStatements();
+ if(statements.length != 1){
+ return false;
+ }
+
+ final PsiStatement statement = statements[0];
+ if(!(statement instanceof PsiReturnStatement)){
+ return false;
+ }
+
+ final PsiExpression value = ((PsiReturnStatement)statement).getReturnValue();
+ if(!(value instanceof PsiReferenceExpression)){
+ return false;
+ }
+
+ final PsiReferenceExpression reference = (PsiReferenceExpression)value;
+ final PsiExpression qualifier = reference.getQualifierExpression();
+ //noinspection HardCodedStringLiteral
+ if(qualifier != null && !"this".equals(qualifier.getText())) {
+ return false;
+ }
+
+ final PsiElement referent = reference.resolve();
+ if(referent == null) {
+ return false;
+ }
+
+ if(!(referent instanceof PsiField)) {
+ return false;
+ }
+
+ return ((PsiField)referent).getContainingClass().equals(method.getContainingClass());
+ }
+
+ public static boolean isPrimitiveType(final String typeName) {
+ return ourPrimitiveTypeNames.contains(typeName);
+ }
+
+ protected static class ArrayClass {
+ public String className;
+ public int dims;
+
+ public ArrayClass(String className, int dims) {
+ this.className = className;
+ this.dims = dims;
+ }
+ }
+
+ public static DebuggerUtils getInstance() {
+ return ServiceManager.getService(DebuggerUtils.class);
+ }
+
+ public abstract PsiExpression substituteThis(PsiExpression expressionWithThis, PsiExpression howToEvaluateThis, Value howToEvaluateThisValue, StackFrameContext context) throws EvaluateException;
+
+ public abstract DebuggerContext getDebuggerContext (DataContext context);
+
+ public abstract Element writeTextWithImports(TextWithImports text);
+ public abstract TextWithImports readTextWithImports (Element element);
+
+ public abstract void writeTextWithImports(Element root, @NonNls String name, TextWithImports value);
+ public abstract TextWithImports readTextWithImports (Element root, @NonNls String name);
+
+ public abstract TextWithImports createExpressionWithImports(@NonNls String expression);
+
+ public abstract PsiElement getContextElement(final StackFrameContext context);
+
+ public abstract PsiClass chooseClassDialog(String title, Project project);
+
+ public static boolean supportsJVMDebugging(FileType type) {
+ return type instanceof LanguageFileType && ((LanguageFileType)type).isJVMDebuggingSupported();
+ }
+
+ public static boolean supportsJVMDebugging(PsiFile file) {
+ final JVMDebugProvider[] providers = Extensions.getExtensions(JVMDebugProvider.EP_NAME);
+ for (JVMDebugProvider provider : providers) {
+ if (provider.supportsJVMDebugging(file)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java b/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java
new file mode 100644
index 0000000..1697684
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.NoDataException;
+import com.intellij.debugger.PositionManager;
+import com.intellij.debugger.SourcePosition;
+import com.intellij.debugger.requests.ClassPrepareRequestor;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.PsiFile;
+import com.sun.jdi.*;
+import com.sun.jdi.request.ClassPrepareRequest;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: May 23, 2006
+ */
+public abstract class JSR45PositionManager<Scope> implements PositionManager {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.JSR45PositionManager");
+ protected final DebugProcess myDebugProcess;
+ protected final Scope myScope;
+ private final String myStratumId;
+ protected final SourcesFinder<Scope> mySourcesFinder;
+ protected final String GENERATED_CLASS_PATTERN;
+ protected Matcher myGeneratedClassPatternMatcher;
+ private final Set<LanguageFileType> myFileTypes;
+
+ public JSR45PositionManager(DebugProcess debugProcess, Scope scope, final String stratumId, final LanguageFileType[] acceptedFileTypes,
+ final SourcesFinder<Scope> sourcesFinder) {
+ myDebugProcess = debugProcess;
+ myScope = scope;
+ myStratumId = stratumId;
+ myFileTypes = Collections.unmodifiableSet(new HashSet<LanguageFileType>(Arrays.asList(acceptedFileTypes)));
+ mySourcesFinder = sourcesFinder;
+ String generatedClassPattern = getGeneratedClassesPackage();
+ if(generatedClassPattern.length() == 0) {
+ generatedClassPattern = getGeneratedClassesNamePattern();
+ }
+ else {
+ generatedClassPattern = generatedClassPattern + "." + getGeneratedClassesNamePattern();
+ }
+ GENERATED_CLASS_PATTERN = generatedClassPattern;
+ myGeneratedClassPatternMatcher = Pattern.compile(generatedClassPattern.replaceAll("\\*", ".*")).matcher("");
+ }
+
+ @NonNls
+ protected abstract String getGeneratedClassesPackage();
+
+ protected String getGeneratedClassesNamePattern() {
+ return "*";
+ }
+
+ public final String getStratumId() {
+ return myStratumId;
+ }
+
+ public SourcePosition getSourcePosition(final Location location) throws NoDataException {
+ SourcePosition sourcePosition = null;
+
+ try {
+ String sourcePath = getRelativeSourcePathByLocation(location);
+ PsiFile file = mySourcesFinder.findSourceFile(sourcePath, myDebugProcess.getProject(), myScope);
+ if(file != null) {
+ int lineNumber = getLineNumber(location);
+ sourcePosition = SourcePosition.createFromLine(file, lineNumber - 1);
+ }
+ }
+ catch (AbsentInformationException ignored) { // ignored
+ }
+ catch (Throwable e) {
+ LOG.info(e);
+ }
+ if(sourcePosition == null) {
+ throw new NoDataException();
+ }
+ return sourcePosition;
+ }
+
+ protected String getRelativeSourcePathByLocation(final Location location) throws AbsentInformationException {
+ return getRelativePath(location.sourcePath(myStratumId));
+ }
+
+ protected int getLineNumber(final Location location) {
+ return location.lineNumber(myStratumId);
+ }
+
+ @NotNull
+ public List<ReferenceType> getAllClasses(SourcePosition classPosition) throws NoDataException {
+ checkSourcePositionFileType(classPosition);
+
+ final List<ReferenceType> referenceTypes = myDebugProcess.getVirtualMachineProxy().allClasses();
+
+ final List<ReferenceType> result = new ArrayList<ReferenceType>();
+
+ for (final ReferenceType referenceType : referenceTypes) {
+ myGeneratedClassPatternMatcher.reset(referenceType.name());
+ if (myGeneratedClassPatternMatcher.matches()) {
+ final List<Location> locations = locationsOfClassAt(referenceType, classPosition);
+ if (locations != null && locations.size() > 0) {
+ result.add(referenceType);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private void checkSourcePositionFileType(final SourcePosition classPosition) throws NoDataException {
+ final FileType fileType = classPosition.getFile().getFileType();
+ if(!myFileTypes.contains(fileType)) {
+ throw new NoDataException();
+ }
+ }
+
+ @NotNull
+ public List<Location> locationsOfLine(final ReferenceType type, final SourcePosition position) throws NoDataException {
+ List<Location> locations = locationsOfClassAt(type, position);
+ return locations != null ? locations : Collections.<Location>emptyList();
+
+ }
+
+ private List<Location> locationsOfClassAt(final ReferenceType type, final SourcePosition position) throws NoDataException {
+ checkSourcePositionFileType(position);
+
+ return ApplicationManager.getApplication().runReadAction(new Computable<List<Location>>() {
+ public List<Location> compute() {
+ try {
+ final List<String> relativePaths = getRelativeSourePathsByType(type);
+ for (String relativePath : relativePaths) {
+ final PsiFile file = mySourcesFinder.findSourceFile(relativePath, myDebugProcess.getProject(), myScope);
+ if(file != null && file.equals(position.getFile())) {
+ return getLocationsOfLine(type, getSourceName(file.getName(), type), relativePath, position.getLine() + 1);
+ }
+ }
+ }
+ catch(ObjectCollectedException ignored) {
+ }
+ catch(AbsentInformationException ignored) {
+ }
+ catch(ClassNotPreparedException ignored) {
+ }
+ catch (InternalError e) {
+ myDebugProcess.getExecutionResult().getProcessHandler().notifyTextAvailable(
+ DebuggerBundle.message("internal.error.locations.of.line", type.name()), ProcessOutputTypes.SYSTEM);
+ }
+ return null;
+ }
+
+ // Finds exact server file name (from available in type)
+ // This is needed because some servers (e.g. WebSphere) put not exact file name such as 'A.jsp '
+ private String getSourceName(final String name, final ReferenceType type) throws AbsentInformationException {
+ for(String sourceNameFromType: type.sourceNames(myStratumId)) {
+ if (sourceNameFromType.indexOf(name) >= 0) {
+ return sourceNameFromType;
+ }
+ }
+ return name;
+ }
+ });
+ }
+
+ protected List<String> getRelativeSourePathsByType(final ReferenceType type) throws AbsentInformationException {
+ final List<String> paths = type.sourcePaths(myStratumId);
+ final ArrayList<String> relativePaths = new ArrayList<String>();
+ for (String path : paths) {
+ relativePaths.add(getRelativePath(path));
+ }
+ return relativePaths;
+ }
+
+ protected List<Location> getLocationsOfLine(final ReferenceType type, final String fileName,
+ final String relativePath, final int lineNumber) throws AbsentInformationException {
+ return type.locationsOfLine(myStratumId, fileName, lineNumber);
+ }
+
+ public ClassPrepareRequest createPrepareRequest(final ClassPrepareRequestor requestor, final SourcePosition position)
+ throws NoDataException {
+ checkSourcePositionFileType(position);
+
+ return myDebugProcess.getRequestsManager().createClassPrepareRequest(new ClassPrepareRequestor() {
+ public void processClassPrepare(DebugProcess debuggerProcess, ReferenceType referenceType) {
+ onClassPrepare(debuggerProcess, referenceType, position, requestor);
+ }
+ }, GENERATED_CLASS_PATTERN);
+ }
+
+ protected void onClassPrepare(final DebugProcess debuggerProcess, final ReferenceType referenceType,
+ final SourcePosition position, final ClassPrepareRequestor requestor) {
+ try {
+ if(locationsOfClassAt(referenceType, position) != null) {
+ requestor.processClassPrepare(debuggerProcess, referenceType);
+ }
+ }
+ catch (NoDataException e) {
+ }
+ }
+
+ protected String getRelativePath(String sourcePath) {
+
+ if (sourcePath != null) {
+ sourcePath = sourcePath.trim();
+ String generatedClassesPackage = getGeneratedClassesPackage();
+ final String prefix = generatedClassesPackage.replace('.', File.separatorChar);
+
+ if (sourcePath.startsWith(prefix)) {
+ sourcePath = sourcePath.substring(prefix.length());
+ if (sourcePath.startsWith(File.separator)) {
+ sourcePath = sourcePath.substring(1);
+ }
+ }
+ }
+
+ return sourcePath;
+ }
+
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/JVMDebugProvider.java b/java/debugger/openapi/src/com/intellij/debugger/engine/JVMDebugProvider.java
new file mode 100644
index 0000000..15fde83
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/JVMDebugProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2010 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.engine;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiFile;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public interface JVMDebugProvider {
+ ExtensionPointName<JVMDebugProvider> EP_NAME = ExtensionPointName.create("com.intellij.debugger.jvmDebugProvider");
+
+ boolean supportsJVMDebugging(PsiFile file);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/SourcesFinder.java b/java/debugger/openapi/src/com/intellij/debugger/engine/SourcesFinder.java
new file mode 100644
index 0000000..106499b
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/SourcesFinder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: May 23, 2006
+ */
+public interface SourcesFinder<Scope> {
+ /**
+ * Searches for source file within the deployedModules
+ * @param relPath relative path of the source to be found (fetched from the class file)
+ * @param project
+ * @param scope a search scope
+ */
+ @Nullable
+ PsiFile findSourceFile(String relPath, Project project, Scope scope);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/StackFrameContext.java b/java/debugger/openapi/src/com/intellij/debugger/engine/StackFrameContext.java
new file mode 100644
index 0000000..442f2c7
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/StackFrameContext.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.debugger.engine.jdi.StackFrameProxy;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: lex
+ * Date: Jun 3, 2003
+ * Time: 5:58:58 PM
+ * To change this template use Options | File Templates.
+ */
+public interface StackFrameContext {
+ @Nullable
+ StackFrameProxy getFrameProxy();
+ DebugProcess getDebugProcess();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/SuspendContext.java b/java/debugger/openapi/src/com/intellij/debugger/engine/SuspendContext.java
new file mode 100644
index 0000000..ae89344
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/SuspendContext.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2009 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.engine;
+
+import com.intellij.debugger.engine.jdi.ThreadReferenceProxy;
+
+public interface SuspendContext extends StackFrameContext {
+ public int getSuspendPolicy();
+
+ ThreadReferenceProxy getThread();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java b/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java
new file mode 100644
index 0000000..782bf34
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2011 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.engine;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Max Medvedev
+ */
+public abstract class TopLevelParentClassProvider {
+ private static final ExtensionPointName<TopLevelParentClassProvider> EP_NAME =
+ ExtensionPointName.create("com.intellij.topLevelClassProvider");
+
+ public static PsiClass getTopLevelParentClass(PsiClass psiClass) {
+ for (TopLevelParentClassProvider provider : EP_NAME.getExtensions()) {
+ final PsiClass custom = provider.getCustomTopLevelParentClass(psiClass);
+ if (custom != null) return custom;
+ }
+
+ PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
+ while (enclosing != null) {
+ psiClass = enclosing;
+ enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
+ }
+ return psiClass;
+ }
+
+ @Nullable
+ protected abstract PsiClass getCustomTopLevelParentClass(PsiClass psiClass);
+
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactory.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactory.java
new file mode 100644
index 0000000..f7ceafc
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+
+import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.JavaCodeFragment;
+import com.intellij.psi.PsiElement;
+
+public abstract class CodeFragmentFactory {
+ public static final ExtensionPointName<CodeFragmentFactory> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.debugger.codeFragmentFactory");
+
+ public abstract JavaCodeFragment createCodeFragment(TextWithImports item, PsiElement context, Project project);
+
+ public abstract JavaCodeFragment createPresentationCodeFragment(TextWithImports item, PsiElement context, Project project);
+
+ public abstract boolean isContextAccepted(PsiElement contextElement);
+
+ public abstract LanguageFileType getFileType();
+
+ /**
+ * In case if createCodeFragment returns java code use
+ * com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl#getInstance()
+ * @return builder, which can evaluate expression for your code fragment
+ */
+ public abstract EvaluatorBuilder getEvaluatorBuilder();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentKind.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentKind.java
new file mode 100644
index 0000000..34766d2
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/CodeFragmentKind.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+public enum CodeFragmentKind {
+ EXPRESSION, CODE_BLOCK
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateException.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateException.java
new file mode 100644
index 0000000..30dac08
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateException.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.sun.jdi.InvocationException;
+import com.sun.jdi.ObjectReference;
+import org.jetbrains.annotations.Nullable;
+
+public class EvaluateException extends Exception {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.evaluation.EvaluateException");
+ private ObjectReference myTargetException;
+
+ public EvaluateException(final String message) {
+ super(message);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(message);
+ }
+ }
+
+ public EvaluateException(String msg, Throwable th) {
+ super(msg, th);
+ if (th instanceof EvaluateException) {
+ myTargetException = ((EvaluateException)th).getExceptionFromTargetVM();
+ }
+ else if(th instanceof InvocationException){
+ InvocationException invocationException = (InvocationException) th;
+ myTargetException = invocationException.exception();
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(msg);
+ }
+ }
+
+ @Nullable
+ public ObjectReference getExceptionFromTargetVM() {
+ return myTargetException;
+ }
+
+ public void setTargetException(final ObjectReference targetException) {
+ myTargetException = targetException;
+ }
+
+ public String getMessage() {
+ final String errorMessage = super.getMessage();
+ if (errorMessage != null) {
+ return errorMessage;
+ }
+ final Throwable cause = getCause();
+ final String causeMessage = cause != null? cause.getMessage() : null;
+ if (causeMessage != null) {
+ return causeMessage;
+ }
+ return "unknown error";
+ }
+}
\ No newline at end of file
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateExceptionUtil.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateExceptionUtil.java
new file mode 100644
index 0000000..4d5536c
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluateExceptionUtil.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.sun.jdi.*;
+
+/**
+ * @author lex
+ */
+public class EvaluateExceptionUtil {
+ public static final EvaluateException INCONSISTEND_DEBUG_INFO = createEvaluateException(DebuggerBundle.message("evaluation.error.inconsistent.debug.info"));
+ public static final EvaluateException BOOLEAN_EXPECTED = createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.value.expected.in.condition"));
+ public static final EvaluateException PROCESS_EXITED = createEvaluateException(DebuggerBundle.message("evaluation.error.process.exited"));
+ public static final EvaluateException NULL_STACK_FRAME = createEvaluateException(DebuggerBundle.message("evaluation.error.stack.frame.unavailable"));
+ public static final EvaluateException NESTED_EVALUATION_ERROR = createEvaluateException(DebuggerBundle.message("evaluation.error.nested.evaluation"));
+ public static final EvaluateException INVALID_DEBUG_INFO = createEvaluateException(DebuggerBundle.message("evaluation.error.sources.out.of.sync"));
+ public static final EvaluateException CANNOT_FIND_SOURCE_CLASS = createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.find.stackframe.source"));
+ public static final EvaluateException OBJECT_WAS_COLLECTED = createEvaluateException(DebuggerBundle.message("evaluation.error.object.collected"));
+ public static final EvaluateException ARRAY_WAS_COLLECTED = createEvaluateException(DebuggerBundle.message("evaluation.error.array.collected"));
+ public static final EvaluateException THREAD_WAS_RESUMED = createEvaluateException(DebuggerBundle.message("evaluation.error.thread.resumed"));
+ public static final EvaluateException DEBUG_INFO_UNAVAILABLE = createEvaluateException(DebuggerBundle.message("evaluation.error.debug.info.unavailable"));
+
+ private EvaluateExceptionUtil() {
+ }
+
+ public static EvaluateException createEvaluateException(Throwable th) {
+ return createEvaluateException(null, th);
+ }
+
+ public static EvaluateException createEvaluateException(String msg, Throwable th) {
+ final String message = msg != null? msg + ": " + reason(th) : reason(th);
+ return new EvaluateException(message, th instanceof EvaluateException ? th.getCause() : th);
+ }
+
+ public static EvaluateException createEvaluateException(String reason) {
+ return new EvaluateException(reason, null);
+ }
+
+ private static String reason(Throwable th) {
+ if(th instanceof InvalidTypeException) {
+ final String originalReason = th.getMessage();
+ return DebuggerBundle.message("evaluation.error.type.mismatch") + (originalReason != null? " " + originalReason : "");
+ }
+ else if(th instanceof AbsentInformationException) {
+ return DebuggerBundle.message("evaluation.error.debug.info.unavailable");
+ }
+ else if(th instanceof ClassNotLoadedException) {
+ return DebuggerBundle.message("evaluation.error.class.not.loaded", ((ClassNotLoadedException)th).className());
+ }
+ else if(th instanceof ClassNotPreparedException) {
+ return th.getMessage();
+ }
+ else if(th instanceof IncompatibleThreadStateException) {
+ return DebuggerBundle.message("evaluation.error.thread.not.at.breakpoint");
+ }
+ else if(th instanceof InconsistentDebugInfoException) {
+ return DebuggerBundle.message("evaluation.error.inconsistent.debug.info");
+ }
+ else if(th instanceof ObjectCollectedException) {
+ return DebuggerBundle.message("evaluation.error.object.collected");
+ }
+ else if(th instanceof InvocationException){
+ InvocationException invocationException = (InvocationException) th;
+ return DebuggerBundle.message("evaluation.error.method.exception", invocationException.exception().referenceType().name());
+ }
+ else if(th instanceof EvaluateException) {
+ return th.getMessage();
+ }
+ else {
+ return th.getClass().getName() + " : " + (th.getMessage() != null ? th.getMessage() : "");
+ }
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContext.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContext.java
new file mode 100644
index 0000000..e50ef43
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContext.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+
+import com.intellij.debugger.engine.DebugProcess;
+import com.intellij.debugger.engine.StackFrameContext;
+import com.intellij.debugger.engine.SuspendContext;
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ClassLoaderReference;
+import com.sun.jdi.Value;
+
+public interface EvaluationContext extends StackFrameContext{
+ DebugProcess getDebugProcess();
+
+ EvaluationContext createEvaluationContext(Value value);
+
+ SuspendContext getSuspendContext();
+
+ Project getProject();
+
+ ClassLoaderReference getClassLoader() throws EvaluateException;
+
+ Value getThisObject();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java
new file mode 100644
index 0000000..0ae3e64
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation;
+
+import com.intellij.openapi.fileTypes.FileType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface TextWithImports {
+ String getText();
+
+ void setText(String newText);
+
+ @NotNull
+ String getImports();
+
+ CodeFragmentKind getKind();
+
+ boolean isEmpty();
+
+ String toExternalForm();
+
+ @Nullable
+ FileType getFileType();
+
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilder.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilder.java
new file mode 100644
index 0000000..66bb45a
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilder.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2011 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.engine.evaluation.expression;
+
+import com.intellij.debugger.SourcePosition;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.TextWithImports;
+import com.intellij.psi.PsiElement;
+
+/**
+ * Main interface to extend evaluation for different JVM languages.
+ * @see com.intellij.debugger.engine.evaluation.CodeFragmentFactory
+ */
+public interface EvaluatorBuilder {
+ ExpressionEvaluator build(PsiElement codeFragment, final SourcePosition position) throws EvaluateException;
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluator.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluator.java
new file mode 100644
index 0000000..18528c2
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2009 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.engine.evaluation.expression;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContext;
+import com.sun.jdi.Value;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: lex
+ * Date: Jul 15, 2003
+ * Time: 1:44:35 PM
+ * To change this template use Options | File Templates.
+ */
+public interface ExpressionEvaluator {
+ //call evaluate before
+ public Value getValue();
+
+ //call evaluate before
+ public Modifier getModifier();
+
+ public Value evaluate(final EvaluationContext context) throws EvaluateException;
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/Modifier.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/Modifier.java
new file mode 100644
index 0000000..809feac
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/expression/Modifier.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 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.
+ */
+
+/*
+ * Interface Modifier
+ * @author Jeka
+ */
+package com.intellij.debugger.engine.evaluation.expression;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.ui.tree.NodeDescriptor;
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.ClassNotLoadedException;
+import com.sun.jdi.InvalidTypeException;
+import com.sun.jdi.Type;
+import com.sun.jdi.Value;
+
+public interface Modifier {
+ boolean canInspect();
+
+ boolean canSetValue();
+ /**
+ * sets the value to the expression
+ */
+ void setValue(Value value) throws ClassNotLoadedException, InvalidTypeException, EvaluateException;
+
+ /**
+ * @return the expected type of the expression or null is class was not loaded
+ */
+ Type getExpectedType() throws ClassNotLoadedException, EvaluateException;
+
+ NodeDescriptor getInspectItem(Project project);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/LocalVariableProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/LocalVariableProxy.java
new file mode 100644
index 0000000..8efdaae
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/LocalVariableProxy.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+public interface LocalVariableProxy extends ObjectReferenceProxy{
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ObjectReferenceProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ObjectReferenceProxy.java
new file mode 100644
index 0000000..3ec95fb
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ObjectReferenceProxy.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+public interface ObjectReferenceProxy {
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java
new file mode 100644
index 0000000..7e0b6ee
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.sun.jdi.ClassLoaderReference;
+import com.sun.jdi.Location;
+import com.sun.jdi.StackFrame;
+
+public interface StackFrameProxy extends ObjectReferenceProxy{
+ StackFrame getStackFrame() throws EvaluateException;
+
+ int getFrameIndex() throws EvaluateException ;
+
+ VirtualMachineProxy getVirtualMachine();
+
+ Location location() throws EvaluateException;
+
+ ClassLoaderReference getClassLoader() throws EvaluateException;
+
+ LocalVariableProxy visibleVariableByName(String name) throws EvaluateException;
+
+ ThreadReferenceProxy threadProxy();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadGroupReferenceProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadGroupReferenceProxy.java
new file mode 100644
index 0000000..146ab75
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadGroupReferenceProxy.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+import com.sun.jdi.ThreadGroupReference;
+
+public interface ThreadGroupReferenceProxy extends ObjectReferenceProxy{
+ ThreadGroupReference getThreadGroupReference();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadReferenceProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadReferenceProxy.java
new file mode 100644
index 0000000..9723516
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/ThreadReferenceProxy.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.sun.jdi.ThreadReference;
+
+public interface ThreadReferenceProxy extends ObjectReferenceProxy{
+ VirtualMachineProxy getVirtualMachine();
+ ThreadReference getThreadReference();
+
+ StackFrameProxy frame(int i) throws EvaluateException;
+
+ int frameCount() throws EvaluateException;
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/VirtualMachineProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/VirtualMachineProxy.java
new file mode 100644
index 0000000..4f4cb82
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/VirtualMachineProxy.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2009 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.engine.jdi;
+
+import com.intellij.debugger.engine.DebugProcess;
+import com.sun.jdi.ReferenceType;
+
+import java.util.List;
+
+/**
+ * @author lex
+ */
+public interface VirtualMachineProxy {
+ List<ReferenceType> allClasses();
+
+ boolean versionHigher(String version);
+
+ boolean canWatchFieldModification();
+
+ boolean canWatchFieldAccess();
+
+ boolean canInvokeMethods();
+
+ DebugProcess getDebugProcess();
+
+ List<ReferenceType> nestedTypes(ReferenceType refType);
+
+ List<ReferenceType> classesByName(String s);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerCommand.java b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerCommand.java
new file mode 100644
index 0000000..a39d83f
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerCommand.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2009 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.engine.managerThread;
+
+public interface DebuggerCommand {
+ void action();
+
+ void commandCancelled();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerManagerThread.java b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerManagerThread.java
new file mode 100644
index 0000000..8d19667
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/DebuggerManagerThread.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2009 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.engine.managerThread;
+
+public interface DebuggerManagerThread {
+ /**
+ * executes command in DebuggerManagerThread
+ *
+ * @param command
+ */
+ void invokeCommand(DebuggerCommand command);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/SuspendContextCommand.java b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/SuspendContextCommand.java
new file mode 100644
index 0000000..13d75fe
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/managerThread/SuspendContextCommand.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2009 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.engine.managerThread;
+
+import com.intellij.debugger.engine.SuspendContext;
+
+public interface SuspendContextCommand extends DebuggerCommand{
+ SuspendContext getSuspendContext();
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/package.html b/java/debugger/openapi/src/com/intellij/debugger/package.html
new file mode 100644
index 0000000..e9fa628
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/package.html
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright 2000-2007 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.
+ -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html><body bgcolor="white">
+Provides interfaces for interacting with IDEA's debugger. The main extensibility
+point of the debugger is the possibility for a plugin to provide custom mapping of
+positions in compiled classes to source code lines, which is mostly necessary for
+JSP debugging. Such mapping is provided through the {@link PositionManager} interface.
+One standard implementation of this interface for application servers compatible
+with the JSR-45 specification is provided by the {@link JSR45PositionManager} class.
+Another implementation of this interface, which can be used as an example for the debugger
+API, is found in the Tomcat plugin.
+</body></html>
diff --git a/java/debugger/openapi/src/com/intellij/debugger/requests/ClassPrepareRequestor.java b/java/debugger/openapi/src/com/intellij/debugger/requests/ClassPrepareRequestor.java
new file mode 100644
index 0000000..e58e052
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/requests/ClassPrepareRequestor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2009 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.requests;
+
+import com.intellij.debugger.engine.DebugProcess;
+import com.sun.jdi.ReferenceType;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: lex
+ * Date: Jun 27, 2003
+ * Time: 7:27:41 PM
+ * To change this template use Options | File Templates.
+ */
+public interface ClassPrepareRequestor extends Requestor {
+ void processClassPrepare(DebugProcess debuggerProcess, final ReferenceType referenceType);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/requests/RequestManager.java b/java/debugger/openapi/src/com/intellij/debugger/requests/RequestManager.java
new file mode 100644
index 0000000..bd949fd
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/requests/RequestManager.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2009 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.requests;
+
+import com.intellij.debugger.SourcePosition;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.EventRequest;
+
+public interface RequestManager {
+ void callbackOnPrepareClasses(ClassPrepareRequestor requestor, String classOrPatternToBeLoaded);
+ void callbackOnPrepareClasses(ClassPrepareRequestor requestor, SourcePosition classPosition) throws EvaluateException;
+
+ ClassPrepareRequest createClassPrepareRequest(ClassPrepareRequestor requestor, String pattern);
+
+ void enableRequest(EventRequest request);
+
+ void setInvalid(Requestor requestor, String message);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/requests/Requestor.java b/java/debugger/openapi/src/com/intellij/debugger/requests/Requestor.java
new file mode 100644
index 0000000..9a13832
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/requests/Requestor.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2009 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.requests;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: lex
+ * Date: Jun 27, 2003
+ * Time: 8:06:36 PM
+ * To change this template use Options | File Templates.
+ */
+public interface Requestor {
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java b/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java
new file mode 100644
index 0000000..4ed6de6
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 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.ui.tree;
+
+import com.intellij.openapi.util.Key;
+
+public interface NodeDescriptor {
+
+ String getName();
+ String getLabel();
+
+ <T> T getUserData(Key<T> key);
+ <T> void putUserData(Key<T> key, T value);
+
+ void displayAs(NodeDescriptor descriptor);
+
+ void setAncestor(NodeDescriptor oldDescriptor);
+}