public void testInferInCall1() throws Exception {
   PsiReferenceExpression ref = configure();
   PsiType type = ref.getType();
   assertTrue(type instanceof PsiClassType);
   PsiType[] paramTypes = ((PsiClassType) type).getParameters();
   assertEquals(1, paramTypes.length);
   assertEquals(CommonClassNames.JAVA_LANG_OBJECT, paramTypes[0].getCanonicalText());
 }
 public void testInferInAssign1() throws Exception {
   PsiReferenceExpression ref = configure();
   PsiType type = ref.getType();
   assertTrue(type instanceof PsiClassType);
   PsiType[] paramTypes = ((PsiClassType) type).getParameters();
   assertEquals(1, paramTypes.length);
   assertEquals("java.lang.String", paramTypes[0].getCanonicalText());
 }
 /** @return true, if a declaration was introduced, false otherwise */
 private static boolean replaceVariableName(
     PsiElement element,
     PsiReferenceExpression firstReference,
     String newName,
     String originalName,
     StringBuilder out) {
   if (element instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) element;
     if (element.equals(firstReference) && isLeftSideOfSimpleAssignment(referenceExpression)) {
       final PsiType type = firstReference.getType();
       if (type != null) {
         out.append(type.getCanonicalText());
         out.append(' ');
         out.append(newName);
         return true;
       }
     }
     final String text = element.getText();
     if (text.equals(originalName)) {
       out.append(newName);
       return false;
     }
   }
   final PsiElement[] children = element.getChildren();
   if (children.length == 0) {
     final String text = element.getText();
     out.append(text);
   } else {
     boolean result = false;
     for (final PsiElement child : children) {
       if (result) {
         out.append(child.getText());
       } else {
         result = replaceVariableName(child, firstReference, newName, originalName, out);
       }
     }
     return result;
   }
   return false;
 }
 private void checkResolvesTo(@NonNls String typeName) throws Exception {
   PsiReferenceExpression ref = configure();
   PsiType type = ref.getType();
   assertNotNull(type);
   assertEquals(typeName, type.getCanonicalText());
 }
 @Nullable
 private String createListIterationText(@NotNull PsiForStatement forStatement) {
   final PsiBinaryExpression condition =
       (PsiBinaryExpression) ParenthesesUtils.stripParentheses(forStatement.getCondition());
   if (condition == null) {
     return null;
   }
   final PsiExpression lhs = ParenthesesUtils.stripParentheses(condition.getLOperand());
   if (lhs == null) {
     return null;
   }
   final PsiExpression rhs = ParenthesesUtils.stripParentheses(condition.getROperand());
   if (rhs == null) {
     return null;
   }
   final IElementType tokenType = condition.getOperationTokenType();
   final String indexName;
   PsiExpression collectionSize;
   if (JavaTokenType.LT.equals(tokenType)) {
     indexName = lhs.getText();
     collectionSize = rhs;
   } else if (JavaTokenType.GT.equals(tokenType)) {
     indexName = rhs.getText();
     collectionSize = lhs;
   } else {
     return null;
   }
   if (collectionSize instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collectionSize;
     final PsiElement target = referenceExpression.resolve();
     if (target instanceof PsiVariable) {
       final PsiVariable variable = (PsiVariable) target;
       collectionSize = ParenthesesUtils.stripParentheses(variable.getInitializer());
     }
   }
   if (!(collectionSize instanceof PsiMethodCallExpression)) {
     return null;
   }
   final PsiMethodCallExpression methodCallExpression =
       (PsiMethodCallExpression) ParenthesesUtils.stripParentheses(collectionSize);
   if (methodCallExpression == null) {
     return null;
   }
   final PsiReferenceExpression listLengthExpression =
       methodCallExpression.getMethodExpression();
   final PsiExpression qualifier =
       ParenthesesUtils.stripParentheses(listLengthExpression.getQualifierExpression());
   final PsiReferenceExpression listReference;
   if (qualifier instanceof PsiReferenceExpression) {
     listReference = (PsiReferenceExpression) qualifier;
   } else {
     listReference = null;
   }
   PsiType parameterType;
   if (listReference == null) {
     parameterType = extractListTypeFromContainingClass(forStatement);
   } else {
     final PsiType type = listReference.getType();
     if (type == null) {
       return null;
     }
     parameterType = extractContentTypeFromType(type);
   }
   if (parameterType == null) {
     parameterType = TypeUtils.getObjectType(forStatement);
   }
   final String typeString = parameterType.getCanonicalText();
   final PsiVariable listVariable;
   if (listReference == null) {
     listVariable = null;
   } else {
     final PsiElement target = listReference.resolve();
     if (!(target instanceof PsiVariable)) {
       return null;
     }
     listVariable = (PsiVariable) target;
   }
   final PsiStatement body = forStatement.getBody();
   final PsiStatement firstStatement = getFirstStatement(body);
   final boolean isDeclaration =
       isListElementDeclaration(firstStatement, listVariable, indexName, parameterType);
   final String contentVariableName;
   @NonNls final String finalString;
   final PsiStatement statementToSkip;
   if (isDeclaration) {
     final PsiDeclarationStatement declarationStatement =
         (PsiDeclarationStatement) firstStatement;
     assert declarationStatement != null;
     final PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
     final PsiElement declaredElement = declaredElements[0];
     if (!(declaredElement instanceof PsiVariable)) {
       return null;
     }
     final PsiVariable variable = (PsiVariable) declaredElement;
     contentVariableName = variable.getName();
     statementToSkip = declarationStatement;
     if (variable.hasModifierProperty(PsiModifier.FINAL)) {
       finalString = "final ";
     } else {
       finalString = "";
     }
   } else {
     final String collectionName;
     if (listReference == null) {
       collectionName = null;
     } else {
       collectionName = listReference.getReferenceName();
     }
     contentVariableName = createNewVariableName(forStatement, parameterType, collectionName);
     finalString = "";
     statementToSkip = null;
   }
   @NonNls final StringBuilder out = new StringBuilder();
   out.append("for(");
   out.append(finalString);
   out.append(typeString);
   out.append(' ');
   out.append(contentVariableName);
   out.append(": ");
   @NonNls final String listName;
   if (listReference == null) {
     listName = "this";
   } else {
     listName = listReference.getText();
   }
   out.append(listName);
   out.append(')');
   if (body != null) {
     replaceCollectionGetAccess(
         body, contentVariableName, listVariable, indexName, statementToSkip, out);
   }
   return out.toString();
 }
 @Nullable
 private String createArrayIterationText(@NotNull PsiForStatement forStatement) {
   final PsiExpression condition = forStatement.getCondition();
   final PsiBinaryExpression strippedCondition =
       (PsiBinaryExpression) ParenthesesUtils.stripParentheses(condition);
   if (strippedCondition == null) {
     return null;
   }
   final PsiExpression lhs = ParenthesesUtils.stripParentheses(strippedCondition.getLOperand());
   if (lhs == null) {
     return null;
   }
   final PsiExpression rhs = ParenthesesUtils.stripParentheses(strippedCondition.getROperand());
   if (rhs == null) {
     return null;
   }
   final IElementType tokenType = strippedCondition.getOperationTokenType();
   final PsiReferenceExpression arrayLengthExpression;
   final String indexName;
   if (tokenType.equals(JavaTokenType.LT)) {
     arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(rhs);
     indexName = lhs.getText();
   } else if (tokenType.equals(JavaTokenType.GT)) {
     arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(lhs);
     indexName = rhs.getText();
   } else {
     return null;
   }
   if (arrayLengthExpression == null) {
     return null;
   }
   PsiReferenceExpression arrayReference =
       (PsiReferenceExpression) arrayLengthExpression.getQualifierExpression();
   if (arrayReference == null) {
     final PsiElement target = arrayLengthExpression.resolve();
     if (!(target instanceof PsiVariable)) {
       return null;
     }
     final PsiVariable variable = (PsiVariable) target;
     final PsiExpression initializer = variable.getInitializer();
     if (!(initializer instanceof PsiReferenceExpression)) {
       return null;
     }
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) initializer;
     arrayReference = (PsiReferenceExpression) referenceExpression.getQualifierExpression();
     if (arrayReference == null) {
       return null;
     }
   }
   final PsiType type = arrayReference.getType();
   if (!(type instanceof PsiArrayType)) {
     return null;
   }
   final PsiArrayType arrayType = (PsiArrayType) type;
   final PsiType componentType = arrayType.getComponentType();
   final String typeText = componentType.getCanonicalText();
   final PsiElement target = arrayReference.resolve();
   if (!(target instanceof PsiVariable)) {
     return null;
   }
   final PsiVariable arrayVariable = (PsiVariable) target;
   final PsiStatement body = forStatement.getBody();
   final PsiStatement firstStatement = getFirstStatement(body);
   final boolean isDeclaration =
       isArrayElementDeclaration(firstStatement, arrayVariable, indexName);
   final String contentVariableName;
   @NonNls final String finalString;
   final PsiStatement statementToSkip;
   if (isDeclaration) {
     final PsiDeclarationStatement declarationStatement =
         (PsiDeclarationStatement) firstStatement;
     assert declarationStatement != null;
     final PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
     final PsiElement declaredElement = declaredElements[0];
     if (!(declaredElement instanceof PsiVariable)) {
       return null;
     }
     final PsiVariable variable = (PsiVariable) declaredElement;
     if (VariableAccessUtils.variableIsAssigned(variable, forStatement)) {
       final String collectionName = arrayReference.getReferenceName();
       contentVariableName = createNewVariableName(forStatement, componentType, collectionName);
       final Project project = forStatement.getProject();
       final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
       if (codeStyleSettings.GENERATE_FINAL_LOCALS) {
         finalString = "final ";
       } else {
         finalString = "";
       }
       statementToSkip = null;
     } else {
       contentVariableName = variable.getName();
       statementToSkip = declarationStatement;
       if (variable.hasModifierProperty(PsiModifier.FINAL)) {
         finalString = "final ";
       } else {
         finalString = "";
       }
     }
   } else {
     final String collectionName = arrayReference.getReferenceName();
     contentVariableName = createNewVariableName(forStatement, componentType, collectionName);
     final Project project = forStatement.getProject();
     final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
     if (codeStyleSettings.GENERATE_FINAL_LOCALS) {
       finalString = "final ";
     } else {
       finalString = "";
     }
     statementToSkip = null;
   }
   @NonNls final StringBuilder out = new StringBuilder();
   out.append("for(");
   out.append(finalString);
   out.append(typeText);
   out.append(' ');
   out.append(contentVariableName);
   out.append(": ");
   final String arrayName = arrayReference.getText();
   out.append(arrayName);
   out.append(')');
   if (body != null) {
     replaceArrayAccess(
         body, contentVariableName, arrayVariable, indexName, statementToSkip, out);
   }
   return out.toString();
 }
 private static boolean isInConcatenationContext(PsiElement element) {
   final PsiElement parent = element.getParent();
   if (parent instanceof PsiPolyadicExpression) {
     final PsiPolyadicExpression parentExpression = (PsiPolyadicExpression) parent;
     final PsiType parentType = parentExpression.getType();
     if (parentType == null) {
       return false;
     }
     final String parentTypeText = parentType.getCanonicalText();
     return JAVA_LANG_STRING.equals(parentTypeText);
   } else if (parent instanceof PsiAssignmentExpression) {
     final PsiAssignmentExpression parentExpression = (PsiAssignmentExpression) parent;
     final IElementType tokenType = parentExpression.getOperationTokenType();
     if (!JavaTokenType.PLUSEQ.equals(tokenType)) {
       return false;
     }
     final PsiType parentType = parentExpression.getType();
     if (parentType == null) {
       return false;
     }
     final String parentTypeText = parentType.getCanonicalText();
     return JAVA_LANG_STRING.equals(parentTypeText);
   } else if (parent instanceof PsiExpressionList) {
     final PsiElement grandParent = parent.getParent();
     if (!(grandParent instanceof PsiMethodCallExpression)) {
       return false;
     }
     final PsiMethodCallExpression methodCall = (PsiMethodCallExpression) grandParent;
     final PsiReferenceExpression methodExpression = methodCall.getMethodExpression();
     final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
     final PsiType type;
     if (qualifierExpression == null) {
       // to use the intention inside the source of
       // String and StringBuffer
       type = methodExpression.getType();
     } else {
       type = qualifierExpression.getType();
     }
     if (type == null) {
       return false;
     }
     final String className = type.getCanonicalText();
     if (CommonClassNames.JAVA_LANG_STRING_BUFFER.equals(className)
         || CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(className)) {
       @NonNls final String methodName = methodExpression.getReferenceName();
       if (!"append".equals(methodName) && !"insert".equals(methodName)) {
         return false;
       }
       final PsiElement method = methodExpression.resolve();
       return method != null;
     } else if (JAVA_LANG_STRING.equals(className)) {
       @NonNls final String methodName = methodExpression.getReferenceName();
       if (!"indexOf".equals(methodName)
           && !"lastIndexOf".equals(methodName)
           && !"replace".equals(methodName)) {
         return false;
       }
       final PsiElement method = methodExpression.resolve();
       return method != null;
     }
   }
   return false;
 }
 @Override
 public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
   final PsiReferenceExpression parameterReference =
       (PsiReferenceExpression) descriptor.getPsiElement();
   final PsiElement target = parameterReference.resolve();
   if (!(target instanceof PsiParameter)) {
     return;
   }
   final PsiParameter parameter = (PsiParameter) target;
   final PsiElement declarationScope = parameter.getDeclarationScope();
   final PsiElement body;
   if (declarationScope instanceof PsiMethod) {
     final PsiMethod method = (PsiMethod) declarationScope;
     body = method.getBody();
   } else if (declarationScope instanceof PsiCatchSection) {
     final PsiCatchSection catchSection = (PsiCatchSection) declarationScope;
     body = catchSection.getCatchBlock();
   } else if (declarationScope instanceof PsiLoopStatement) {
     final PsiLoopStatement forStatement = (PsiLoopStatement) declarationScope;
     final PsiStatement forBody = forStatement.getBody();
     if (forBody instanceof PsiBlockStatement) {
       final PsiBlockStatement blockStatement = (PsiBlockStatement) forBody;
       body = blockStatement.getCodeBlock();
     } else {
       body = forBody;
     }
   } else {
     return;
   }
   if (body == null) {
     return;
   }
   final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
   final String parameterName = parameterReference.getText();
   final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
   final String variableName =
       javaCodeStyleManager.suggestUniqueVariableName(parameterName, parameterReference, true);
   final SearchScope scope = parameter.getUseScope();
   final Query<PsiReference> search = ReferencesSearch.search(parameter, scope);
   final PsiReference reference = search.findFirst();
   if (reference == null) {
     return;
   }
   final PsiElement element = reference.getElement();
   if (!(element instanceof PsiReferenceExpression)) {
     return;
   }
   final PsiReferenceExpression firstReference = (PsiReferenceExpression) element;
   final PsiElement[] children = body.getChildren();
   final int startIndex;
   final int endIndex;
   if (body instanceof PsiCodeBlock) {
     startIndex = 1;
     endIndex = children.length - 1;
   } else {
     startIndex = 0;
     endIndex = children.length;
   }
   boolean newDeclarationCreated = false;
   final StringBuilder buffer = new StringBuilder();
   for (int i = startIndex; i < endIndex; i++) {
     final PsiElement child = children[i];
     newDeclarationCreated |=
         replaceVariableName(child, firstReference, variableName, parameterName, buffer);
   }
   final String replacementText;
   if (newDeclarationCreated) {
     replacementText = "{" + buffer + '}';
   } else {
     final PsiType type = parameterReference.getType();
     if (type == null) {
       return;
     }
     final String className = type.getCanonicalText();
     replacementText =
         '{' + className + ' ' + variableName + " = " + parameterName + ';' + buffer + '}';
   }
   final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
   final PsiCodeBlock block = elementFactory.createCodeBlockFromText(replacementText, null);
   body.replace(block);
   codeStyleManager.reformat(declarationScope);
 }