Search in sources :

Example 71 with GrMethod

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod in project intellij-community by JetBrains.

the class GrFinalVariableAccessInspection method isFieldInitialized.

private static boolean isFieldInitialized(@NotNull GrField field) {
    if (field instanceof GrEnumConstant)
        return true;
    if (field.getInitializerGroovy() != null)
        return true;
    if (isImmutableField(field))
        return true;
    final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
    final GrTypeDefinition aClass = ((GrTypeDefinition) field.getContainingClass());
    if (aClass == null)
        return true;
    GrClassInitializer[] initializers = aClass.getInitializers();
    for (GrClassInitializer initializer : initializers) {
        if (initializer.isStatic() != isStatic)
            continue;
        final GrOpenBlock block = initializer.getBlock();
        final Instruction[] initializerFlow = buildFlowForField(block);
        if (VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, initializerFlow)) {
            return true;
        }
    }
    if (isStatic)
        return false;
    final GrMethod[] constructors = aClass.getCodeConstructors();
    if (constructors.length == 0)
        return false;
    Set<GrMethod> initializedConstructors = ContainerUtil.newHashSet();
    Set<GrMethod> notInitializedConstructors = ContainerUtil.newHashSet();
    NEXT_CONSTR: for (GrMethod constructor : constructors) {
        if (constructor.getBlock() == null)
            return false;
        final List<GrMethod> chained = getChainedConstructors(constructor);
        NEXT_CHAINED: for (GrMethod method : chained) {
            if (initializedConstructors.contains(method)) {
                continue NEXT_CONSTR;
            } else if (notInitializedConstructors.contains(method)) {
                continue NEXT_CHAINED;
            }
            final GrOpenBlock block = method.getBlock();
            assert block != null;
            final boolean initialized = VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, buildFlowForField(block));
            if (initialized) {
                initializedConstructors.add(method);
                continue NEXT_CONSTR;
            } else {
                notInitializedConstructors.add(method);
            }
        }
        return false;
    }
    return true;
}
Also used : GrTypeDefinition(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition) GrEnumConstant(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrModifierList(org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)

Example 72 with GrMethod

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod in project intellij-community by JetBrains.

the class GrFinalVariableAccessInspection method buildVisitor.

@NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
    return new BaseInspectionVisitor() {

        @Override
        public void visitMethod(@NotNull GrMethod method) {
            super.visitMethod(method);
            final GrOpenBlock block = method.getBlock();
            if (block != null) {
                processLocalVars(block);
            }
            if (method.isConstructor()) {
                processFieldsInConstructors(method);
            }
        }

        @Override
        public void visitFile(@NotNull GroovyFileBase file) {
            super.visitFile(file);
            if (file instanceof GroovyFile && file.isScript()) {
                processLocalVars(file);
            }
        }

        @Override
        public void visitField(@NotNull GrField field) {
            super.visitField(field);
            final GrExpression initializer = field.getInitializerGroovy();
            if (initializer != null) {
                processLocalVars(initializer);
            }
            if (field.hasModifierProperty(PsiModifier.FINAL)) {
                if (!isFieldInitialized(field)) {
                    registerError(field.getNameIdentifierGroovy(), GroovyBundle.message("variable.0.might.not.have.been.initialized", field.getName()), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
                }
            }
        }

        @Override
        public void visitReferenceExpression(@NotNull GrReferenceExpression ref) {
            super.visitReferenceExpression(ref);
            final PsiElement resolved = ref.resolve();
            if (resolved instanceof GrField && ((GrField) resolved).hasModifierProperty(PsiModifier.FINAL)) {
                final GrField field = (GrField) resolved;
                final PsiClass containingClass = field.getContainingClass();
                if (PsiUtil.isLValue(ref)) {
                    if (containingClass == null || !PsiTreeUtil.isAncestor(containingClass, ref, true)) {
                        registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.field.0", field.getName()), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
                    }
                } else if (PsiUtil.isUsedInIncOrDec(ref)) {
                    if (containingClass == null || !isInsideConstructorOrInitializer(containingClass, ref, field.hasModifierProperty(PsiModifier.STATIC))) {
                        registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.field.0", field.getName()), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
                    }
                }
            } else if (resolved instanceof GrParameter && ((GrParameter) resolved).getDeclarationScope() instanceof GrMethod && ((GrParameter) resolved).hasModifierProperty(PsiModifier.FINAL) && PsiUtil.isUsedInIncOrDec(ref)) {
                registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.parameter.0", ((GrParameter) resolved).getName()), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
            }
        }

        @Override
        public void visitClassInitializer(@NotNull GrClassInitializer initializer) {
            super.visitClassInitializer(initializer);
            processLocalVars(initializer.getBlock());
            processFieldsInClassInitializer(initializer);
        }

        private void processFieldsInConstructors(@NotNull GrMethod constructor) {
            final GrOpenBlock block = constructor.getBlock();
            if (block == null)
                return;
            final GrTypeDefinition clazz = (GrTypeDefinition) constructor.getContainingClass();
            if (clazz == null)
                return;
            final GrClassInitializer[] initializers = clazz.getInitializers();
            final List<GrField> fields = getFinalFields(clazz);
            Set<GrVariable> initializedFields = ContainerUtil.newHashSet();
            appendFieldInitializedInDeclaration(false, fields, initializedFields);
            appendFieldsInitializedInClassInitializer(initializers, null, false, fields, initializedFields);
            appendInitializationFromChainedConstructors(constructor, fields, initializedFields);
            final Instruction[] flow = buildFlowForField(block);
            final Map<String, GrVariable> variables = buildVarMap(fields, false);
            highlightInvalidWriteAccess(flow, variables, initializedFields);
        }

        private void processFieldsInClassInitializer(@NotNull GrClassInitializer initializer) {
            final GrTypeDefinition clazz = (GrTypeDefinition) initializer.getContainingClass();
            if (clazz == null)
                return;
            final boolean isStatic = initializer.isStatic();
            final GrClassInitializer[] initializers = clazz.getInitializers();
            final List<GrField> fields = getFinalFields(clazz);
            Set<GrVariable> initializedFields = ContainerUtil.newHashSet();
            appendFieldInitializedInDeclaration(isStatic, fields, initializedFields);
            appendFieldsInitializedInClassInitializer(initializers, initializer, isStatic, fields, initializedFields);
            final Instruction[] flow = buildFlowForField(initializer.getBlock());
            final Map<String, GrVariable> variables = buildVarMap(fields, isStatic);
            highlightInvalidWriteAccess(flow, variables, initializedFields);
        }

        private void processLocalVars(@NotNull GroovyPsiElement scope) {
            final MultiMap<PsiElement, GrVariable> scopes = collectVariables(scope);
            for (final Map.Entry<PsiElement, Collection<GrVariable>> entry : scopes.entrySet()) {
                final PsiElement scopeToProcess = entry.getKey();
                final Set<GrVariable> forInParameters = ContainerUtil.newHashSet();
                final Map<String, GrVariable> variables = ContainerUtil.newHashMap();
                for (final GrVariable var : entry.getValue()) {
                    variables.put(var.getName(), var);
                    if (var instanceof GrParameter && ((GrParameter) var).getDeclarationScope() instanceof GrForStatement) {
                        forInParameters.add(var);
                    }
                }
                final Instruction[] flow = getFlow(scopeToProcess);
                highlightInvalidWriteAccess(flow, variables, forInParameters);
            }
        }

        private void highlightInvalidWriteAccess(@NotNull Instruction[] flow, @NotNull Map<String, GrVariable> variables, @NotNull Set<GrVariable> initializedVariables) {
            final List<ReadWriteVariableInstruction> result = InvalidWriteAccessSearcher.findInvalidWriteAccess(flow, variables, initializedVariables);
            if (result == null)
                return;
            for (final ReadWriteVariableInstruction instruction : result) {
                if (variables.containsKey(instruction.getVariableName())) {
                    registerError(instruction.getElement(), GroovyBundle.message("cannot.assign.a.value.to.final.field.0", instruction.getVariableName()), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
                }
            }
        }
    };
}
Also used : BaseInspectionVisitor(org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor) GrParameter(org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction) NotNull(org.jetbrains.annotations.NotNull) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) GrReferenceExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression) GrTypeDefinition(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) MultiMap(com.intellij.util.containers.MultiMap) NotNull(org.jetbrains.annotations.NotNull)

