public void verifyVariable(@NotNull final PsiLocalVariable psiLocalVariable, @NotNull final ProblemsHolder holder) { boolean isVal = isSameName(psiLocalVariable.getTypeElement().getText()); boolean isVar = isVar(psiLocalVariable.getTypeElement().getText()); final String ann = isVal ? "val" : "var"; if (isVal || isVar) { final PsiExpression initializer = psiLocalVariable.getInitializer(); if (initializer == null) { holder.registerProblem(psiLocalVariable, "'" + ann + "' on a local variable requires an initializer expression", ProblemHighlightType.ERROR); } else if (initializer instanceof PsiArrayInitializerExpression) { holder.registerProblem(psiLocalVariable, "'" + ann + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })", ProblemHighlightType.ERROR); } else if (initializer instanceof PsiLambdaExpression) { holder.registerProblem(psiLocalVariable, "'" + ann + "' is not allowed with lambda expressions.", ProblemHighlightType.ERROR); } else if (isVal) { final PsiElement typeParentParent = psiLocalVariable.getParent(); if (typeParentParent instanceof PsiDeclarationStatement && typeParentParent.getParent() instanceof PsiForStatement) { holder.registerProblem(psiLocalVariable, "'" + ann + "' is not allowed in old-style for loops", ProblemHighlightType.ERROR); } } } }
/** * {@link JavaSmartEnterProcessor#registerUnresolvedError(int) registers target offset} taking care of the situation when * current code style implies white space after 'for' part's semicolon. * * @param editor target editor * @param processor target smart enter processor * @param lastValidForPart last valid element of the target 'for' loop * @param forStatement PSI element for the target 'for' loop */ private static void registerErrorOffset(@NotNull Editor editor, @NotNull JavaSmartEnterProcessor processor, @NotNull PsiElement lastValidForPart, @NotNull PsiForStatement forStatement) { final Project project = editor.getProject(); int offset = lastValidForPart.getTextRange().getEndOffset(); if(project != null && CodeStyleSettingsManager.getSettings(project).SPACE_AFTER_COMMA) { if(editor.getDocument().getCharsSequence().charAt(lastValidForPart.getTextRange().getEndOffset() - 1) != ';') { offset++; } for(PsiElement element = lastValidForPart.getNextSibling(); element != null && element != forStatement.getRParenth() && element.getParent() == forStatement; element = element .getNextSibling()) { final ASTNode node = element.getNode(); if(node != null && JavaJspElementType.WHITE_SPACE_BIT_SET.contains(node.getElementType()) && element.getTextLength() > 0) { offset++; break; } } } processor.registerUnresolvedError(offset); }
public boolean satisfiedBy(PsiElement element) { if (!(element instanceof PsiJavaToken)) { return false; } final PsiJavaToken token = (PsiJavaToken)element; final IElementType tokenType = token.getTokenType(); if (!JavaTokenType.FOR_KEYWORD.equals(tokenType)) { return false; } final PsiElement parent = element.getParent(); return parent instanceof PsiForStatement && !ErrorUtil.containsError(parent); }
public void verifyParameter(@NotNull final PsiParameter psiParameter, @NotNull final ProblemsHolder holder) { final PsiTypeElement typeElement = psiParameter.getTypeElement(); boolean isVal = null != typeElement && isSameName(typeElement.getText()); boolean isVar = null != typeElement && isVar(typeElement.getText()); if (isVar || isVal) { PsiElement scope = psiParameter.getDeclarationScope(); boolean isForeachStatement = scope instanceof PsiForeachStatement; boolean isForStatement = scope instanceof PsiForStatement; if (isVal && !isForeachStatement) { holder.registerProblem(psiParameter, "'val' works only on local variables and on foreach loops", ProblemHighlightType.ERROR); } else if (isVar && !(isForeachStatement || isForStatement)) { holder.registerProblem(psiParameter, "'var' works only on local variables and on for/foreach loops", ProblemHighlightType.ERROR); } } }
@Override public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { PsiForStatement forStatement = getForStatementParent(psiElement); if(forStatement == null) { return; } final Document doc = editor.getDocument(); PsiElement body = forStatement.getBody(); if(body instanceof PsiBlockStatement) { return; } if(body != null && startLine(doc, body) == startLine(doc, forStatement)) { return; } PsiElement eltToInsertAfter = forStatement.getRParenth(); String text = "{}"; if(eltToInsertAfter == null) { eltToInsertAfter = forStatement; text = "){}"; } doc.insertString(eltToInsertAfter.getTextRange().getEndOffset(), text); }
@Nullable private static PsiForStatement getForStatementParent(PsiElement psiElement) { PsiForStatement statement = PsiTreeUtil.getParentOfType(psiElement, PsiForStatement.class); if(statement == null) { return null; } PsiStatement init = statement.getInitialization(); PsiStatement update = statement.getUpdate(); PsiExpression check = statement.getCondition(); return isValidChild(init, psiElement) || isValidChild(update, psiElement) || isValidChild(check, psiElement) ? statement : null; }
@Override public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { if(!(psiElement instanceof PsiForStatement)) { return; } PsiForStatement forStatement = (PsiForStatement) psiElement; final PsiJavaToken lParenth = forStatement.getLParenth(); final PsiJavaToken rParenth = forStatement.getRParenth(); if(lParenth == null || rParenth == null) { final TextRange textRange = forStatement.getTextRange(); editor.getDocument().replaceString(textRange.getStartOffset(), textRange.getEndOffset(), "for () {\n}"); processor.registerUnresolvedError(textRange.getStartOffset() + "for (".length()); return; } final PsiStatement initialization = forStatement.getInitialization(); if(initialization == null) { processor.registerUnresolvedError(lParenth.getTextRange().getEndOffset()); return; } final PsiExpression condition = forStatement.getCondition(); if(condition == null) { registerErrorOffset(editor, processor, initialization, forStatement); return; } if(forStatement.getUpdate() == null) { registerErrorOffset(editor, processor, condition, forStatement); } }
@Override public void visitForStatement(PsiForStatement statement) { mVisitor.report("PsiForStatement", statement.getText(), statement); super.visitStatement(statement); }
@Override public void visitForStatement( @NotNull PsiForStatement statement) { super.visitForStatement(statement); checkStatement(statement); }
@Nullable public static CountingLoop from(PsiForStatement forStatement) { // check that initialization is for(int/long i = <initial_value>;...;...) PsiDeclarationStatement initialization = tryCast(forStatement.getInitialization(), PsiDeclarationStatement.class); if(initialization == null || initialization.getDeclaredElements().length != 1) { return null; } PsiLocalVariable counter = tryCast(initialization.getDeclaredElements()[0], PsiLocalVariable.class); if(counter == null) { return null; } if(!counter.getType().equals(PsiType.INT) && !counter.getType().equals(PsiType.LONG)) { return null; } PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(counter.getInitializer()); if(initializer == null) { return null; } // check that increment is like for(...;...;i++) if(!VariableAccessUtils.variableIsIncremented(counter, forStatement.getUpdate())) { return null; } // check that condition is like for(...;i<bound;...) or for(...;i<=bound;...) PsiBinaryExpression condition = tryCast(forStatement.getCondition(), PsiBinaryExpression.class); if(condition == null) { return null; } IElementType type = condition.getOperationTokenType(); boolean closed = false; PsiExpression bound; PsiExpression ref; if(type.equals(JavaTokenType.LE)) { bound = condition.getROperand(); ref = condition.getLOperand(); closed = true; } else if(type.equals(JavaTokenType.LT)) { bound = condition.getROperand(); ref = condition.getLOperand(); } else if(type.equals(JavaTokenType.GE)) { bound = condition.getLOperand(); ref = condition.getROperand(); closed = true; } else if(type.equals(JavaTokenType.GT)) { bound = condition.getLOperand(); ref = condition.getROperand(); } else { return null; } if(bound == null || !ExpressionUtils.isReferenceTo(ref, counter)) { return null; } if(!TypeConversionUtil.areTypesAssignmentCompatible(counter.getType(), bound)) { return null; } return new CountingLoop(forStatement, counter, initializer, bound, closed); }
@Override public void visitForStatement(@NotNull PsiForStatement statement) { super.visitForStatement(statement); checkStatement(statement); }
@Nullable protected PsiElement calcPsiElement() { PsiFile psiFile = getFile(); int lineNumber = getLine(); if(lineNumber < 0) { return psiFile; } final Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); if (document == null) { return null; } if (lineNumber >= document.getLineCount()) { return psiFile; } int startOffset = document.getLineStartOffset(lineNumber); if(startOffset == -1) { return null; } PsiElement rootElement = psiFile; List<PsiFile> allFiles = psiFile.getViewProvider().getAllFiles(); if (allFiles.size() > 1) { // jsp & gsp PsiClassOwner owner = ContainerUtil.findInstance(allFiles, PsiClassOwner.class); if (owner != null) { PsiClass[] classes = owner.getClasses(); if (classes.length == 1 && classes[0] instanceof SyntheticElement) { rootElement = classes[0]; } } } PsiElement element; while(true) { final CharSequence charsSequence = document.getCharsSequence(); for (; startOffset < charsSequence.length(); startOffset++) { char c = charsSequence.charAt(startOffset); if (c != ' ' && c != '\t') { break; } } element = rootElement.findElementAt(startOffset); if(element instanceof PsiComment) { startOffset = element.getTextRange().getEndOffset() + 1; } else{ break; } } if (element != null && element.getParent() instanceof PsiForStatement) { return ((PsiForStatement)element.getParent()).getInitialization(); } return element; }