@Override
  public void visitUnaryExpression(GrUnaryExpression expression) {
    final GrExpression operand = expression.getOperand();
    if (operand == null) return;

    if (expression.getOperationTokenType() != mLNOT) {
      operand.accept(this);
      visitCall(expression);
      return;
    }

    ConditionInstruction cond = new ConditionInstruction(expression);
    addNodeAndCheckPending(cond);
    registerCondition(cond);

    operand.accept(this);
    visitCall(expression);

    myConditions.removeFirstOccurrence(cond);

    List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);

    InstructionImpl head = myHead;
    addNodeAndCheckPending(new PositiveGotoInstruction(expression, cond));
    handlePossibleReturn(expression);
    addPendingEdge(expression, myHead);

    if (negations.isEmpty()) {
      myHead = head;
    } else {
      myHead = reduceAllNegationsIntoInstruction(expression, negations);
    }
  }
 @Nullable
 private static PsiType getInferredTypes(
     GrReferenceExpressionImpl refExpr, @Nullable PsiElement resolved) {
   final GrExpression qualifier = refExpr.getQualifier();
   if (qualifier == null && !(resolved instanceof PsiClass)) {
     return TypeInferenceHelper.getCurrentContext().getVariableType(refExpr);
   } else if (qualifier != null) {
     // map access
     PsiType qType = qualifier.getType();
     if (qType instanceof PsiClassType && !(qType instanceof GrMapType)) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(refExpr.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, refExpr.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
  @Override
  public void visitCaseSection(GrCaseSection caseSection) {
    for (GrCaseLabel label : caseSection.getCaseLabels()) {
      GrExpression value = label.getValue();
      if (value != null) {
        value.accept(this);
      }
    }

    final GrStatement[] statements = caseSection.getStatements();

    // infer 'may be return' position
    int i;
    for (i = statements.length - 1; i >= 0 && statements[i] instanceof GrBreakStatement; i--) {}

    for (int j = 0; j < statements.length; j++) {
      GrStatement statement = statements[j];
      statement.accept(this);
      if (j == i) handlePossibleReturn(statement);
    }

    if (myHead != null) {
      addPendingEdge(caseSection, myHead);
    }
  }
    @Override
    public void visitBinaryExpression(GrBinaryExpression expression) {
      final IElementType type = expression.getOperationTokenType();
      final GrExpression left = expression.getLeftOperand();
      final GrExpression right = expression.getRightOperand();

      if (type == mREGEX_FIND || type == mREGEX_MATCH) {
        final PsiClassType string =
            TypesUtil.createType(CommonClassNames.JAVA_LANG_STRING, expression);
        myResult = createSimpleSubTypeResult(string);
        return;
      }

      final GrExpression other = myExpression == left ? right : left;
      final PsiType otherType = other != null ? other.getType() : null;

      if (otherType == null) return;

      if (type == mPLUS && otherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
        final PsiClassType obj = TypesUtil.getJavaLangObject(expression);
        myResult = createSimpleSubTypeResult(obj);
        return;
      }

      myResult = createSimpleSubTypeResult(otherType);
    }
Ejemplo n.º 5
0
  @Nullable
  private static PsiType doNormalizeWildcardByPosition(
      final PsiType type, final GrExpression expression, final GrExpression toplevel) {
    if (type instanceof PsiCapturedWildcardType) {
      return doNormalizeWildcardByPosition(
          ((PsiCapturedWildcardType) type).getWildcard(), expression, toplevel);
    }

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(toplevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, toplevel);
      if (normalizedComponentType != componentType) {
        assert normalizedComponentType != null;
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
 @Nullable
 private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpressionImpl ref) {
   // map access
   GrExpression qualifier = ref.getQualifierExpression();
   if (qualifier != null) {
     PsiType qType = qualifier.getNominalType();
     if (qType instanceof PsiClassType) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(ref.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
  public void visitAssertStatement(GrAssertStatement assertStatement) {
    final InstructionImpl assertInstruction = startNode(assertStatement);

    final GrExpression assertion = assertStatement.getAssertion();
    if (assertion != null) {
      assertion.accept(this);

      InstructionImpl positiveHead = myHead;

      List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(assertStatement);
      if (!negations.isEmpty()) {
        interruptFlow();
        reduceAllNegationsIntoInstruction(assertStatement, negations);
      }

      GrExpression errorMessage = assertStatement.getErrorMessage();
      if (errorMessage != null) {
        errorMessage.accept(this);
      }
      addNode(new ThrowingInstruction(assertStatement));

      final PsiType type =
          TypesUtil.createTypeByFQClassName(
              CommonClassNames.JAVA_LANG_ASSERTION_ERROR, assertStatement);
      ExceptionInfo info = findCatch(type);
      if (info != null) {
        info.myThrowers.add(myHead);
      } else {
        addPendingEdge(null, myHead);
      }

      myHead = positiveHead;
    }
    finishNode(assertInstruction);
  }
Ejemplo n.º 8
0
  public static PsiExpression getOrCreatePisExpression(GrExpression expr) {
    if (expr == null) return null;

    final SoftReference<PsiExpression> ref = expr.getUserData(PSI_EXPRESSION);
    final PsiExpression element = ref == null ? null : ref.get();
    if (element != null) return element;
    final GrSyntheticExpression newExpr = new GrSyntheticExpression(expr);
    expr.putUserData(PSI_EXPRESSION, new SoftReference<PsiExpression>(newExpr));
    return newExpr;
  }
 public void visitIfStatement(GrIfStatement ifStatement) {
   if (myExpression.equals(ifStatement.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(ifStatement), PsiType.BOOLEAN)
         };
   } else if (myExpression.equals(ifStatement.getThenBranch())
       || myExpression.equals(ifStatement.getElseBranch())) {
     checkExitPoint();
   }
 }
    @Override
    public void visitCaseLabel(GrCaseLabel caseLabel) {
      final PsiElement parent = caseLabel.getParent().getParent();
      assert parent instanceof GrSwitchStatement : parent + " of class " + parent.getClass();
      final GrExpression condition = ((GrSwitchStatement) parent).getCondition();
      if (condition == null) return;

      final PsiType type = condition.getType();
      if (type == null) return;

      myResult = new TypeConstraint[] {SubtypeConstraint.create(type)};
    }
 private void addForLoopBreakingEdge(GrForStatement forStatement, @Nullable GrForClause clause) {
   if (clause instanceof GrTraditionalForClause) {
     final GrExpression condition = ((GrTraditionalForClause) clause).getCondition();
     if (condition != null) {
       condition.accept(this);
       if (!alwaysTrue(condition)) {
         addPendingEdge(forStatement, myHead); // break cycle
       }
     }
   } else {
     addPendingEdge(forStatement, myHead); // break cycle
   }
 }
  public void visitReturnStatement(GrReturnStatement returnStatement) {
    boolean isNodeNeeded = myHead == null || myHead.getElement() != returnStatement;
    final GrExpression value = returnStatement.getReturnValue();
    if (value != null) value.accept(this);

    if (isNodeNeeded) {
      InstructionImpl returnInstruction = startNode(returnStatement);
      addPendingEdge(null, myHead);
      finishNode(returnInstruction);
    } else {
      addPendingEdge(null, myHead);
    }
    interruptFlow();
  }
    @Override
    public void visitSwitchStatement(GrSwitchStatement switchStatement) {
      final GrCaseSection[] sections = switchStatement.getCaseSections();
      List<PsiType> types = new ArrayList<PsiType>(sections.length);
      for (GrCaseSection section : sections) {
        final GrExpression value = section.getCaseLabel().getValue();
        final PsiType type = value != null ? value.getType() : null;
        if (type != null) types.add(type);
      }

      final PsiType upperBoundNullable =
          TypesUtil.getLeastUpperBoundNullable(types, switchStatement.getManager());
      if (upperBoundNullable == null) return;

      myResult = new TypeConstraint[] {SubtypeConstraint.create(upperBoundNullable)};
    }
 @Override
 public void visitOpenBlock(GrOpenBlock block) {
   final GrStatement[] statements = block.getStatements();
   if (statements.length > 0 && myExpression.equals(statements[statements.length - 1])) {
     checkExitPoint();
   }
 }
Ejemplo n.º 15
0
  @Nullable
  public static PsiType normalizeWildcardTypeByPosition(
      @NotNull PsiType type, @NotNull GrExpression expression) {
    GrExpression toplevel = expression;
    while (toplevel.getParent() instanceof GrIndexProperty
        && ((GrIndexProperty) toplevel.getParent()).getInvokedExpression() == toplevel) {
      toplevel = (GrExpression) toplevel.getParent();
    }

    final PsiType normalized = doNormalizeWildcardByPosition(type, expression, toplevel);
    if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(toplevel)) {
      return com.intellij.psi.util.PsiUtil.captureToplevelWildcards(normalized, expression);
    }

    return normalized;
  }
 public void visitTraditionalForClause(GrTraditionalForClause forClause) {
   if (myExpression.equals(forClause.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(forClause), PsiType.BOOLEAN)
         };
   }
 }
 public void visitWhileStatement(GrWhileStatement whileStatement) {
   if (myExpression.equals(whileStatement.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(whileStatement), PsiType.BOOLEAN)
         };
   }
 }
  public void visitAssignmentExpression(GrAssignmentExpression expression) {
    GrExpression lValue = expression.getLValue();
    if (expression.getOperationTokenType() != mASSIGN) {
      if (lValue instanceof GrReferenceExpression
          && myPolicy.isReferenceAccepted((GrReferenceExpression) lValue)) {
        String referenceName = ((GrReferenceExpression) lValue).getReferenceName();
        if (referenceName != null) {
          addNodeAndCheckPending(new ReadWriteVariableInstruction(referenceName, lValue, READ));
        }
      }
    }

    GrExpression rValue = expression.getRValue();
    if (rValue != null) {
      rValue.accept(this);
      lValue.accept(this);
    }
  }
 @Nullable
 private static PsiType getNominalTypeNoRecursion(@NotNull final GrExpression expression) {
   if (expression instanceof GrNewExpression) {
     return expression.getType();
   } else if (expression instanceof GrReferenceExpression
       && ((GrReferenceExpression) expression).getQualifier() == null) {
     return getTypeByRef((GrReferenceExpression) expression);
   }
   return null;
 }
  @Override
  public void visitElvisExpression(GrElvisExpression expression) {
    GrExpression condition = expression.getCondition();
    GrExpression elseBranch = expression.getElseBranch();

    condition.accept(this);
    List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);

    InstructionImpl head = myHead;
    handlePossibleReturn(condition);
    addPendingEdge(expression, myHead);
    myHead = head;

    if (elseBranch != null) {
      head = reduceAllNegationsIntoInstruction(expression, negations);
      if (head != null) myHead = head;
      elseBranch.accept(this);
      handlePossibleReturn(elseBranch);
    }
  }
  public void visitThrowStatement(GrThrowStatement throwStatement) {
    final GrExpression exception = throwStatement.getException();
    if (exception == null) return;

    exception.accept(this);
    final InstructionImpl throwInstruction = new ThrowingInstruction(throwStatement);
    addNodeAndCheckPending(throwInstruction);

    interruptFlow();
    final PsiType type = getNominalTypeNoRecursion(exception);
    if (type != null) {
      ExceptionInfo info = findCatch(type);
      if (info != null) {
        info.myThrowers.add(throwInstruction);
      } else {
        addPendingEdge(null, throwInstruction);
      }
    } else {
      addPendingEdge(null, throwInstruction);
    }
  }
Ejemplo n.º 22
0
  /** @return replaced expression or null if expression is not replaced */
  @Nullable
  private static GrExpression addParenthesesIfNeeded(
      GrExpression newExpr, GrExpression oldExpr, GrExpression oldParent) {
    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(oldExpr.getProject());

    int parentPriorityLevel = getExprPriorityLevel(oldParent);
    int newPriorityLevel = getExprPriorityLevel(newExpr);

    if (parentPriorityLevel > newPriorityLevel) {
      newExpr = factory.createParenthesizedExpr(newExpr);
    } else if (parentPriorityLevel == newPriorityLevel && parentPriorityLevel != 0) {
      if (oldParent instanceof GrBinaryExpression) {
        GrBinaryExpression binaryExpression = (GrBinaryExpression) oldParent;
        if (isNotAssociative(binaryExpression)
            && oldExpr.equals(binaryExpression.getRightOperand())) {
          newExpr = factory.createParenthesizedExpr(newExpr);
        }
      }
    }
    return newExpr;
  }
 public void visitAssignmentExpression(GrAssignmentExpression expression) {
   GrExpression rValue = expression.getRValue();
   GrExpression lValue = expression.getLValue();
   if (myExpression.equals(rValue)) {
     PsiType lType = lValue.getNominalType();
     if (lType != null) {
       myResult = new TypeConstraint[] {SubtypeConstraint.create(lType)};
     } else if (lValue instanceof GrReferenceExpression) {
       GroovyResolveResult result = ((GrReferenceExpression) lValue).advancedResolve();
       PsiElement resolved = result.getElement();
       if (resolved instanceof GrVariable) {
         PsiType type = ((GrVariable) resolved).getTypeGroovy();
         if (type != null) {
           myResult =
               new TypeConstraint[] {
                 SubtypeConstraint.create(result.getSubstitutor().substitute(type))
               };
         }
       }
     }
   } else if (myExpression.equals(lValue)) {
     if (rValue != null) {
       PsiType rType = rValue.getType();
       if (rType != null) {
         myResult = new TypeConstraint[] {SupertypeConstraint.create(rType)};
       }
     }
   }
 }
  private boolean isDefinitelyKeyOfMap() {
    final GrExpression qualifier = ResolveUtil.getSelfOrWithQualifier(this);
    if (qualifier == null) return false;
    if (qualifier
        instanceof
        GrReferenceExpression) { // key in 'java.util.Map.key' is not access to map, it is access to
      // static property of field
      final PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
      if (resolved instanceof PsiClass) return false;
    }

    final PsiType type = qualifier.getType();
    if (type == null) return false;

    if (!InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) return false;

    final String canonicalText = type.getCanonicalText();
    if (canonicalText.startsWith("java.")) return true;
    if (GroovyCommonClassNames.GROOVY_UTIL_CONFIG_OBJECT.equals(canonicalText)) return false;
    if (canonicalText.startsWith("groovy.")) return true;

    return false;
  }
    @Nullable
    public PsiType fun(GrReferenceExpressionImpl refExpr) {
      PsiType result = GrReassignedLocalVarsChecker.checkReassignedVar(refExpr, true);
      if (result != null) return result;

      if (GrUnresolvedAccessInspection.isClassReference(refExpr)) {
        GrExpression qualifier = refExpr.getQualifier();
        LOG.assertTrue(qualifier != null);
        return TypesUtil.createJavaLangClassType(
            qualifier.getType(), refExpr.getProject(), refExpr.getResolveScope());
      }

      final PsiElement resolved = refExpr.resolve();
      final PsiType inferred = getInferredTypes(refExpr, resolved);
      final PsiType nominal = refExpr.getNominalType();
      if (inferred == null || PsiType.NULL.equals(inferred)) {
        if (nominal == null) {
          // inside nested closure we could still try to infer from variable initializer. Not sound,
          // but makes sense
          if (resolved instanceof GrVariable) {
            LOG.assertTrue(resolved.isValid());
            return ((GrVariable) resolved).getTypeGroovy();
          }
        }

        return nominal;
      }

      if (nominal == null) return inferred;
      if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
        if (resolved instanceof GrVariable
            && ((GrVariable) resolved).getTypeElementGroovy() != null) {
          return nominal;
        }
      }
      return inferred;
    }
Ejemplo n.º 26
0
  @Nullable
  public static PsiType inferExpectedTypeForDiamond(GrExpression diamondNew) {
    PsiElement skipped = PsiUtil.skipParentheses(diamondNew, true);
    assert skipped != null;
    PsiElement pparent = skipped.getParent();
    if (pparent instanceof GrAssignmentExpression
        && PsiTreeUtil.isAncestor(
            ((GrAssignmentExpression) pparent).getRValue(), diamondNew, false)) {
      GrExpression lValue = ((GrAssignmentExpression) pparent).getLValue();
      if (PsiUtil.mightBeLValue(lValue)) {
        return lValue.getNominalType();
      }
    } else if (pparent instanceof GrVariable
        && ((GrVariable) pparent).getInitializerGroovy() == diamondNew) {
      return ((GrVariable) pparent).getDeclaredType();
    } else if (pparent instanceof GrListOrMap) {
      PsiElement ppparent = PsiUtil.skipParentheses(pparent.getParent(), true);

      if (ppparent instanceof GrAssignmentExpression
          && PsiTreeUtil.isAncestor(
              ((GrAssignmentExpression) ppparent).getRValue(), pparent, false)) {

        PsiElement lValue =
            PsiUtil.skipParentheses(((GrAssignmentExpression) ppparent).getLValue(), false);
        if (lValue instanceof GrTupleExpression) {
          GrExpression[] initializers = ((GrListOrMap) pparent).getInitializers();
          int index = ArrayUtil.find(initializers, diamondNew);
          GrExpression[] expressions = ((GrTupleExpression) lValue).getExpressions();
          if (index < expressions.length) {
            return expressions[index].getNominalType();
          }
        }
      }
    }

    return null;
  }
  private static boolean shouldHighlightAsUnresolved(
      @NotNull GrReferenceExpression referenceExpression) {
    if (GrHighlightUtil.isDeclarationAssignment(referenceExpression)) return false;

    GrExpression qualifier = referenceExpression.getQualifier();
    if (qualifier != null && qualifier.getType() == null && !isRefToPackage(qualifier))
      return false;

    if (qualifier != null
        && referenceExpression.getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER
        && referenceExpression.multiResolve(false).length > 0) {
      return false;
    }

    if (!GroovyUnresolvedHighlightFilter.shouldHighlight(referenceExpression)) return false;

    CollectConsumer<PomTarget> consumer = new CollectConsumer<PomTarget>();
    for (PomDeclarationSearcher searcher : PomDeclarationSearcher.EP_NAME.getExtensions()) {
      searcher.findDeclarationsAt(referenceExpression, 0, consumer);
      if (!consumer.getResult().isEmpty()) return false;
    }

    return true;
  }
    public void visitMethodCallExpression(GrMethodCallExpression methodCall) {
      final GrExpression invokedExpression = methodCall.getInvokedExpression();
      if (myExpression.equals(invokedExpression)) {
        myResult =
            new TypeConstraint[] {
              SubtypeConstraint.create(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, methodCall)
            };
        return;
      }

      final GrClosableBlock[] closureArgs = methodCall.getClosureArguments();
      //noinspection SuspiciousMethodCalls
      final int closureIndex = Arrays.asList(closureArgs).indexOf(myExpression);
      if (closureIndex >= 0) {
        List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
        for (GroovyResolveResult variant : ResolveUtil.getCallVariants(myExpression)) {
          final GrArgumentList argumentList = methodCall.getArgumentList();
          final GrNamedArgument[] namedArgs =
              argumentList == null ? GrNamedArgument.EMPTY_ARRAY : argumentList.getNamedArguments();
          final GrExpression[] expressionArgs =
              argumentList == null
                  ? GrExpression.EMPTY_ARRAY
                  : argumentList.getExpressionArguments();
          try {
            final Map<GrExpression, Pair<PsiParameter, PsiType>> map =
                GrClosureSignatureUtil.mapArgumentsToParameters(
                    variant, methodCall, true, true, namedArgs, expressionArgs, closureArgs);
            addConstraintsFromMap(constraints, map);
          } catch (RuntimeException e) {
            LOG.error(
                "call: " + methodCall.getText() + "\nsymbol: " + variant.getElement().getText(), e);
          }
        }
        if (!constraints.isEmpty()) {
          myResult = constraints.toArray(new TypeConstraint[constraints.size()]);
        }
      }
    }
    @Override
    public void visitAnnotationNameValuePair(GrAnnotationNameValuePair nameValuePair) {
      if (myExpression.equals(nameValuePair.getValue())) {
        final PsiClass annot = ResolveUtil.resolveAnnotation(nameValuePair.getParent());
        if (annot != null) {
          final String name = nameValuePair.getName();
          if (name != null) {
            final PsiMethod[] attrs = annot.findMethodsByName(name, false);
            if (attrs.length > 0) {
              PsiType type = attrs[0].getReturnType();
              while (type instanceof PsiArrayType) type = ((PsiArrayType) type).getComponentType();
              if (type != null && isAcceptableAnnotationValueType(type)) {
                myResult = createSimpleSubTypeResult(type);
              }
            }
          } else {
            final PsiMethod[] valueAttr = annot.findMethodsByName("value", false);
            boolean canHaveSimpleExpr = valueAttr.length > 0;
            final PsiMethod[] methods = annot.getMethods();
            for (PsiMethod method : methods) {
              if (!("value".equals(method.getName())
                  || method instanceof PsiAnnotationMethod
                      && ((PsiAnnotationMethod) method).getDefaultValue() != null)) {
                canHaveSimpleExpr = false;
              }
            }

            if (canHaveSimpleExpr) {
              PsiType type = valueAttr[0].getReturnType();
              while (type instanceof PsiArrayType) type = ((PsiArrayType) type).getComponentType();
              if (type != null && isAcceptableAnnotationValueType(type)) {
                myResult = createSimpleSubTypeResult(type);
              }
            }
          }
        }
      }
    }
  @Nullable
  private PsiType getNominalTypeInner(PsiElement resolved) {
    if (resolved == null && !"class".equals(getReferenceName())) {
      resolved = resolve();
    }

    if (resolved instanceof PsiClass) {
      final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
      if (PsiUtil.isInstanceThisRef(this)) {
        final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved);
        if (categoryType != null) {
          return categoryType;
        } else {
          return factory.createType((PsiClass) resolved);
        }
      }
      if (getParent() instanceof GrReferenceExpression || PsiUtil.isSuperReference(this)) {
        return factory.createType((PsiClass) resolved);
      } else {
        return TypesUtil.createJavaLangClassType(
            factory.createType((PsiClass) resolved), getProject(), getResolveScope());
      }
    }

    if (resolved instanceof GrVariable) {
      return ((GrVariable) resolved).getDeclaredType();
    }

    if (resolved instanceof PsiVariable) {
      return ((PsiVariable) resolved).getType();
    }

    if (resolved instanceof PsiMethod) {
      PsiMethod method = (PsiMethod) resolved;
      if (PropertyUtil.isSimplePropertySetter(method)
          && !method.getName().equals(getReferenceName())) {
        return method.getParameterList().getParameters()[0].getType();
      }

      // 'class' property with explicit generic
      PsiClass containingClass = method.getContainingClass();
      if (containingClass != null
          && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())
          && "getClass".equals(method.getName())) {
        return TypesUtil.createJavaLangClassType(
            GrReferenceResolveUtil.getQualifierType(this), getProject(), getResolveScope());
      }

      return PsiUtil.getSmartReturnType(method);
    }

    if (resolved instanceof GrReferenceExpression) {
      PsiElement parent = resolved.getParent();
      if (parent instanceof GrAssignmentExpression) {
        GrAssignmentExpression assignment = (GrAssignmentExpression) parent;
        if (resolved.equals(assignment.getLValue())) {
          GrExpression rValue = assignment.getRValue();
          if (rValue != null) {
            PsiType rType = rValue.getType();
            if (rType != null) {
              return rType;
            }
          }
        }
      }
    }

    if (resolved == null) {
      final PsiType fromClassRef = getTypeFromClassRef(this);
      if (fromClassRef != null) {
        return fromClassRef;
      }

      final PsiType fromMapAccess = getTypeFromMapAccess(this);
      if (fromMapAccess != null) {
        return fromMapAccess;
      }

      final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this);
      if (fromSpreadOperator != null) {
        return fromSpreadOperator;
      }
    }

    return null;
  }