Example 73 with GrMethod

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod in project intellij-community by JetBrains.

the class GroovyVariableCanBeFinalInspection method process.

private static void process(@NotNull GrControlFlowOwner owner, @NotNull GrVariable variable, @NotNull ProblemsHolder problemsHolder) {
    if (variable.hasModifierProperty(PsiModifier.FINAL))
        return;
    if (!checkVariableDeclaredInsideScope(owner, variable))
        return;
    if (checkVariableAssignedInsideClosureOrAnonymous(owner, variable))
        return;
    final boolean isParameterTooltip = variable instanceof GrParameter && (((GrParameter) variable).getDeclarationScope() instanceof GrMethod || ((GrParameter) variable).getDeclarationScope() instanceof GrClosableBlock);
    final String tooltip = GroovyInspectionBundle.message(isParameterTooltip ? "parameter.can.be.final.tooltip" : "variable.can.be.final.tooltip", variable.getName());
    problemsHolder.registerProblem(variable.getNameIdentifierGroovy(), tooltip, new GrModifierFix(variable, PsiModifier.FINAL, true, ID_MODIFIER_LIST_PROVIDER));
}
Also used : GrModifierFix(org.jetbrains.plugins.groovy.codeInspection.bugs.GrModifierFix) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GrParameter(org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter)

