package com.intellij.lang.javascript.inspections.actionscript.fixes; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.javascript.JSBundle; import com.intellij.lang.javascript.highlighting.JSFixFactory; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.ecmal4.JSClass; import com.intellij.lang.javascript.psi.ecmal4.JSSuperExpression; import com.intellij.lang.javascript.validation.JSAnnotatorProblemReporter; import com.intellij.lang.javascript.validation.JSConstructorChecker; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static com.intellij.lang.javascript.validation.JSAnnotatingVisitor.getPlaceForNamedElementProblem; public class ActionScriptConstructorChecker extends JSConstructorChecker { public ActionScriptConstructorChecker(@NotNull JSAnnotatorProblemReporter problemReporter) { super(problemReporter); } public void checkMissedConstructor(@NotNull JSClass jsClass) { if (jsClass.isInterface()) return; final JSFunction nontrivialSuperClassConstructor = getNontrivialSuperClassConstructor(jsClass); if (nontrivialSuperClassConstructor == null) { return; } final PsiElement place = getPlaceForNamedElementProblem(jsClass); Annotation annotation = myProblemReporter.registerGenericError(place, JSBundle .message("javascript.validation.message.missed.super.constructor.call")); annotation.registerFix(JSFixFactory.getInstance().addConstructorAndSuperInvocationFix(jsClass, nontrivialSuperClassConstructor)); } @Override protected void checkInstanceMemberAccesses(@NotNull JSFunction constructor, @NotNull JSClass clazz) { } @Contract("null -> null") protected JSCallExpression findAnyBaseConstructorCall(@Nullable JSFunction jsFunction) { if (jsFunction == null) return null; final JSSourceElement[] body = jsFunction.getBody(); return body.length > 0 ? findBaseConstructorCall(((JSBlockStatement)body[0])) : null; } private static JSCallExpression findBaseConstructorCall(final JSBlockStatement blockStatement) { for (JSStatement statement : blockStatement.getStatements()) { JSExpression expr; if (statement instanceof JSExpressionStatement && (expr = ((JSExpressionStatement)statement).getExpression()) instanceof JSCallExpression && ((JSCallExpression)expr).getMethodExpression() instanceof JSSuperExpression) { return (JSCallExpression)expr; } else if (statement instanceof JSIfStatement) { // awful compiler somehow allows to call super() only in one branch of 'if' statement. Example in Starling framework sources: class starling.display.Image final JSStatement then = ((JSIfStatement)statement).getThen(); if (then instanceof JSBlockStatement) { return findBaseConstructorCall((JSBlockStatement)then); } } } return null; } }