generate line number info (initial); position manager (supports stopping at breakpoints, doesn't support stepping yet)
This commit is contained in:
@@ -45,5 +45,6 @@
|
|||||||
<iconProvider implementation="org.jetbrains.jet.plugin.JetIconProvider"/>
|
<iconProvider implementation="org.jetbrains.jet.plugin.JetIconProvider"/>
|
||||||
<fileTypeIndentOptionsProvider implementation="org.jetbrains.jet.plugin.formatter.JetIndentOptionsProvider"/>
|
<fileTypeIndentOptionsProvider implementation="org.jetbrains.jet.plugin.formatter.JetIndentOptionsProvider"/>
|
||||||
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
|
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
|
||||||
|
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class ClassCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
||||||
state.prepareAnonymousClasses((JetElement) aClass);
|
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||||
|
|
||||||
if (aClass instanceof JetObjectDeclaration) {
|
if (aClass instanceof JetObjectDeclaration) {
|
||||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ public class ClassFileFactory {
|
|||||||
String fqName = namespace.getFQName();
|
String fqName = namespace.getFQName();
|
||||||
NamespaceCodegen codegen = ns2codegen.get(fqName);
|
NamespaceCodegen codegen = ns2codegen.get(fqName);
|
||||||
if (codegen == null) {
|
if (codegen == null) {
|
||||||
codegen = new NamespaceCodegen(newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class"), fqName, state);
|
final ClassVisitor classVisitor = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class");
|
||||||
|
codegen = new NamespaceCodegen(classVisitor, fqName, state, namespace.getContainingFile());
|
||||||
ns2codegen.put(fqName, codegen);
|
ns2codegen.put(fqName, codegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ public class ClosureCodegen {
|
|||||||
funClass,
|
funClass,
|
||||||
new String[0]
|
new String[0]
|
||||||
);
|
);
|
||||||
|
cv.visitSource(fun.getContainingFile().getName(), null);
|
||||||
|
|
||||||
|
|
||||||
generateBridge(name, funDescriptor, cv);
|
generateBridge(name, funDescriptor, cv);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.search.ProjectScope;
|
import com.intellij.psi.search.ProjectScope;
|
||||||
@@ -581,6 +582,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
|
|
||||||
for (int i = 0, statementsSize = statements.size(); i < statementsSize; i++) {
|
for (int i = 0, statementsSize = statements.size(); i < statementsSize; i++) {
|
||||||
JetElement statement = statements.get(i);
|
JetElement statement = statements.get(i);
|
||||||
|
markLineNumber(statement);
|
||||||
if (i == statements.size() - 1) {
|
if (i == statements.size() - 1) {
|
||||||
gen(statement);
|
gen(statement);
|
||||||
}
|
}
|
||||||
@@ -604,6 +606,16 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void markLineNumber(JetElement statement) {
|
||||||
|
final Document document = statement.getContainingFile().getViewProvider().getDocument();
|
||||||
|
if (document != null) {
|
||||||
|
int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset());
|
||||||
|
Label label = new Label();
|
||||||
|
v.visitLabel(label);
|
||||||
|
v.visitLineNumber(lineNumber, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitReturnExpression(JetReturnExpression expression) {
|
public void visitReturnExpression(JetReturnExpression expression) {
|
||||||
final JetExpression returnedExpression = expression.getReturnedExpression();
|
final JetExpression returnedExpression = expression.getReturnedExpression();
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void compile(JetFile psiFile) {
|
public void compile(JetFile psiFile) {
|
||||||
final JetNamespace namespace = ((JetFile) psiFile).getRootNamespace();
|
final JetNamespace namespace = psiFile.getRootNamespace();
|
||||||
NamespaceCodegen codegen = forNamespace(namespace);
|
NamespaceCodegen codegen = forNamespace(namespace);
|
||||||
final BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
final BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||||
bindingContexts.push(bindingContext);
|
bindingContexts.push(bindingContext);
|
||||||
@@ -101,7 +101,7 @@ public class GenerationState {
|
|||||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"), false);
|
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareAnonymousClasses(JetElement aClass) {
|
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
|
||||||
aClass.acceptChildren(new JetVisitor() {
|
aClass.acceptChildren(new JetVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitJetElement(JetElement element) {
|
public void visitJetElement(JetElement element) {
|
||||||
@@ -111,7 +111,7 @@ public class GenerationState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||||
getTypeMapper().classNameForAnonymousClass(expression.getObjectDeclaration());
|
typeMapper.classNameForAnonymousClass(expression.getObjectDeclaration());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
superClass,
|
superClass,
|
||||||
interfaces.toArray(new String[interfaces.size()])
|
interfaces.toArray(new String[interfaces.size()])
|
||||||
);
|
);
|
||||||
|
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String jvmName() {
|
private String jvmName() {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
|||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
superInterfaces.toArray(new String[superInterfaces.size()])
|
superInterfaces.toArray(new String[superInterfaces.size()])
|
||||||
);
|
);
|
||||||
|
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Set<String> getSuperInterfaces(JetClassOrObject aClass, final BindingContext bindingContext) {
|
static Set<String> getSuperInterfaces(JetClassOrObject aClass, final BindingContext bindingContext) {
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ public class JetTypeMapper {
|
|||||||
return Type.getType("L" + jvmNameForDelegatingImplementation(classDescriptor) + ";");
|
return Type.getType("L" + jvmNameForDelegatingImplementation(classDescriptor) + ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
static String jvmName(JetNamespace namespace) {
|
public static String jvmName(JetNamespace namespace) {
|
||||||
return NamespaceCodegen.getJVMClassName(namespace.getFQName());
|
return NamespaceCodegen.getJVMClassName(namespace.getFQName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,4 +572,15 @@ public class JetTypeMapper {
|
|||||||
classNamesForAnonymousClasses.put(expression, className);
|
classNamesForAnonymousClasses.put(expression, className);
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<String> allJvmNames(JetClassOrObject jetClass) {
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
final ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(jetClass);
|
||||||
|
if (classDescriptor != null) {
|
||||||
|
result.add(jvmName(classDescriptor, OwnerKind.INTERFACE));
|
||||||
|
result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION));
|
||||||
|
result.add(jvmName(classDescriptor, OwnerKind.DELEGATING_IMPLEMENTATION));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
@@ -15,7 +16,7 @@ public class NamespaceCodegen {
|
|||||||
private final ClassVisitor v;
|
private final ClassVisitor v;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
|
||||||
public NamespaceCodegen(ClassVisitor v, String fqName, GenerationState state) {
|
public NamespaceCodegen(ClassVisitor v, String fqName, GenerationState state, PsiFile sourceFile) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
@@ -27,6 +28,8 @@ public class NamespaceCodegen {
|
|||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
new String[0]
|
new String[0]
|
||||||
);
|
);
|
||||||
|
// TODO figure something out for a namespace that spans multiple files
|
||||||
|
v.visitSource(sourceFile.getName(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetNamespace namespace) {
|
public void generate(JetNamespace namespace) {
|
||||||
@@ -36,7 +39,7 @@ public class NamespaceCodegen {
|
|||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
final ClassCodegen classCodegen = state.forClass();
|
final ClassCodegen classCodegen = state.forClass();
|
||||||
|
|
||||||
state.prepareAnonymousClasses(namespace);
|
GenerationState.prepareAnonymousClasses(namespace, state.getTypeMapper());
|
||||||
|
|
||||||
if (hasNonConstantPropertyInitializers(namespace)) {
|
if (hasNonConstantPropertyInitializers(namespace)) {
|
||||||
generateStaticInitializers(namespace);
|
generateStaticInitializers(namespace);
|
||||||
|
|||||||
@@ -34,4 +34,9 @@ public class JetFileType extends LanguageFileType {
|
|||||||
public Icon getIcon() {
|
public Icon getIcon() {
|
||||||
return Icons.PROJECT_ICON;
|
return Icons.PROJECT_ICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJVMDebuggingSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package org.jetbrains.jet.plugin.debugger;
|
||||||
|
|
||||||
|
import com.intellij.debugger.NoDataException;
|
||||||
|
import com.intellij.debugger.PositionManager;
|
||||||
|
import com.intellij.debugger.SourcePosition;
|
||||||
|
import com.intellij.debugger.engine.DebugProcess;
|
||||||
|
import com.intellij.debugger.requests.ClassPrepareRequestor;
|
||||||
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import com.sun.jdi.AbsentInformationException;
|
||||||
|
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 org.jetbrains.jet.codegen.GenerationState;
|
||||||
|
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||||
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public class JetPositionManager implements PositionManager {
|
||||||
|
private final DebugProcess myDebugProcess;
|
||||||
|
private WeakHashMap<PsiFile, JetTypeMapper> myTypeMappers = new WeakHashMap<PsiFile, JetTypeMapper>();
|
||||||
|
|
||||||
|
public JetPositionManager(DebugProcess debugProcess) {
|
||||||
|
myDebugProcess = debugProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public SourcePosition getSourcePosition(@Nullable Location location) throws NoDataException {
|
||||||
|
PsiFile psiFile = getPsiFileByLocation(location);
|
||||||
|
throw new NoDataException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiFile getPsiFileByLocation(Location location) {
|
||||||
|
final ReferenceType referenceType = location.declaringType();
|
||||||
|
if (referenceType == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<ReferenceType> getAllClasses(SourcePosition sourcePosition) throws NoDataException {
|
||||||
|
if (!(sourcePosition.getFile() instanceof JetFile)) {
|
||||||
|
throw new NoDataException();
|
||||||
|
}
|
||||||
|
final Collection<String> names = classNamesForPosition(sourcePosition);
|
||||||
|
List<ReferenceType> result = new ArrayList<ReferenceType>();
|
||||||
|
for (String name : names) {
|
||||||
|
result.addAll(myDebugProcess.getVirtualMachineProxy().classesByName(name));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<String> classNamesForPosition(SourcePosition sourcePosition) {
|
||||||
|
final JetFile file = (JetFile) sourcePosition.getFile();
|
||||||
|
JetTypeMapper typeMapper = prepareTypeMapper(file);
|
||||||
|
final Collection<String> names = new ArrayList<String>();
|
||||||
|
JetClassOrObject jetClass = PsiTreeUtil.getParentOfType(sourcePosition.getElementAt(), JetClassOrObject.class);
|
||||||
|
if (jetClass != null) {
|
||||||
|
names.addAll(typeMapper.allJvmNames(jetClass));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JetNamespace namespace = PsiTreeUtil.getParentOfType(sourcePosition.getElementAt(), JetNamespace.class);
|
||||||
|
if (namespace != null) {
|
||||||
|
names.add(JetTypeMapper.jvmName(namespace));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
names.add(JetTypeMapper.jvmName(file.getRootNamespace()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JetTypeMapper prepareTypeMapper(JetFile file) {
|
||||||
|
final JetTypeMapper mapper = myTypeMappers.get(file);
|
||||||
|
if (mapper != null) {
|
||||||
|
return mapper;
|
||||||
|
}
|
||||||
|
final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file);
|
||||||
|
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(myDebugProcess.getProject());
|
||||||
|
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||||
|
file.acceptChildren(new JetVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitJetElement(JetElement element) {
|
||||||
|
element.acceptChildren(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClass(JetClass klass) {
|
||||||
|
GenerationState.prepareAnonymousClasses(klass, typeMapper);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
myTypeMappers.put(file, typeMapper);
|
||||||
|
return typeMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<Location> locationsOfLine(ReferenceType type, SourcePosition position) throws NoDataException {
|
||||||
|
if (!(position.getFile() instanceof JetFile)) {
|
||||||
|
throw new NoDataException();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int line = position.getLine() + 1;
|
||||||
|
List<Location> locations = myDebugProcess.getVirtualMachineProxy().versionHigher("1.4")
|
||||||
|
? type.locationsOfLine(DebugProcess.JAVA_STRATUM, null, line)
|
||||||
|
: type.locationsOfLine(line);
|
||||||
|
if (locations == null || locations.isEmpty()) throw new NoDataException();
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
catch (AbsentInformationException e) {
|
||||||
|
throw new NoDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassPrepareRequest createPrepareRequest(ClassPrepareRequestor classPrepareRequestor,
|
||||||
|
SourcePosition sourcePosition) throws NoDataException {
|
||||||
|
if (!(sourcePosition.getFile() instanceof JetFile)) {
|
||||||
|
throw new NoDataException();
|
||||||
|
}
|
||||||
|
final Collection<String> classNames = classNamesForPosition(sourcePosition);
|
||||||
|
if (classNames.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Iterator<String> iterator = classNames.iterator();
|
||||||
|
boolean wildcard = false;
|
||||||
|
String namePattern = iterator.next();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
namePattern = StringUtil.commonPrefix(namePattern, iterator.next());
|
||||||
|
wildcard = true;
|
||||||
|
}
|
||||||
|
if (wildcard) {
|
||||||
|
namePattern += "*";
|
||||||
|
}
|
||||||
|
return myDebugProcess.getRequestsManager().createClassPrepareRequest(classPrepareRequestor, namePattern.replace('/', '.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.jetbrains.jet.plugin.debugger;
|
||||||
|
|
||||||
|
import com.intellij.debugger.PositionManager;
|
||||||
|
import com.intellij.debugger.PositionManagerFactory;
|
||||||
|
import com.intellij.debugger.engine.DebugProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public class JetPositionManagerFactory implements PositionManagerFactory {
|
||||||
|
@Override
|
||||||
|
public PositionManager create(DebugProcess debugProcess) {
|
||||||
|
return new JetPositionManager(debugProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user