Nullablility diagnostics for extension functions

This commit is contained in:
Andrey Breslav
2011-05-30 20:09:04 +04:00
parent 02565f669c
commit 6319ada926
17 changed files with 166 additions and 77 deletions
+2
View File
@@ -7,6 +7,8 @@ namespace typeinfo {
} }
} }
fun Any?.equals(other : Any?) : Boolean = this === other
class Iterator<out T> { class Iterator<out T> {
fun next() : T fun next() : T
@@ -5,14 +5,12 @@ import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator; import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.psi.MultiRangeReference; import com.intellij.psi.MultiRangeReference;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference; import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetDiagnostic;
import org.jetbrains.jet.lang.JetHighlighter; import org.jetbrains.jet.lang.JetHighlighter;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
@@ -124,8 +122,8 @@ public class JetPsiChecker implements Annotator {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
elem.acceptChildren(this); element.acceptChildren(this);
} }
}); });
} }
@@ -694,16 +694,16 @@ public class JetControlFlowProcessor {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + elem.toString()); throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
} }
}); });
} }
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + elem.toString()); throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
} }
}); });
} }
@@ -726,8 +726,8 @@ public class JetControlFlowProcessor {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
builder.unsupported(elem); builder.unsupported(element);
} }
} }
} }
@@ -31,9 +31,9 @@ public class JetPsiUtil {
final Set<JetElement> shadowedElements = new HashSet<JetElement>(); final Set<JetElement> shadowedElements = new HashSet<JetElement>();
JetVisitor shadowAllChildren = new JetVisitor() { JetVisitor shadowAllChildren = new JetVisitor() {
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
if (shadowedElements.add(elem)) { if (shadowedElements.add(element)) {
elem.acceptChildren(this); element.acceptChildren(this);
} }
} }
}; };
@@ -6,8 +6,8 @@ import com.intellij.psi.PsiElementVisitor;
* @author max * @author max
*/ */
public class JetVisitor extends PsiElementVisitor { public class JetVisitor extends PsiElementVisitor {
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
visitElement(elem); visitElement(element);
} }
public void visitDeclaration(JetDeclaration dcl) { public void visitDeclaration(JetDeclaration dcl) {
@@ -143,6 +143,10 @@ public class JetVisitor extends PsiElementVisitor {
} }
public void visitSimpleNameExpression(JetSimpleNameExpression expression) { public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
visitReferenceExpression(expression);
}
public void visitReferenceExpression(JetReferenceExpression expression) {
visitExpression(expression); visitExpression(expression);
} }
@@ -231,7 +235,7 @@ public class JetVisitor extends PsiElementVisitor {
} }
public void visitArrayAccessExpression(JetArrayAccessExpression expression) { public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
visitExpression(expression); visitReferenceExpression(expression);
} }
public void visitQualifiedExpression(JetQualifiedExpression expression) { public void visitQualifiedExpression(JetQualifiedExpression expression) {
@@ -84,8 +84,8 @@ public class ClassDescriptorResolver {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException(elem.toString()); throw new UnsupportedOperationException(element.toString());
} }
}); });
} }
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionGroup;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker; import org.jetbrains.jet.lang.types.JetTypeChecker;
import org.jetbrains.jet.lang.types.TypeUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -62,9 +63,12 @@ public class OverloadResolver {
if (receiverType != null) { if (receiverType != null) {
// ASSERT : either the receiver in not present or we are in a scope with no top-level functions // ASSERT : either the receiver in not present or we are in a scope with no top-level functions
final JetType functionReceiverType = descriptor.getReceiverType(); JetType functionReceiverType = descriptor.getReceiverType();
if (functionReceiverType != null && !typeChecker.isSubtypeOf(receiverType, functionReceiverType)) { if (functionReceiverType != null) {
continue; functionReceiverType = TypeUtils.makeNullable(functionReceiverType); // Too look things up in T for T?, and later check receiver's nullability
if (!typeChecker.isSubtypeOf(receiverType, functionReceiverType)) {
continue;
}
} }
} }
else if (descriptor.getReceiverType() != null) { else if (descriptor.getReceiverType() != null) {
@@ -14,7 +14,7 @@ public class ScopeWithReceiver extends JetScopeImpl {
private final JetScope outerScope; private final JetScope outerScope;
private final JetTypeChecker typeChecker; private final JetTypeChecker typeChecker;
public ScopeWithReceiver(JetScope outerScope, JetType receiverType, JetTypeChecker typeChecker) { public ScopeWithReceiver(@NotNull JetScope outerScope, @NotNull JetType receiverType, @NotNull JetTypeChecker typeChecker) {
this.outerScope = outerScope; this.outerScope = outerScope;
this.receiverType = receiverType; this.receiverType = receiverType;
this.typeChecker = typeChecker; this.typeChecker = typeChecker;
@@ -23,7 +23,9 @@ public class ScopeWithReceiver extends JetScopeImpl {
@NotNull @NotNull
@Override @Override
public FunctionGroup getFunctionGroup(@NotNull String name) { public FunctionGroup getFunctionGroup(@NotNull String name) {
FunctionGroup functionGroup = receiverType.getMemberScope().getFunctionGroup(name); JetScope memberScope = receiverType.getMemberScope();
assert memberScope != null : receiverType;
FunctionGroup functionGroup = memberScope.getFunctionGroup(name);
if (functionGroup.isEmpty()) { if (functionGroup.isEmpty()) {
return outerScope.getFunctionGroup(name); return outerScope.getFunctionGroup(name);
// return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name), // return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name),
@@ -449,8 +449,8 @@ public class TopDownAnalyzer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException(elem.getText() + " : " + elem); throw new UnsupportedOperationException(element.getText() + " : " + element);
} }
}); });
} }
@@ -149,8 +149,8 @@ public class TypeResolver {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
throw new IllegalArgumentException("Unsupported type: " + elem); throw new IllegalArgumentException("Unsupported type: " + element);
} }
}); });
} }
@@ -123,11 +123,7 @@ public class ErrorUtils {
); );
} }
private static FunctionDescriptor createErrorFunction(int typeParameterCount, Map<String, JetType> valueParameters) { public static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
throw new UnsupportedOperationException(); // TODO
}
private static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize( return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize(
null, null,
Collections.<TypeParameterDescriptor>emptyList(), // TODO Collections.<TypeParameterDescriptor>emptyList(), // TODO
@@ -59,6 +59,7 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
return nullable; return nullable;
} }
@NotNull
@Override @Override
public JetScope getMemberScope() { public JetScope getMemberScope() {
if (memberScope == null) { if (memberScope == null) {
@@ -164,22 +164,22 @@ public class JetTypeInferrer {
trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]"); trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]");
// . or ?. // . or ?.
JetType receiverType = getType(scope, expression.getReceiverExpression(), false); // JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
checkNullSafety(receiverType, expression.getOperationTokenNode()); // checkNullSafety(receiverType, expression.getOperationTokenNode());
//
JetExpression selectorExpression = expression.getSelectorExpression(); // JetExpression selectorExpression = expression.getSelectorExpression();
if (selectorExpression instanceof JetSimpleNameExpression) { // if (selectorExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression; // JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName(); // String referencedName = referenceExpression.getReferencedName();
//
if (receiverType != null && referencedName != null) { // if (receiverType != null && referencedName != null) {
// No generics. Guaranteed // // No generics. Guaranteed
result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); // result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
reference[0] = referenceExpression; // reference[0] = referenceExpression;
} // }
} else { // } else {
throw new UnsupportedOperationException(); // TODO // throw new UnsupportedOperationException(); // TODO
} // }
} }
@Override @Override
@@ -200,22 +200,25 @@ public class JetTypeInferrer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported in call element"); // TODO : Message trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message
} }
}); });
return wrapForTracing(result[0], reference[0], argumentList, true); return wrapForTracing(result[0], reference[0], argumentList, true);
} }
private void checkNullSafety(JetType receiverType, ASTNode operationTokenNode) { private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) {
if (receiverType != null) { if (receiverType != null && callee != null) {
boolean namespaceType = receiverType instanceof NamespaceType; boolean namespaceType = receiverType instanceof NamespaceType;
boolean nullable = !namespaceType && receiverType.isNullable(); JetType calleeReceiverType = callee.getReceiverType();
boolean nullableReceiver = !namespaceType && receiverType.isNullable();
boolean calleeForbidsNullableReceiver = calleeReceiverType == null || !calleeReceiverType.isNullable();
IElementType operationSign = operationTokenNode.getElementType(); IElementType operationSign = operationTokenNode.getElementType();
if (nullable && operationSign == JetTokens.DOT) { if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType); trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
} }
else if (!nullable && operationSign == JetTokens.SAFE_ACCESS) { else if ((!nullableReceiver || !calleeForbidsNullableReceiver) && operationSign == JetTokens.SAFE_ACCESS) {
if (namespaceType) { if (namespaceType) {
trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces"); trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
} }
@@ -1054,7 +1057,7 @@ public class JetTypeInferrer {
// TODO : exhaustive patterns // TODO : exhaustive patterns
for (JetWhenEntry whenEntry : expression.getEntries()) { for (JetWhenEntry whenEntry : expression.getEntries()) {
final JetType finalSubjectType = subjectType; final JetType finalSubjectType = subjectType != null ? subjectType : ErrorUtils.createErrorType("Unknown type");
JetWhenCondition condition = whenEntry.getCondition(); JetWhenCondition condition = whenEntry.getCondition();
if (condition != null) { if (condition != null) {
condition.accept(new JetVisitor() { condition.accept(new JetVisitor() {
@@ -1073,12 +1076,12 @@ public class JetTypeInferrer {
@Override @Override
public void visitWhenConditionCall(JetWhenConditionCall condition) { public void visitWhenConditionCall(JetWhenConditionCall condition) {
checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
JetExpression callSuffixExpression = condition.getCallSuffixExpression(); JetExpression callSuffixExpression = condition.getCallSuffixExpression();
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker()); JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
if (callSuffixExpression != null) { if (callSuffixExpression != null) {
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false); JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression"); ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
checkNullSafety(finalSubjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression));
} }
} }
@@ -1099,8 +1102,8 @@ public class JetTypeInferrer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer] : " + elem); trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer] : " + element);
} }
}); });
} }
@@ -1182,8 +1185,8 @@ public class JetTypeInferrer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer]"); trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer]");
} }
}); });
} }
@@ -1437,8 +1440,6 @@ public class JetTypeInferrer {
JetExpression receiverExpression = expression.getReceiverExpression(); JetExpression receiverExpression = expression.getReceiverExpression();
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression); JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
if (receiverType != null) { if (receiverType != null) {
// TODO : extensions to 'Any?'
checkNullSafety(receiverType, expression.getOperationTokenNode());
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression); JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
if (expression.getOperationSign() == JetTokens.QUEST) { if (expression.getOperationSign() == JetTokens.QUEST) {
if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) { if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
@@ -1453,9 +1454,57 @@ public class JetTypeInferrer {
if (selectorExpression != null && result != null) { if (selectorExpression != null && result != null) {
trace.recordExpressionType(selectorExpression, result); trace.recordExpressionType(selectorExpression, result);
} }
if (selectorReturnType != null) {
// TODO : extensions to 'Any?'
assert selectorExpression != null;
checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression));
}
} }
} }
@NotNull
private FunctionDescriptor getCalleeFunctionDescriptor(@NotNull JetExpression selectorExpression) {
final FunctionDescriptor[] result = new FunctionDescriptor[1];
selectorExpression.accept(new JetVisitor() {
@Override
public void visitCallExpression(JetCallExpression callExpression) {
callExpression.getCalleeExpression().accept(this);
}
@Override
public void visitReferenceExpression(JetReferenceExpression referenceExpression) {
DeclarationDescriptor declarationDescriptor = trace.getBindingContext().resolveReferenceExpression(referenceExpression);
if (declarationDescriptor instanceof FunctionDescriptor) {
result[0] = (FunctionDescriptor) declarationDescriptor;
}
}
@Override
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
expression.getArrayExpression().accept(this);
}
@Override
public void visitBinaryExpression(JetBinaryExpression expression) {
expression.getLeft().accept(this);
}
@Override
public void visitQualifiedExpression(JetQualifiedExpression expression) {
expression.getReceiverExpression().accept(this);
}
@Override
public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(element.getNode(), "Unsupported [getCalleeFunctionDescriptor]: " + element);
}
});
if (result[0] == null) {
result[0] = ErrorUtils.createErrorFunction(0, Collections.<JetType>emptyList());
}
return result[0];
}
private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression) { private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression) {
OverloadDomain overloadDomain = getOverloadDomain(receiverType, scope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList()); OverloadDomain overloadDomain = getOverloadDomain(receiverType, scope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
return resolveCall(scope, overloadDomain, callExpression); return resolveCall(scope, overloadDomain, callExpression);
@@ -1769,8 +1818,8 @@ public class JetTypeInferrer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(elem.getNode(), "[JetTypeInferrer] Unsupported element: " + elem + " " + elem.getClass().getCanonicalName()); trace.getErrorHandler().genericError(element.getNode(), "[JetTypeInferrer] Unsupported element: " + element + " " + element.getClass().getCanonicalName());
} }
} }
@@ -1919,9 +1968,10 @@ public class JetTypeInferrer {
} }
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported element in a block: " + elem + " " + elem.getClass().getCanonicalName()); trace.getErrorHandler().genericError(element.getNode(), "Unsupported element in a block: " + element + " " + element.getClass().getCanonicalName());
} }
} }
// private class CachedBindingTrace extends BindingTraceAdapter { // private class CachedBindingTrace extends BindingTraceAdapter {
@@ -15,15 +15,16 @@ import java.util.*;
* @author abreslav * @author abreslav
*/ */
public class TypeUtils { public class TypeUtils {
public static JetType makeNullable(JetType type) { public static JetType makeNullable(@NotNull JetType type) {
return makeNullableAsSpecified(type, true); return makeNullableAsSpecified(type, true);
} }
public static JetType makeNotNullable(JetType type) { public static JetType makeNotNullable(@NotNull JetType type) {
return makeNullableAsSpecified(type, false); return makeNullableAsSpecified(type, false);
} }
public static JetType makeNullableAsSpecified(JetType type, boolean nullable) { @NotNull
public static JetType makeNullableAsSpecified(@NotNull JetType type, boolean nullable) {
if (type.isNullable() == nullable) { if (type.isNullable() == nullable) {
return type; return type;
} }
+34 -2
View File
@@ -6,7 +6,7 @@ fun <T, E> T.foo(x : E, y : A) : T {
y plus 1 y plus 1
y + 1.0 y + 1.0
this?.minus<T>(this) this<warning>?.</warning>minus<T>(this)
this this
} }
@@ -35,4 +35,36 @@ val Int.abs : Int
val <T> T.foo : T val <T> T.foo : T
fun Int.foo() = this fun Int.foo() = this
namespace null_safety {
fun parse(cmd: String): Command? { return null }
class Command() {
// fun equals(other : Any?) : Boolean
val foo : Int
}
fun Any.equals(other : Any?) : Boolean
fun Any?.equals1(other : Any?) : Boolean
fun main(args: Array<String>) {
System.out?.print(1)
val command = parse("")
command<error>.</error>foo
command<error>.</error>equals(null)
command?.equals(null)
command.equals1(null)
command<warning>?.</warning>equals1(null)
val c = new Command()
c<warning>?.</warning>equals(null)
if (command == null) 1
}
}
@@ -2,7 +2,6 @@ package org.jetbrains.jet;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.ClassCodegen;
import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetDiagnostic; import org.jetbrains.jet.lang.JetDiagnostic;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -136,7 +135,7 @@ public class JetTestUtils {
@Override @Override
public DeclarationDescriptor resolveReferenceExpression(JetReferenceExpression referenceExpression) { public DeclarationDescriptor resolveReferenceExpression(JetReferenceExpression referenceExpression) {
throw new UnsupportedOperationException(); // TODO return null;
} }
@Override @Override
@@ -52,10 +52,10 @@ public class JetParsingTest extends ParsingTestCase {
protected void checkResult(@NonNls String targetDataName, PsiFile file) throws IOException { protected void checkResult(@NonNls String targetDataName, PsiFile file) throws IOException {
file.acceptChildren(new JetVisitor() { file.acceptChildren(new JetVisitor() {
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement element) {
elem.acceptChildren(this); element.acceptChildren(this);
try { try {
checkPsiGetters(elem); checkPsiGetters(element);
} catch (Throwable throwable) { } catch (Throwable throwable) {
throw new RuntimeException(throwable); throw new RuntimeException(throwable);
} }