/** * Reports issue if this call is inside PLog.x(). * Calling this method assumes actual calling method is 'String#format'. * * @see #ISSUE_NESTED_FORMAT */ private static void checkNestedStringFormat(JavaContext context, PsiMethodCallExpression call) { PsiElement current = call; while (true) { current = LintUtils.skipParentheses(current.getParent()); if (current == null || current instanceof PsiCodeBlock) { // Reached AST root or code block node; String.format not inside PLog.X(..). return; } if (current instanceof PsiMethodCallExpression) { PsiMethodCallExpression expression = (PsiMethodCallExpression) current; if (Pattern.matches("org\\.mym\\.plog\\.PLog\\.(v|d|i|w|e)", expression.getMethodExpression().getQualifiedName())) { sHelper.reportIssue(context, ISSUE_NESTED_FORMAT, call); return; } } } }
public LambdaMethodFilter(PsiLambdaExpression lambda, int expressionOrdinal, Range<Integer> callingExpressionLines) { myLambdaOrdinal = expressionOrdinal; myCallingExpressionLines = callingExpressionLines; SourcePosition firstStatementPosition = null; SourcePosition lastStatementPosition = null; final PsiElement body = lambda.getBody(); if (body instanceof PsiCodeBlock) { final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements(); if (statements.length > 0) { firstStatementPosition = SourcePosition.createFromElement(statements[0]); if (firstStatementPosition != null) { final PsiStatement lastStatement = statements[statements.length - 1]; lastStatementPosition = SourcePosition.createFromOffset(firstStatementPosition.getFile(), lastStatement.getTextRange().getEndOffset()); } } } else if (body != null) { firstStatementPosition = SourcePosition.createFromElement(body); } myFirstStatementPosition = firstStatementPosition; myLastStatementLine = lastStatementPosition != null ? lastStatementPosition.getLine() : -1; }
public AnonymousClassMethodFilter(PsiMethod psiMethod, Range<Integer> lines) { super(psiMethod, lines); SourcePosition firstStatementPosition = null; SourcePosition lastStatementPosition = null; final PsiCodeBlock body = psiMethod.getBody(); if (body != null) { final PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { firstStatementPosition = SourcePosition.createFromElement(statements[0]); if (firstStatementPosition != null) { final PsiStatement lastStatement = statements[statements.length - 1]; lastStatementPosition = SourcePosition.createFromOffset(firstStatementPosition.getFile(), lastStatement.getTextRange().getEndOffset()); } } } myBreakpointPosition = firstStatementPosition; myLastStatementLine = lastStatementPosition != null? lastStatementPosition.getLine() : -1; }
private static List<PsiStatement> getFinallyStatements(@Nullable SourcePosition position) { if (position == null) { return Collections.emptyList(); } List<PsiStatement> res = new ArrayList<PsiStatement>(); PsiElement element = position.getFile().findElementAt(position.getOffset()); PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class); while (tryStatement != null) { PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); if (finallyBlock != null) { ContainerUtil.addAll(res, finallyBlock.getStatements()); } tryStatement = PsiTreeUtil.getParentOfType(tryStatement, PsiTryStatement.class); } return res; }
@Override public void visitTryStatement(@NotNull PsiTryStatement statement) { super.visitTryStatement(statement); final PsiTryStatement parentTry = PsiTreeUtil.getParentOfType(statement, PsiTryStatement.class); if (parentTry == null) { return; } final PsiCodeBlock tryBlock = parentTry.getTryBlock(); if (tryBlock == null) { return; } if (!PsiTreeUtil.isAncestor(tryBlock, statement, true)) { return; } if (NestedSynchronizedStatementInspection.isNestedStatement(statement, PsiTryStatement.class)) { registerStatementError(statement); } }
@Override public void visitTryStatement(@NotNull PsiTryStatement statement) { super.visitTryStatement(statement); final PsiCodeBlock finallyBlock = statement.getFinallyBlock(); if (finallyBlock == null) { return; } if (ControlFlowUtils.codeBlockMayCompleteNormally(finallyBlock)) { return; } final PsiElement[] children = statement.getChildren(); for (final PsiElement child : children) { final String childText = child.getText(); if (PsiKeyword.FINALLY.equals(childText)) { registerError(child); return; } } }
private int calculateReturnPointCount(PsiMethod method) { final ReturnPointCountVisitor visitor = new ReturnPointCountVisitor(ignoreGuardClauses); method.accept(visitor); final int count = visitor.getCount(); if (!mayFallThroughBottom(method)) { return count; } final PsiCodeBlock body = method.getBody(); if (body == null) { return count; } final PsiStatement[] statements = body.getStatements(); if (statements.length == 0) { return count + 1; } final PsiStatement lastStatement = statements[statements.length - 1]; if (ControlFlowUtils.statementMayCompleteNormally(lastStatement)) { return count + 1; } return count; }
@Override public void readMethod(PsiCodeBlock methodBody, PsiElementFactory factory, PsiField field) { if (null == methodBody) { return; } String fieldName = field.getName(); String parameterType = ((PsiClassReferenceType) field.getType()).getParameters()[0].getPresentableText(); // // phones = new ArrayList<>(); // // in.readTypedList(phones, Phone.CREATOR); // methodBody.add(factory.createStatementFromText(fieldName + " = new ArrayList<" + parameterType + ">();", null)); // methodBody.add(factory.createStatementFromText("in.readTypedList(" + fieldName + ", " + parameterType + ".CREATOR);", null)); // phones = in.createTypedArrayList(Phone.CREATOR); methodBody.add(factory.createStatementFromText(fieldName + " = in.createTypedArrayList(" + parameterType + ".CREATOR);", null)); }
@Override public void visitSynchronizedStatement( @NotNull PsiSynchronizedStatement statement) { super.visitSynchronizedStatement(statement); if (FileTypeUtils.isInJsp(statement.getContainingFile())) { return; } final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { return; } registerStatementError(statement); }
@NotNull private PsiCodeBlock createCodeBlock(@NotNull PsiField psiField, @NotNull PsiClass psiClass, PsiType returnType, boolean isStatic, PsiParameter methodParameter) { final String blockText; if (isShouldGenerateFullBodyBlock()) { final String thisOrClass = isStatic ? psiClass.getName() : "this"; blockText = String.format("%s.%s = %s; ", thisOrClass, psiField.getName(), methodParameter.getName()); } else { blockText = ""; } String codeBlockText = blockText; if (!isStatic && !PsiType.VOID.equals(returnType)) { codeBlockText += "return this;"; } return PsiMethodUtil.createCodeBlockFromText(codeBlockText, psiClass); }
@NotNull private PsiCodeBlock createBuildMethodCodeBlock(@Nullable PsiMethod psiMethod, @NotNull PsiClass psiClass, @NotNull PsiType buildMethodReturnType, @NotNull String buildMethodPrepare, @NotNull String buildMethodParameters) { final String blockText; if (isShouldGenerateFullBodyBlock()) { final String codeBlockFormat, callExpressionText; if (null == psiMethod || psiMethod.isConstructor()) { codeBlockFormat = "%s\n return new %s(%s);"; callExpressionText = buildMethodReturnType.getPresentableText(); } else { if (PsiType.VOID.equals(buildMethodReturnType)) { codeBlockFormat = "%s\n %s(%s);"; } else { codeBlockFormat = "%s\n return %s(%s);"; } callExpressionText = calculateCallExpressionForMethod(psiMethod, psiClass); } blockText = String.format(codeBlockFormat, buildMethodPrepare, callExpressionText, buildMethodParameters); } else { blockText = "return " + PsiTypeUtil.getReturnValueOfType(buildMethodReturnType) + ";"; } return PsiMethodUtil.createCodeBlockFromText(blockText, psiClass); }
private boolean isChainingConstructor(PsiMethod constructor) { PsiCodeBlock body = constructor.getBody(); if (body != null) { PsiStatement[] statements = body.getStatements(); if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) { PsiExpression expression = ((PsiExpressionStatement) statements[0]).getExpression(); if (expression instanceof PsiMethodCallExpression) { PsiReferenceExpression methodExpr = ((PsiMethodCallExpression) expression).getMethodExpression(); if ("this".equals(methodExpr.getReferenceName())) { PsiElement resolved = methodExpr.resolve(); return resolved instanceof PsiMethod && ((PsiMethod) resolved).isConstructor(); //delegated via "this" call } } } } return false; }
@Override public PsiMethod[] generateGetters(PsiField field) { final Project project = field.getProject(); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); final PsiMethod getter = PropertyUtil.generateGetterPrototype(field); final PsiType wrappedType = JavaFxPsiUtil.getWrappedPropertyType(field, project, JavaFxCommonClassNames.ourReadOnlyMap); final PsiTypeElement returnTypeElement = getter.getReturnTypeElement(); LOG.assertTrue(returnTypeElement != null); returnTypeElement.replace(factory.createTypeElement(wrappedType)); final PsiCodeBlock getterBody = getter.getBody(); LOG.assertTrue(getterBody != null); getterBody.getStatements()[0].replace(factory.createStatementFromText("return " + field.getName() + ".get();", field)); final PsiMethod propertyGetter = PropertyUtil.generateGetterPrototype(field); propertyGetter.setName(JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD) + "Property"); return new PsiMethod[] {getter, propertyGetter}; }
@Override public PsiMethod[] generateSetters(PsiField field) { final PsiMethod setter = PropertyUtil.generateSetterPrototype(field); final Project project = field.getProject(); final PsiType wrappedType = JavaFxPsiUtil.getWrappedPropertyType(field, project, JavaFxCommonClassNames.ourWritableMap); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); final PsiTypeElement newTypeElement = elementFactory.createTypeElement(wrappedType); final PsiParameter[] parameters = setter.getParameterList().getParameters(); LOG.assertTrue(parameters.length == 1); final PsiParameter parameter = parameters[0]; final PsiTypeElement typeElement = parameter.getTypeElement(); LOG.assertTrue(typeElement != null); typeElement.replace(newTypeElement); final PsiCodeBlock body = setter.getBody(); LOG.assertTrue(body != null); body.getStatements()[0].replace(elementFactory.createStatementFromText("this." + field.getName() + ".set(" + parameter.getName() + ");", field)); return new PsiMethod[] {setter}; }
@NotNull @Override public List<StandardMethodContract> toContracts(PsiMethod method, Supplier<PsiCodeBlock> body) { PsiExpression expression = call.restoreExpression(body.get()); if(!(expression instanceof PsiMethodCallExpression)) { return Collections.emptyList(); } PsiMethod target = ((PsiMethodCallExpression) expression).resolveMethod(); if(target != null && NullableNotNullManager.isNotNull(target)) { return ContractInferenceInterpreter.toContracts(ContainerUtil.map(states, it -> it.toArray(new MethodContract.ValueConstraint[it.size()])), MethodContract.ValueConstraint.NOT_NULL_VALUE); } return Collections.emptyList(); }
private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiClass nestedClass) { DfaMemoryState state = instructionState.getMemoryState(); for(PsiMethod method : nestedClass.getMethods()) { PsiCodeBlock body = method.getBody(); if(body != null) { createClosureState(body, state); } } for(PsiClassInitializer initializer : nestedClass.getInitializers()) { createClosureState(initializer.getBody(), state); } for(PsiField field : nestedClass.getFields()) { createClosureState(field, state); } }
/** * Add new statement after given anchor statement creating code block, if necessary * * @param anchor existing statement * @param newStatement a new statement which should be added after an existing one * @return added physical statement */ public static PsiStatement addAfter(PsiStatement anchor, PsiStatement newStatement) { PsiElement oldStatement = anchor; PsiElement parent = oldStatement.getParent(); while(parent instanceof PsiLabeledStatement) { oldStatement = parent; parent = oldStatement.getParent(); } final PsiElement result; if(parent instanceof PsiCodeBlock) { result = parent.addAfter(newStatement, oldStatement); } else { PsiElementFactory factory = JavaPsiFacade.getElementFactory(anchor.getProject()); final PsiBlockStatement newBlockStatement = (PsiBlockStatement) factory.createStatementFromText("{}", oldStatement); final PsiElement codeBlock = newBlockStatement.getCodeBlock(); codeBlock.add(oldStatement); codeBlock.add(newStatement); result = ((PsiBlockStatement) oldStatement.replace(newBlockStatement)).getCodeBlock().getStatements()[1]; } return (PsiStatement) result; }
@Override public void invoke(@NotNull Project project, @NotNull PsiFile file, @Nullable("is null when called from inspection") Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { final PsiClass myClass = (PsiClass)startElement; if (!FileModificationService.getInstance().prepareFileForWrite(myClass.getContainingFile())) return; PsiCodeBlock body; if (myClass.isInterface() && (body = myMethodPrototype.getBody()) != null) body.delete(); for (String exception : myExceptions) { PsiUtil.addException(myMethodPrototype, exception); } PsiMethod method = (PsiMethod)myClass.add(myMethodPrototype); method = (PsiMethod)method.replace(reformat(project, method)); if (editor != null && method.getContainingFile() == file) { GenerateMembersUtil.positionCaret(editor, method, true); } }
@Override public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { if(!(psiElement instanceof PsiCatchSection)) { return; } PsiCatchSection catchSection = (PsiCatchSection) psiElement; final Document doc = editor.getDocument(); PsiCodeBlock body = catchSection.getCatchBlock(); if(body != null && startLine(doc, body) == startLine(doc, catchSection)) { return; } final PsiJavaToken rParenth = catchSection.getRParenth(); if(rParenth == null) { return; } doc.insertString(rParenth.getTextRange().getEndOffset(), "{}"); }
private boolean isInitializedInInitializer(@NotNull PsiField field, UninitializedReadCollector uninitializedReadsCollector) { final PsiClass aClass = field.getContainingClass(); if (aClass == null) { return false; } final PsiClassInitializer[] initializers = aClass.getInitializers(); for (final PsiClassInitializer initializer : initializers) { if (!initializer.hasModifierProperty(PsiModifier.STATIC)) { final PsiCodeBlock body = initializer.getBody(); if (uninitializedReadsCollector.blockAssignsVariable(body, field)) { return true; } } } return false; }
@Override public void visitSynchronizedStatement( @NotNull PsiSynchronizedStatement statement) { super.visitSynchronizedStatement(statement); /* if (JspPsiUtil.isInJspFile(statement.getContainingFile())) { return; }*/ final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { return; } registerStatementError(statement); }
public AnonymousClassMethodFilter(PsiMethod psiMethod, Range<Integer> lines) { super(psiMethod, lines); SourcePosition firstStatementPosition = null; SourcePosition lastStatementPosition = null; final PsiCodeBlock body = psiMethod.getBody(); if(body != null) { final PsiStatement[] statements = body.getStatements(); if(statements.length > 0) { firstStatementPosition = SourcePosition.createFromElement(statements[0]); if(firstStatementPosition != null) { final PsiStatement lastStatement = statements[statements.length - 1]; lastStatementPosition = SourcePosition.createFromOffset(firstStatementPosition.getFile(), lastStatement.getTextRange().getEndOffset()); } } } myBreakpointPosition = firstStatementPosition; myLastStatementLine = lastStatementPosition != null ? lastStatementPosition.getLine() : -1; }
@Override protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException { PsiCodeBlock body = ((PsiSynchronizedStatement)element).getBody(); context.extractFromCodeBlock(body, element); context.delete(element); }
@Override public boolean doEnter(Editor editor, PsiElement psiElement, boolean isModified) { PsiElement parent = psiElement.getParent(); if (!(parent instanceof PsiCodeBlock)) { return false; } final ASTNode node = psiElement.getNode(); if (node != null && CONTROL_FLOW_ELEMENT_TYPES.contains(node.getElementType())) { return false; } boolean leaveCodeBlock = isControlFlowBreak(psiElement); if (!leaveCodeBlock) { return false; } final int offset = parent.getTextRange().getEndOffset(); // Check if there is empty line after the code block. Just move caret there in the case of the positive answer. final CharSequence text = editor.getDocument().getCharsSequence(); if (offset < text.length() - 1) { final int i = CharArrayUtil.shiftForward(text, offset + 1, " \t"); if (i < text.length() && text.charAt(i) == '\n') { editor.getCaretModel().moveToOffset(offset + 1); EditorActionManager actionManager = EditorActionManager.getInstance(); EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_MOVE_LINE_END); final DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent()); if (dataContext != null) { actionHandler.execute(editor, dataContext); return true; } } } editor.getCaretModel().moveToOffset(offset); return false; }
@Override public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { if (psiElement instanceof PsiCodeBlock && afterUnmatchedBrace(editor,psiElement.getContainingFile().getFileType())) { PsiCodeBlock block = (PsiCodeBlock) psiElement; int stopOffset = block.getTextRange().getEndOffset(); final PsiStatement[] statements = block.getStatements(); if (statements.length > 0) { stopOffset = statements[0].getTextRange().getEndOffset(); } editor.getDocument().insertString(stopOffset, "}"); } }
@Override public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) { List<TextRange> result = new ArrayList<TextRange>(); final PsiElement parent = e.getParent(); if (parent instanceof PsiTryStatement) { final PsiTryStatement tryStatement = (PsiTryStatement)parent; final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); if (finallyBlock != null) { result.add(new TextRange(e.getTextRange().getStartOffset(), finallyBlock.getTextRange().getEndOffset())); } } return result; }
private static void doTestFor(final File file) throws Exception { String contents = StringUtil.convertLineSeparators(FileUtil.loadFile(file)); configureFromFileText(file.getName(), contents); // extract factory policy class name Pattern pattern = Pattern.compile("^// (\\S*).*", Pattern.DOTALL); Matcher matcher = pattern.matcher(contents); assertTrue(matcher.matches()); final String policyClassName = matcher.group(1); final ControlFlowPolicy policy; if ("LocalsOrMyInstanceFieldsControlFlowPolicy".equals(policyClassName)) { policy = LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(); } else { policy = null; } final int offset = getEditor().getCaretModel().getOffset(); PsiElement element = getFile().findElementAt(offset); element = PsiTreeUtil.getParentOfType(element, PsiCodeBlock.class, false); assertTrue("Selected element: "+element, element instanceof PsiCodeBlock); ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()).getControlFlow(element, policy); String result = controlFlow.toString().trim(); final String expectedFullPath = StringUtil.trimEnd(file.getPath(),".java") + ".txt"; VirtualFile expectedFile = LocalFileSystem.getInstance().findFileByPath(expectedFullPath); String expected = new String(expectedFile.contentsToByteArray()).trim(); expected = expected.replaceAll("\r",""); assertEquals("Text mismatch (in file "+expectedFullPath+"):\n",expected, result); }
public void testMethodWithOnlyDoWhileStatementHasExitPoints() throws Exception { configureFromFileText("a.java", "public class Foo {\n" + " public void foo() {\n" + " boolean f;\n" + " do {\n" + " f = something();\n" + " } while (f);\n" + " }\n" + "}"); final PsiCodeBlock body = ((PsiJavaFile)getFile()).getClasses()[0].getMethods()[0].getBody(); ControlFlow flow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, new LocalsControlFlowPolicy(body), false); IntArrayList exitPoints = new IntArrayList(); ControlFlowUtil.findExitPointsAndStatements(flow, 0, flow.getSize() -1 , exitPoints, ControlFlowUtil.DEFAULT_EXIT_STATEMENTS_CLASSES); assertEquals(1, exitPoints.size()); }
@Override public void visitClassInitializer( @NotNull PsiClassInitializer initializer) { super.visitClassInitializer(initializer); final PsiCodeBlock body = initializer.getBody(); if (!codeBlockIsEmpty(body)) { return; } registerClassInitializerError(initializer); }
@Override public void visitSwitchStatement( @NotNull PsiSwitchStatement statement) { final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final int branchCount = SwitchUtils.calculateBranchCount(statement); if (branchCount <= m_limit) { return; } registerStatementError(statement, Integer.valueOf(branchCount)); }
@Override public void visitSwitchStatement( @NotNull PsiSwitchStatement statement) { super.visitSwitchStatement(statement); final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final PsiStatement[] statements = body.getStatements(); boolean labelSeen = false; for (int i = statements.length - 1; i >= 0; i--) { final PsiStatement child = statements[i]; if (child instanceof PsiSwitchLabelStatement) { final PsiSwitchLabelStatement label = (PsiSwitchLabelStatement)child; if (label.isDefaultCase()) { if (labelSeen) { registerStatementError(label); } return; } else { labelSeen = true; } } } }
@Override public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) { final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final int branchCount = SwitchUtils.calculateBranchCount(statement); if (branchCount == 0) { return; // // do not warn when no switch branches are present at all } if (branchCount >= m_limit) { return; } registerStatementError(statement, Integer.valueOf(branchCount)); }
@Override public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) { super.visitSynchronizedStatement(statement); final PsiCodeBlock body = statement.getBody(); if (body == null) { return; } final PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { return; } registerStatementError(statement); }
@Override public void visitTryStatement(@NotNull PsiTryStatement statement) { super.visitTryStatement(statement); final PsiCodeBlock finallyBlock = statement.getTryBlock(); if (finallyBlock == null) { return; } if (finallyBlock.getStatements().length != 0) { return; } registerStatementError(statement); }
@Override public void writeMethod(PsiCodeBlock methodBody, PsiElementFactory factory, PsiField field) { if (null == methodBody) { return; } methodBody.add(factory.createStatementFromText("out.writeValue(" + field.getName() + ");", null)); }
@Override public void readMethod(PsiCodeBlock methodBody, PsiElementFactory factory, PsiField field) { if (null == methodBody) { return; } methodBody.add(factory.createStatementFromText(field.getName() + " = (" + typeNameHolder + ")in.readValue(" + typeNameHolder + ".class.getClassLoader());", null)); }