Search in sources :

Example 46 with GrOpenBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock in project intellij-community by JetBrains.

the class GrFinalVariableAccessInspection method appendInitializationFromChainedConstructors.

private static void appendInitializationFromChainedConstructors(@NotNull GrMethod constructor, @NotNull List<GrField> fields, @NotNull Set<GrVariable> initializedFields) {
    final List<GrMethod> chained = getChainedConstructors(constructor);
    chained.remove(0);
    for (GrMethod method : chained) {
        final GrOpenBlock block = method.getBlock();
        if (block == null)
            continue;
        final Instruction[] flow = buildFlowForField(block);
        for (GrField field : fields) {
            if (!field.hasModifierProperty(PsiModifier.STATIC) && !initializedFields.contains(field) && VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, flow)) {
                initializedFields.add(field);
            }
        }
    }
}
Also used : GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) 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 47 with GrOpenBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock 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 48 with GrOpenBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock 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 49 with GrOpenBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock in project intellij-community by JetBrains.

the class GrChangeSignatureUsageProcessor method processConstructor.

private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) {
    final PsiClass containingClass = constructor.getContainingClass();
    final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
    final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, containingClass, PsiSubstitutor.EMPTY);
    GrOpenBlock block = constructor.getBlock();
    GrConstructorInvocation invocation = GroovyPsiElementFactory.getInstance(constructor.getProject()).createConstructorInvocation("super()");
    invocation = (GrConstructorInvocation) block.addStatementBefore(invocation, getFirstStatement(block));
    processMethodUsage(invocation.getInvokedExpression(), changeInfo, changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(), changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.<PsiElement>empty_array(), substitutor);
}
Also used : GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)

Example 50 with GrOpenBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock in project intellij-community by JetBrains.

the class GrChageSignatureUsageSearcher method detectLocalsCollisionsInMethod.

/* todo
  private void findUsagesInCallers(final ArrayList<UsageInfo> usages) {
    if (myChangeInfo instanceof JavaChangeInfoImpl) {
      JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo;

      for (PsiMethod caller : changeInfo.propagateParametersMethods) {
        usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller)));
      }
      for (PsiMethod caller : changeInfo.propagateExceptionsMethods) {
        usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true));
      }
      Set<PsiMethod> merged = new HashSet<PsiMethod>();
      merged.addAll(changeInfo.propagateParametersMethods);
      merged.addAll(changeInfo.propagateExceptionsMethods);
      for (final PsiMethod method : merged) {
        findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method),
                                          changeInfo.propagateExceptionsMethods.contains(method), false);
      }
    }
  }
  */
private void detectLocalsCollisionsInMethod(final GrMethod method, final ArrayList<UsageInfo> result, boolean isOriginal) {
    if (!GroovyLanguage.INSTANCE.equals(method.getLanguage()))
        return;
    final PsiParameter[] parameters = method.getParameterList().getParameters();
    final Set<PsiParameter> deletedOrRenamedParameters = new HashSet<>();
    if (isOriginal) {
        ContainerUtil.addAll(deletedOrRenamedParameters, parameters);
        for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
            if (parameterInfo.getOldIndex() >= 0) {
                final PsiParameter parameter = parameters[parameterInfo.getOldIndex()];
                if (parameterInfo.getName().equals(parameter.getName())) {
                    deletedOrRenamedParameters.remove(parameter);
                }
            }
        }
    }
    final GrOpenBlock block = method.getBlock();
    for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
        final int oldParameterIndex = parameterInfo.getOldIndex();
        final String newName = parameterInfo.getName();
        if (oldParameterIndex >= 0) {
            if (isOriginal) {
                //Name changes take place only in primary method
                final PsiParameter parameter = parameters[oldParameterIndex];
                if (!newName.equals(parameter.getName())) {
                    final GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor collidingVariableVisitor = new GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {

                        @Override
                        public void visitCollidingVariable(final PsiVariable collidingVariable) {
                            if (!deletedOrRenamedParameters.contains(collidingVariable)) {
                                result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method));
                            }
                        }
                    };
                    if (block != null) {
                        GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, block, collidingVariableVisitor);
                    }
                }
            }
        } else {
            final GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor variableVisitor = new GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {

                @Override
                public void visitCollidingVariable(PsiVariable collidingVariable) {
                    if (!deletedOrRenamedParameters.contains(collidingVariable)) {
                        result.add(new NewParameterCollidesWithLocalUsageInfo(collidingVariable, collidingVariable, method));
                    }
                }
            };
            if (block != null) {
                GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, block, variableVisitor);
            }
        }
    }
}
Also used : GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) HashSet(com.intellij.util.containers.HashSet)

Aggregations

GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)68 GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)24 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)21 PsiElement (com.intellij.psi.PsiElement)13 GrClosableBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock)10 GrReferenceExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression)10 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)9 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)9 GroovyPsiElementFactory (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory)8 GrParameter (org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter)8 GrReturnStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement)7 Nullable (org.jetbrains.annotations.Nullable)6 NotNull (org.jetbrains.annotations.NotNull)5 GrBlockStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement)5 Instruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction)5 ReadWriteVariableInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)5 TextRange (com.intellij.openapi.util.TextRange)4 GroovyRecursiveElementVisitor (org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor)4 GrCodeBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock)4 UsageInfo (com.intellij.usageView.UsageInfo)3