blob: 7427f91df50064ece98b3ba160c7fe6d580eb09c [file] [log] [blame]
/*
* 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.breakpoints;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.java.debugger.JavaDebuggerEditorsProvider;
import org.jetbrains.java.debugger.breakpoints.JavaBreakpointFiltersPanel;
import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
/**
* Base class for java line-connected exceptions (line, method, field)
* @author egor
*/
public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointProperties> extends XLineBreakpointType<P> {
public JavaLineBreakpointTypeBase(@NonNls @NotNull String id, @Nls @NotNull String title) {
super(id, title);
}
@Override
public boolean isAddBreakpointButtonVisible() {
return false;
}
@Override
public final boolean isSuspendThreadSupported() {
return true;
}
@Nullable
@Override
public final XBreakpointCustomPropertiesPanel<XLineBreakpoint<P>> createCustomRightPropertiesPanel(@NotNull Project project) {
return new JavaBreakpointFiltersPanel<P, XLineBreakpoint<P>>(project);
}
@Nullable
@Override
public final XDebuggerEditorsProvider getEditorsProvider(@NotNull XLineBreakpoint<P> breakpoint, @NotNull Project project) {
return new JavaDebuggerEditorsProvider();
}
@Override
public String getDisplayText(XLineBreakpoint<P> breakpoint) {
BreakpointWithHighlighter javaBreakpoint = (BreakpointWithHighlighter)BreakpointManager.getJavaBreakpoint(breakpoint);
if (javaBreakpoint != null) {
return javaBreakpoint.getDescription();
}
else {
return super.getDisplayText(breakpoint);
}
}
@Override
public final boolean canPutAt(@NotNull VirtualFile file, final int line, @NotNull Project project) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
// JSPX supports jvm debugging, but not in XHTML files
if (psiFile == null || psiFile.getVirtualFile().getFileType() == StdFileTypes.XHTML) {
return false;
}
if (!StdFileTypes.CLASS.equals(psiFile.getFileType()) && !DebuggerUtils.isBreakpointAware(psiFile)) {
return false;
}
final Document document = FileDocumentManager.getInstance().getDocument(file);
final Ref<Class<? extends JavaLineBreakpointTypeBase>> result = Ref.create();
XDebuggerUtil.getInstance().iterateLine(project, document, line, new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
// avoid comments
if ((element instanceof PsiWhiteSpace) || (PsiTreeUtil.getParentOfType(element, PsiComment.class, false) != null)) {
return true;
}
PsiElement parent = element;
while(element != null) {
// skip modifiers
if (element instanceof PsiModifierList) {
element = element.getParent();
continue;
}
final int offset = element.getTextOffset();
if (offset >= 0) {
if (document.getLineNumber(offset) != line) {
break;
}
}
parent = element;
element = element.getParent();
}
if(parent instanceof PsiMethod) {
if (parent.getTextRange().getEndOffset() >= document.getLineEndOffset(line)) {
PsiCodeBlock body = ((PsiMethod)parent).getBody();
if (body != null) {
PsiStatement[] statements = body.getStatements();
if (statements.length > 0 && document.getLineNumber(statements[0].getTextOffset()) == line) {
result.set(JavaLineBreakpointType.class);
}
}
}
if (result.isNull()) {
result.set(JavaMethodBreakpointType.class);
}
}
else if (parent instanceof PsiField) {
if (result.isNull()) {
result.set(JavaFieldBreakpointType.class);
}
}
else {
result.set(JavaLineBreakpointType.class);
}
return true;
}
});
return result.get() == getClass();
}
}