/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.debugger;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.debugger.impl.EditorTextProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiCallExpression;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.psi.PsiIdentifier;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiStatement;
import com.intellij.psi.PsiThisExpression;
import com.intellij.psi.PsiVariable;
import com.intellij.util.IncorrectOperationException;
import gw.plugin.ij.lang.psi.impl.expressions.GosuReferenceExpressionImpl;
import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil;
import org.jetbrains.annotations.Nullable;
/**
*/
public class GosuEditorTextProvider implements EditorTextProvider {
private static final Logger LOG = Logger.getInstance( GosuEditorTextProvider.class );
@Override
public TextWithImports getEditorText( PsiElement elementAtCaret ) {
String result = null;
PsiElement element = findExpression( elementAtCaret );
if( element != null ) {
if( element instanceof GosuReferenceExpressionImpl ) {
final GosuReferenceExpressionImpl reference = (GosuReferenceExpressionImpl)element;
if( reference.getQualifier() == null ) {
final PsiElement resolved = reference.resolve();
if( resolved instanceof PsiEnumConstant ) {
final PsiEnumConstant enumConstant = (PsiEnumConstant)resolved;
final PsiClass enumClass = enumConstant.getContainingClass();
if( enumClass != null ) {
result = enumClass.getName() + "." + enumConstant.getName();
}
}
}
}
if( result == null ) {
result = element.getText();
}
}
return result != null ? new TextWithImportsImpl( CodeFragmentKind.EXPRESSION, result ) : null;
}
@Nullable
private static PsiElement findExpression( PsiElement element ) {
if( !(element instanceof PsiIdentifier || element instanceof PsiKeyword) ) {
return null;
}
PsiElement parent = element.getParent();
if( parent instanceof PsiVariable ) {
return element;
}
if( parent instanceof GosuReferenceExpressionImpl ) {
if( parent.getParent() instanceof PsiCallExpression ) {
return parent.getParent();
}
return parent;
}
if( parent instanceof PsiThisExpression ) {
return parent;
}
return null;
}
@Nullable
public Pair<PsiElement, TextRange> findExpression( PsiElement element, boolean allowMethodCalls ) {
if( !(element instanceof PsiIdentifier || element instanceof PsiKeyword) ) {
return null;
}
PsiElement expression = null;
PsiElement parent = element.getParent();
if( parent instanceof PsiVariable ) {
expression = element;
}
else if( parent instanceof GosuReferenceExpressionImpl ) {
final PsiElement pparent = parent.getParent();
if( pparent instanceof PsiCallExpression ) {
parent = pparent;
}
if( allowMethodCalls || !DebuggerUtils.hasSideEffects( parent ) ) {
expression = parent;
}
}
else if( parent instanceof PsiThisExpression ) {
expression = parent;
}
if( expression != null ) {
try {
PsiElement context = element;
if( parent instanceof PsiParameter ) {
try {
context = ((PsiMethod)((PsiParameter)parent).getDeclarationScope()).getBody();
}
catch( Throwable ignored ) {
}
}
else {
while( context != null && !(context instanceof PsiStatement) && !(context instanceof PsiClass) ) {
context = context.getParent();
}
}
TextRange textRange = expression.getTextRange();
PsiElement psiExpression = GosuPsiParseUtil.parseExpression( expression.getText(), element.getManager() );
return Pair.create( psiExpression, textRange );
}
catch( IncorrectOperationException e ) {
LOG.debug( e );
}
}
return null;
}
}