Example 74 with GrMethod

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod in project intellij-community by JetBrains.

the class GrMethodMayBeStaticInspection method buildVisitor.

@NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
    return new BaseInspectionVisitor() {

        @Override
        public void visitMethod(@NotNull GrMethod method) {
            if (checkMethod(method)) {
                final GrModifierFix modifierFix = new GrModifierFix(method, PsiModifier.STATIC, false, true, descriptor -> {
                    final PsiElement element = descriptor.getPsiElement();
                    final PsiElement parent = element.getParent();
                    assert parent instanceof GrMethod : "element: " + element + ", parent:" + parent;
                    return ((GrMethod) parent).getModifierList();
                });
                registerError(method.getNameIdentifierGroovy(), message("method.may.be.static"), new LocalQuickFix[] { modifierFix }, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
            }
        }
    };
}
Also used : BaseInspectionVisitor(org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor) GrModifierFix(org.jetbrains.plugins.groovy.codeInspection.bugs.GrModifierFix) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) NotNull(org.jetbrains.annotations.NotNull) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 75 with GrMethod

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod in project intellij-community by JetBrains.

the class GroovyPostHighlightingPass method doCollectInformation.

@Override
public void doCollectInformation(@NotNull final ProgressIndicator progress) {
    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
    VirtualFile virtualFile = myFile.getViewProvider().getVirtualFile();
    if (!fileIndex.isInContent(virtualFile)) {
        return;
    }
    final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getCurrentProfile();
    final HighlightDisplayKey unusedDefKey = HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME);
    final boolean deadCodeEnabled = profile.isToolEnabled(unusedDefKey, myFile);
    final UnusedDeclarationInspectionBase deadCodeInspection = (UnusedDeclarationInspectionBase) profile.getUnwrappedTool(UnusedDeclarationInspectionBase.SHORT_NAME, myFile);
    final GlobalUsageHelper usageHelper = new GlobalUsageHelper() {

        @Override
        public boolean isCurrentFileAlreadyChecked() {
            return false;
        }

        @Override
        public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
            return false;
        }

        @Override
        public boolean shouldCheckUsages(@NotNull PsiMember member) {
            return deadCodeInspection == null || !deadCodeInspection.isEntryPoint(member);
        }
    };
    final List<HighlightInfo> unusedDeclarations = new ArrayList<>();
    final Map<GrParameter, Boolean> usedParams = new HashMap<>();
    myFile.accept(new PsiRecursiveElementWalkingVisitor() {

        @Override
        public void visitElement(PsiElement element) {
            if (element instanceof GrReferenceExpression && !((GrReferenceElement) element).isQualified()) {
                GroovyResolveResult[] results = ((GrReferenceExpression) element).multiResolve(false);
                if (results.length == 0) {
                    results = ((GrReferenceExpression) element).multiResolve(true);
                }
                for (GroovyResolveResult result : results) {
                    PsiElement resolved = result.getElement();
                    if (resolved instanceof GrParameter && resolved.getContainingFile() == myFile) {
                        usedParams.put((GrParameter) resolved, Boolean.TRUE);
                    }
                }
            }
            if (deadCodeEnabled && element instanceof GrNamedElement && element instanceof PsiModifierListOwner && !UnusedSymbolUtil.isImplicitUsage(element.getProject(), (PsiModifierListOwner) element, progress) && !GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) {
                PsiElement nameId = ((GrNamedElement) element).getNameIdentifierGroovy();
                if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
                    String name = ((GrNamedElement) element).getName();
                    if (element instanceof GrTypeDefinition && !UnusedSymbolUtil.isClassUsed(myProject, element.getContainingFile(), (GrTypeDefinition) element, progress, usageHelper)) {
                        HighlightInfo highlightInfo = UnusedSymbolUtil.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
                        QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(element), unusedDefKey);
                        ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
                    } else if (element instanceof GrMethod) {
                        GrMethod method = (GrMethod) element;
                        if (!UnusedSymbolUtil.isMethodReferenced(method.getProject(), method.getContainingFile(), method, progress, usageHelper)) {
                            String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused";
                            HighlightInfo highlightInfo = UnusedSymbolUtil.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL);
                            QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), unusedDefKey);
                            ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
                        }
                    } else if (element instanceof GrField && isFieldUnused((GrField) element, progress, usageHelper)) {
                        HighlightInfo highlightInfo = UnusedSymbolUtil.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
                        QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(element), unusedDefKey);
                        ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
                    } else if (element instanceof GrParameter) {
                        if (!usedParams.containsKey(element)) {
                            usedParams.put((GrParameter) element, Boolean.FALSE);
                        }
                    }
                }
            }
            super.visitElement(element);
        }
    });
    final Set<GrImportStatement> unusedImports = new HashSet<>(PsiUtil.getValidImportStatements(myFile));
    unusedImports.removeAll(GroovyImportUtil.findUsedImports(myFile));
    myUnusedImports = unusedImports;
    if (deadCodeEnabled) {
        for (GrParameter parameter : usedParams.keySet()) {
            if (usedParams.get(parameter))
                continue;
            PsiElement scope = parameter.getDeclarationScope();
            if (scope instanceof GrMethod) {
                GrMethod method = (GrMethod) scope;
                if (methodMayHaveUnusedParameters(method)) {
                    PsiElement identifier = parameter.getNameIdentifierGroovy();
                    HighlightInfo highlightInfo = UnusedSymbolUtil.createUnusedSymbolInfo(identifier, "Parameter " + parameter.getName() + " is unused", HighlightInfoType.UNUSED_SYMBOL);
                    QuickFixAction.registerQuickFixAction(highlightInfo, GroovyQuickFixFactory.getInstance().createRemoveUnusedGrParameterFix(parameter), unusedDefKey);
                    ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
                }
            } else if (scope instanceof GrClosableBlock) {
            //todo Max Medvedev
            }
        }
    }
    myUnusedDeclarations = unusedDeclarations;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) GrField(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField) HighlightDisplayKey(com.intellij.codeInsight.daemon.HighlightDisplayKey) GrParameter(org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter) GrImportStatement(org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement) NotNull(org.jetbrains.annotations.NotNull) GrNamedElement(org.jetbrains.plugins.groovy.lang.psi.GrNamedElement) InspectionProfile(com.intellij.codeInspection.InspectionProfile) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GrReferenceExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression) UnusedDeclarationInspectionBase(com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase) GroovyResolveResult(org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult) GrTypeDefinition(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition) ProjectFileIndex(com.intellij.openapi.roots.ProjectFileIndex)

Aggregations

GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)134 GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)24 PsiElement (com.intellij.psi.PsiElement)22 NotNull (org.jetbrains.annotations.NotNull)21 GroovyPsiElementFactory (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory)19 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)18 GrParameter (org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter)17 GrField (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField)16 GrClosableBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock)16 ArrayList (java.util.ArrayList)15 GrTypeDefinition (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition)15 Nullable (org.jetbrains.annotations.Nullable)12 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)12 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)12 GrReferenceExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression)12 IncorrectOperationException (com.intellij.util.IncorrectOperationException)10 GrCodeBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock)10 Project (com.intellij.openapi.project.Project)9 GrVariable (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable)8 GrReturnStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement)8