"Resolve window" for debugging purposes
This commit is contained in:
@@ -32,4 +32,9 @@ public class AutoCastReceiver extends AbstractReceiverDescriptor {
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return original.accept(visitor, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + original + " as " + getType() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,4 +19,9 @@ public class DefaultValueArgument implements ResolvedValueArgument {
|
||||
public List<JetExpression> getArgumentExpressions() {
|
||||
return Collections.emptyList(); //throw new UnsupportedOperationException("Look into the default value of the parameter");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "|DEFAULT|";
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -29,4 +29,9 @@ public class ExpressionValueArgument implements ResolvedValueArgument {
|
||||
if (expression == null) return Collections.emptyList();
|
||||
return Collections.singletonList(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return expression.getText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -17,4 +18,17 @@ public class VarargValueArgument implements ResolvedValueArgument {
|
||||
public List<JetExpression> getArgumentExpressions() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("vararg:{");
|
||||
for (Iterator<JetExpression> iterator = values.iterator(); iterator.hasNext(); ) {
|
||||
JetExpression expression = iterator.next();
|
||||
builder.append(expression.getText());
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
return builder.append("}").toString();
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -11,6 +11,7 @@ import java.util.List;
|
||||
*/
|
||||
public interface AutoCastService {
|
||||
AutoCastService NO_AUTO_CASTS = new AutoCastService() {
|
||||
@NotNull
|
||||
@Override
|
||||
public DataFlowInfo getDataFlowInfo() {
|
||||
return DataFlowInfo.EMPTY;
|
||||
@@ -21,13 +22,17 @@ public interface AutoCastService {
|
||||
return !receiver.getType().isNullable();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor) {
|
||||
public List<ReceiverDescriptor> getVariantsForReceiver(@NotNull ReceiverDescriptor receiverDescriptor) {
|
||||
return Collections.singletonList(receiverDescriptor);
|
||||
}
|
||||
};
|
||||
|
||||
List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor);
|
||||
@NotNull
|
||||
List<ReceiverDescriptor> getVariantsForReceiver(@NotNull ReceiverDescriptor receiverDescriptor);
|
||||
|
||||
@NotNull
|
||||
DataFlowInfo getDataFlowInfo();
|
||||
|
||||
boolean isNotNull(@NotNull ReceiverDescriptor receiver);
|
||||
|
||||
+3
-1
@@ -18,11 +18,13 @@ public class AutoCastServiceImpl implements AutoCastService {
|
||||
this.bindingContext = bindingContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor) {
|
||||
public List<ReceiverDescriptor> getVariantsForReceiver(@NotNull ReceiverDescriptor receiverDescriptor) {
|
||||
return AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataFlowInfo getDataFlowInfo() {
|
||||
return dataFlowInfo;
|
||||
|
||||
+5
@@ -37,4 +37,9 @@ public class ClassReceiver implements ThisReceiverDescriptor {
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitClassReceiver(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Class{" + getType() + "}";
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -25,4 +25,9 @@ public class ExpressionReceiver extends AbstractReceiverDescriptor implements Re
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitExpressionReceiver(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getType() + " {" + expression + ": " + expression.getText() + "}";
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -27,4 +27,9 @@ public class ExtensionReceiver extends AbstractReceiverDescriptor implements Thi
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitExtensionReceiver(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getType() + "Ext{" + descriptor + "}";
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -18,4 +18,9 @@ public class TransientReceiver extends AbstractReceiverDescriptor {
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitTransientReceiver(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{Transient} : " + getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,5 +61,8 @@
|
||||
<toolWindow id="CodeWindow"
|
||||
factoryClass="org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow$Factory"
|
||||
anchor="right"/>
|
||||
<toolWindow id="ResolveWindow"
|
||||
factoryClass="org.jetbrains.jet.plugin.internal.resolvewindow.ResolveToolwindow$Factory"
|
||||
anchor="right"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -208,7 +208,7 @@ public class BytecodeToolwindow extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Location {
|
||||
public static class Location {
|
||||
final Editor editor;
|
||||
final long modificationStamp;
|
||||
final int startOffset;
|
||||
@@ -225,6 +225,22 @@ public class BytecodeToolwindow extends JPanel {
|
||||
return new Location(editor);
|
||||
}
|
||||
|
||||
public Editor getEditor() {
|
||||
return editor;
|
||||
}
|
||||
|
||||
public long getModificationStamp() {
|
||||
return modificationStamp;
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
public int getEndOffset() {
|
||||
return endOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.internal.resolvewindow;
|
||||
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowFactory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
|
||||
|
||||
public class ResolveToolwindow extends JPanel {
|
||||
public static class Factory implements ToolWindowFactory {
|
||||
@Override
|
||||
public void createToolWindowContent(Project project, ToolWindow toolWindow) {
|
||||
toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(new ResolveToolwindow(project), "", false));
|
||||
}
|
||||
}
|
||||
|
||||
private static final int UPDATE_DELAY = 500;
|
||||
private final Editor myEditor;
|
||||
private final Alarm myUpdateAlarm;
|
||||
private BytecodeToolwindow.Location myCurrentLocation;
|
||||
private final Project myProject;
|
||||
|
||||
|
||||
public ResolveToolwindow(Project project) {
|
||||
super(new BorderLayout());
|
||||
myProject = project;
|
||||
myEditor = EditorFactory.getInstance().createEditor(EditorFactory.getInstance().createDocument(""), project, JetFileType.INSTANCE, true);
|
||||
add(myEditor.getComponent());
|
||||
myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
|
||||
myUpdateAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myUpdateAlarm.addRequest(this, UPDATE_DELAY);
|
||||
BytecodeToolwindow.Location location = BytecodeToolwindow.Location.fromEditor(FileEditorManager.getInstance(myProject).getSelectedTextEditor());
|
||||
if (!Comparing.equal(location, myCurrentLocation)) {
|
||||
render(location, myCurrentLocation);
|
||||
myCurrentLocation = location;
|
||||
}
|
||||
}
|
||||
}, UPDATE_DELAY);
|
||||
}
|
||||
|
||||
private void render(BytecodeToolwindow.Location location, BytecodeToolwindow.Location oldLocation) {
|
||||
Editor editor = location.getEditor();
|
||||
if (editor == null) {
|
||||
setText("No editor");
|
||||
}
|
||||
else {
|
||||
VirtualFile vFile = ((EditorEx) editor).getVirtualFile();
|
||||
if (vFile == null) {
|
||||
setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
PsiFile psiFile = PsiManager.getInstance(myProject).findFile(vFile);
|
||||
if (!(psiFile instanceof JetFile)) {
|
||||
setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int startOffset = location.getStartOffset();
|
||||
int endOffset = location.getEndOffset();
|
||||
if (oldLocation == null || !Comparing.equal(oldLocation.getEditor(), location.getEditor())
|
||||
|| oldLocation.getStartOffset() != startOffset
|
||||
|| oldLocation.getEndOffset() != endOffset) {
|
||||
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
|
||||
|
||||
|
||||
PsiElement elementAtOffset;
|
||||
if (startOffset == endOffset) {
|
||||
elementAtOffset = PsiUtilCore.getElementAtOffset(psiFile, startOffset);
|
||||
}
|
||||
else {
|
||||
PsiElement start = PsiUtilCore.getElementAtOffset(psiFile, startOffset);
|
||||
System.out.println("start = " + start.getText());
|
||||
PsiElement end = PsiUtilCore.getElementAtOffset(psiFile, endOffset - 1);
|
||||
System.out.println("end = " + end.getText());
|
||||
elementAtOffset = PsiTreeUtil.findCommonParent(start, end);
|
||||
System.out.println("elementAtOffset = " + elementAtOffset.getText());
|
||||
}
|
||||
|
||||
PsiElement currentElement = elementAtOffset;
|
||||
|
||||
boolean callFound = false;
|
||||
while (currentElement != null && !(currentElement instanceof PsiFile)) {
|
||||
if (currentElement instanceof JetElement) {
|
||||
JetElement atOffset = (JetElement) currentElement;
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, (JetElement) atOffset);
|
||||
if (resolvedCall != null) {
|
||||
setText(renderCall(resolvedCall) + "\n===\n" + currentElement + ": " + currentElement.getText());
|
||||
callFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
currentElement = currentElement.getParent();
|
||||
}
|
||||
if (!callFound) {
|
||||
|
||||
JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset
|
||||
: PsiTreeUtil.getParentOfType(elementAtOffset, JetExpression.class);
|
||||
if (parentExpression != null) {
|
||||
JetType type = bindingContext.get(EXPRESSION_TYPE, parentExpression);
|
||||
String text = parentExpression + "|" + parentExpression.getText() + "| : " + type;
|
||||
if (parentExpression instanceof JetReferenceExpression) {
|
||||
JetReferenceExpression referenceExpression = (JetReferenceExpression) parentExpression;
|
||||
DeclarationDescriptor target = bindingContext.get(REFERENCE_TARGET, referenceExpression);
|
||||
text += "\nReference target: \n" + target;
|
||||
}
|
||||
setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String renderCall(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
|
||||
ReceiverDescriptor thisObject = resolvedCall.getThisObject();
|
||||
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||
Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = resolvedCall.getValueArguments();
|
||||
|
||||
renderReceiver(receiverArgument, thisObject, builder);
|
||||
builder.append(resultingDescriptor.getName());
|
||||
renderTypeArguments(typeArguments, builder);
|
||||
|
||||
if (resultingDescriptor instanceof FunctionDescriptor) {
|
||||
renderValueArguments(valueArguments, builder);
|
||||
}
|
||||
|
||||
builder.append(" : ").append(resultingDescriptor.getReturnType());
|
||||
|
||||
builder.append("\n");
|
||||
builder.append("\n");
|
||||
|
||||
CallableDescriptor candidateDescriptor = resolvedCall.getCandidateDescriptor();
|
||||
builder.append("Candidate: \n").append(candidateDescriptor).append("\n");
|
||||
if (resultingDescriptor != candidateDescriptor) {
|
||||
builder.append("Result: \n").append(resultingDescriptor).append("\n");
|
||||
}
|
||||
|
||||
builder.append("Receiver: \n").append(receiverArgument).append("\n");
|
||||
builder.append("This object: \n").append(thisObject).append("\n");
|
||||
builder.append("Type args: \n").append(typeArguments).append("\n");
|
||||
builder.append("Value args: \n").append(valueArguments).append("\n");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void renderValueArguments(Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments, StringBuilder builder) {
|
||||
ResolvedValueArgument[] args = new ResolvedValueArgument[valueArguments.size()];
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : valueArguments.entrySet()) {
|
||||
ValueParameterDescriptor key = entry.getKey();
|
||||
ResolvedValueArgument value = entry.getValue();
|
||||
|
||||
args[key.getIndex()] = value;
|
||||
}
|
||||
builder.append("(");
|
||||
for (int i = 0, argsLength = args.length; i < argsLength; i++) {
|
||||
ResolvedValueArgument arg = args[i];
|
||||
builder.append(arg);
|
||||
if (i != argsLength - 1) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
}
|
||||
|
||||
private void renderTypeArguments(Map<TypeParameterDescriptor, JetType> typeArguments, StringBuilder builder) {
|
||||
JetType[] args = new JetType[typeArguments.size()];
|
||||
for (Map.Entry<TypeParameterDescriptor, JetType> entry : typeArguments.entrySet()) {
|
||||
TypeParameterDescriptor key = entry.getKey();
|
||||
JetType value = entry.getValue();
|
||||
args[key.getIndex()] = value;
|
||||
}
|
||||
builder.append("<");
|
||||
for (int i = 0, argsLength = args.length; i < argsLength; i++) {
|
||||
JetType type = args[i];
|
||||
builder.append(type);
|
||||
if (i != argsLength - 1) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
builder.append(">");
|
||||
}
|
||||
|
||||
private void renderReceiver(ReceiverDescriptor receiverArgument, ReceiverDescriptor thisObject, StringBuilder builder) {
|
||||
if (receiverArgument.exists()) {
|
||||
builder.append("/").append(receiverArgument);
|
||||
}
|
||||
|
||||
if (thisObject.exists()) {
|
||||
builder.append("/this=").append(thisObject);
|
||||
}
|
||||
|
||||
if (thisObject.exists() || receiverArgument.exists()) {
|
||||
builder.append("/.");
|
||||
}
|
||||
}
|
||||
|
||||
private void setText(final String text) {
|
||||
new WriteCommandAction(myProject) {
|
||||
@Override
|
||||
protected void run(Result result) throws Throwable {
|
||||
myEditor.getDocument().setText(text);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user