Search in sources :

Example 61 with GrClosableBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock in project android by JetBrains.

the class GradleEditorModelParserFacade method fillContext.

/**
   * Processes given PSI file and fills given context
   * by {@link GradleEditorModelParseContext#getAssignments(Variable) corresponding assignments}.
   *
   * @param context  context to fill
   * @param psiFile  psi file to parse
   */
private static void fillContext(@NotNull final GradleEditorModelParseContext context, @NotNull PsiFile psiFile) {
    psiFile.acceptChildren(new GroovyPsiElementVisitor(new GroovyRecursiveElementVisitor() {

        @Override
        public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
            Pair<String, TextRange> pair = GradleEditorValueExtractor.extractMethodName(methodCallExpression);
            GrClosableBlock[] closureArguments = methodCallExpression.getClosureArguments();
            if (pair == null || closureArguments.length > 1) {
                super.visitMethodCallExpression(methodCallExpression);
                return;
            }
            if (closureArguments.length == 0) {
                if (methodCallExpression.getArgumentList().getAllArguments().length == 0) {
                    // This is a no-args method, so, we just register it for cases like 'mavenCentral()' or 'jcenter()'.
                    context.addCachedValue(NO_ARGS_METHOD_ASSIGNMENT_VALUE, TextRange.create(pair.second.getEndOffset(), methodCallExpression.getTextRange().getEndOffset()));
                    context.registerAssignmentFromCachedData(pair.first, pair.second, methodCallExpression);
                }
                return;
            }
            context.onMethodEnter(pair.getFirst());
            try {
                super.visitClosure(closureArguments[0]);
            } finally {
                context.onMethodExit();
            }
        }

        @Override
        public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
            Pair<String, TextRange> methodName = GradleEditorValueExtractor.extractMethodName(applicationStatement);
            if (methodName == null) {
                return;
            }
            GroovyPsiElement[] allArguments = applicationStatement.getArgumentList().getAllArguments();
            if (allArguments.length == 1) {
                context.resetCaches();
                extractValueOrVariable(allArguments[0], context);
                context.registerAssignmentFromCachedData(methodName.getFirst(), methodName.getSecond(), applicationStatement.getArgumentList());
            }
        }

        @Override
        public void visitAssignmentExpression(GrAssignmentExpression expression) {
            // General idea is to try to extract variable from the given expression and, in case of success, try to extract rvalue and
            // register corresponding assignment with them.
            context.resetCaches();
            extractValueOrVariable(expression.getLValue(), context);
            Multimap<Variable, Location> vars = context.getCachedVariables();
            if (vars.size() != 1) {
                context.resetCaches();
                return;
            }
            Map.Entry<Variable, Location> entry = vars.entries().iterator().next();
            Variable lVariable = entry.getKey();
            Location lVariableLocation = entry.getValue();
            context.resetCaches();
            GrExpression rValue = expression.getRValue();
            if (rValue == null) {
                return;
            }
            extractValueOrVariable(rValue, context);
            if (context.getCachedValues().size() > 1) {
                Value value = new Value("", new Location(context.getCurrentFile(), GradleEditorModelUtil.interestedRange(rValue)));
                context.setCachedValues(Collections.singletonList(value));
            }
            context.registerAssignmentFromCachedData(lVariable, lVariableLocation, rValue);
            context.resetCaches();
        }

        @Override
        public void visitVariable(GrVariable variable) {
            TextRange nameRange = null;
            boolean lookForInitializer = false;
            ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.findSingle(GroovyLanguage.INSTANCE);
            for (PsiElement e = variable.getFirstChild(); e != null; e = e.getNextSibling()) {
                ASTNode node = e.getNode();
                if (node == null) {
                    continue;
                }
                if (!lookForInitializer) {
                    if (node.getElementType() == GroovyTokenTypes.mIDENT) {
                        nameRange = e.getTextRange();
                    } else if (node.getElementType() == GroovyTokenTypes.mASSIGN) {
                        if (nameRange == null) {
                            return;
                        }
                        lookForInitializer = true;
                    }
                    continue;
                }
                if (node.getElementType() == GroovyTokenTypes.mNLS || node.getElementType() == GroovyTokenTypes.mSEMI) {
                    break;
                }
                if (parserDefinition.getWhitespaceTokens().contains(node.getElementType())) {
                    continue;
                }
                extractValueOrVariable(e, context);
                if (context.getCachedValues().size() > 1) {
                    Value value = new Value("", new Location(context.getCurrentFile(), GradleEditorModelUtil.interestedRange(e)));
                    context.setCachedValues(Collections.singletonList(value));
                }
                if (context.registerAssignmentFromCachedData(variable.getName(), nameRange, e)) {
                    return;
                }
            }
        }
    }));
}
Also used : GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) GrVariable(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GroovyRecursiveElementVisitor(org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor) TextRange(com.intellij.openapi.util.TextRange) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) GrApplicationStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement) GrVariable(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable) ParserDefinition(com.intellij.lang.ParserDefinition) GrMethodCallExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression) GrAssignmentExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression) GroovyPsiElementVisitor(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor) ASTNode(com.intellij.lang.ASTNode) Map(java.util.Map) PsiElement(com.intellij.psi.PsiElement) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)

Example 62 with GrClosableBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock in project android by JetBrains.

the class LintIdeGradleDetector method visitBuildScript.

@Override
public void visitBuildScript(@NonNull final Context context, Map<String, Object> sharedData) {
    ApplicationManager.getApplication().runReadAction(new Runnable() {

        @Override
        public void run() {
            final PsiFile psiFile = LintIdeUtils.getPsiFile(context);
            if (!(psiFile instanceof GroovyFile)) {
                return;
            }
            GroovyFile groovyFile = (GroovyFile) psiFile;
            groovyFile.accept(new GroovyRecursiveElementVisitor() {

                @Override
                public void visitClosure(GrClosableBlock closure) {
                    String parentName = getClosureName(closure);
                    String parentParentName = null;
                    if (parentName != null) {
                        GrClosableBlock block = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class, true);
                        if (block != null) {
                            parentParentName = getClosureName(block);
                        }
                    }
                    if (parentName != null && isInterestingBlock(parentName, parentParentName)) {
                        for (PsiElement element : closure.getChildren()) {
                            if (element instanceof GrApplicationStatement) {
                                GrApplicationStatement call = (GrApplicationStatement) element;
                                GrExpression propertyExpression = call.getInvokedExpression();
                                GrCommandArgumentList argumentList = call.getArgumentList();
                                if (propertyExpression instanceof GrReferenceExpression) {
                                    GrReferenceExpression propertyRef = (GrReferenceExpression) propertyExpression;
                                    String property = propertyRef.getReferenceName();
                                    //noinspection ConstantConditions
                                    if (property != null && isInterestingProperty(property, parentName, parentParentName) && argumentList != null) {
                                        String value = argumentList.getText();
                                        checkDslPropertyAssignment(context, property, value, parentName, parentParentName, argumentList, call);
                                    }
                                }
                            } else if (element instanceof GrAssignmentExpression) {
                                GrAssignmentExpression assignment = (GrAssignmentExpression) element;
                                GrExpression lValue = assignment.getLValue();
                                if (lValue instanceof GrReferenceExpression) {
                                    GrReferenceExpression propertyRef = (GrReferenceExpression) lValue;
                                    String property = propertyRef.getReferenceName();
                                    if (property != null && isInterestingProperty(property, parentName, parentParentName)) {
                                        GrExpression rValue = assignment.getRValue();
                                        if (rValue != null) {
                                            String value = rValue.getText();
                                            checkDslPropertyAssignment(context, property, value, parentName, parentParentName, rValue, assignment);
                                            // handle it here.
                                            if (property.equals(ATTR_MIN_SDK_VERSION) || property.equals(ATTR_TARGET_SDK_VERSION)) {
                                                int lValueEnd = lValue.getTextRange().getEndOffset();
                                                int rValueStart = rValue.getTextRange().getStartOffset();
                                                assert lValueEnd <= rValueStart;
                                                DefaultPosition startPosition = new DefaultPosition(-1, -1, lValueEnd);
                                                DefaultPosition endPosition = new DefaultPosition(-1, -1, rValueStart);
                                                Location location = Location.create(context.file, startPosition, endPosition);
                                                String message = String.format("Do not use assignment with the %1$s property (remove the '=')", property);
                                                context.report(GradleDetector.IDE_SUPPORT, location, message, null);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    super.visitClosure(closure);
                }

                @Override
                public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
                    GrClosableBlock block = PsiTreeUtil.getParentOfType(applicationStatement, GrClosableBlock.class, true);
                    String parentName = block != null ? getClosureName(block) : null;
                    String statementName = applicationStatement.getInvokedExpression().getText();
                    if (isInterestingStatement(statementName, parentName)) {
                        GrCommandArgumentList argumentList = applicationStatement.getArgumentList();
                        Map<String, String> namedArguments = Maps.newHashMap();
                        List<String> unnamedArguments = Lists.newArrayList();
                        for (GroovyPsiElement groovyPsiElement : argumentList.getAllArguments()) {
                            if (groovyPsiElement instanceof GrNamedArgument) {
                                GrNamedArgument namedArgument = (GrNamedArgument) groovyPsiElement;
                                GrExpression expression = namedArgument.getExpression();
                                if (expression == null || !(expression instanceof GrLiteral)) {
                                    continue;
                                }
                                Object value = ((GrLiteral) expression).getValue();
                                if (value == null) {
                                    continue;
                                }
                                namedArguments.put(namedArgument.getLabelName(), value.toString());
                            } else if (groovyPsiElement instanceof GrExpression) {
                                unnamedArguments.add(groovyPsiElement.getText());
                            }
                        }
                        checkMethodCall(context, statementName, parentName, namedArguments, unnamedArguments, applicationStatement);
                    }
                    super.visitApplicationStatement(applicationStatement);
                }
            });
        }
    });
}
Also used : GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) GrNamedArgument(org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GroovyRecursiveElementVisitor(org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor) PsiFile(com.intellij.psi.PsiFile) GrLiteral(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral) GroovyFile(org.jetbrains.plugins.groovy.lang.psi.GroovyFile) PsiElement(com.intellij.psi.PsiElement) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)

Example 63 with GrClosableBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock in project android by JetBrains.

the class GradleDslElement method deleteIfEmpty.

protected static void deleteIfEmpty(@Nullable PsiElement element) {
    if (element == null || !element.isValid()) {
        return;
    }
    PsiElement parent = element.getParent();
    if (element instanceof GrAssignmentExpression) {
        if (((GrAssignmentExpression) element).getRValue() == null) {
            element.delete();
        }
    } else if (element instanceof GrApplicationStatement) {
        if (((GrApplicationStatement) element).getArgumentList() == null) {
            element.delete();
        }
    } else if (element instanceof GrClosableBlock) {
        final Boolean[] isEmpty = new Boolean[] { true };
        ((GrClosableBlock) element).acceptChildren(new GroovyElementVisitor() {

            @Override
            public void visitElement(GroovyPsiElement child) {
                if (child instanceof GrParameterList) {
                    if (((GrParameterList) child).getParameters().length == 0) {
                        // Ignore the empty parameter list.
                        return;
                    }
                }
                isEmpty[0] = false;
            }
        });
        if (isEmpty[0]) {
            element.delete();
        }
    } else if (element instanceof GrMethodCallExpression) {
        GrMethodCallExpression call = ((GrMethodCallExpression) element);
        GrArgumentList argumentList;
        try {
            argumentList = call.getArgumentList();
        } catch (AssertionError e) {
            // We will get this exception if the argument list is already deleted.
            argumentList = null;
        }
        GrClosableBlock[] closureArguments = call.getClosureArguments();
        if ((argumentList == null || argumentList.getAllArguments().length == 0) && closureArguments.length == 0) {
            element.delete();
        }
    } else if (element instanceof GrCommandArgumentList) {
        GrCommandArgumentList commandArgumentList = (GrCommandArgumentList) element;
        if (commandArgumentList.getAllArguments().length == 0) {
            commandArgumentList.delete();
        }
    } else if (element instanceof GrListOrMap) {
        GrListOrMap listOrMap = (GrListOrMap) element;
        if ((listOrMap.isMap() && listOrMap.getNamedArguments().length == 0) || (!listOrMap.isMap() && listOrMap.getInitializers().length == 0)) {
            listOrMap.delete();
        }
    }
    if (!element.isValid()) {
        // If this element is deleted, also delete the parent if it is empty.
        deleteIfEmpty(parent);
    }
}
Also used : GrParameterList(org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList) GrCommandArgumentList(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GrListOrMap(org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap) GrApplicationStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement) GroovyElementVisitor(org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor) GrAssignmentExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression) GrMethodCallExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression) GrArgumentList(org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList) PsiElement(com.intellij.psi.PsiElement) GroovyPsiElement(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)

Example 64 with GrClosableBlock

use of org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock in project android by JetBrains.

the class GradleDslLiteral method getValue.

@Override
@Nullable
public Object getValue() {
    if (myUnsavedValue != null) {
        return myUnsavedValue;
    }
    if (myExpression == null) {
        return null;
    }
    Object value = ((GrLiteral) myExpression).getValue();
    if (value != null) {
        return value;
    }
    if (myExpression instanceof GrString) {
        // String literal with variables. ex: compileSdkVersion = "$ANDROID-${VERSION}"
        String literalText = myExpression.getText();
        if (isQuotedString(literalText)) {
            literalText = unquoteString(literalText);
        }
        List<GradleResolvedVariable> resolvedVariables = Lists.newArrayList();
        GrStringInjection[] injections = ((GrString) myExpression).getInjections();
        for (GrStringInjection injection : injections) {
            String variableName = null;
            GrClosableBlock closableBlock = injection.getClosableBlock();
            if (closableBlock != null) {
                String blockText = closableBlock.getText();
                variableName = blockText.substring(1, blockText.length() - 1);
            } else {
                GrExpression expression = injection.getExpression();
                if (expression != null) {
                    variableName = expression.getText();
                }
            }
            if (!isEmpty(variableName)) {
                GradleDslExpression resolvedExpression = resolveReference(variableName, GradleDslExpression.class);
                if (resolvedExpression != null) {
                    Object resolvedValue = resolvedExpression.getValue();
                    if (resolvedValue != null) {
                        resolvedVariables.add(new GradleResolvedVariable(variableName, resolvedValue, resolvedExpression));
                        literalText = literalText.replace(injection.getText(), resolvedValue.toString());
                    }
                }
            }
        }
        setResolvedVariables(resolvedVariables);
        return literalText;
    }
    return null;
}
Also used : GrString(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) GrString(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString) GradleResolvedVariable(com.android.tools.idea.gradle.dsl.parser.GradleResolvedVariable) GrStringInjection(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection) GrLiteral(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral) Nullable(org.jetbrains.annotations.Nullable)

Example 65 with GrClosableBlock

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

the class CustomWorldContributor method getClosureArg.

@Nullable
private static GrClosableBlock getClosureArg(@NotNull GrMethodCall methodCall) {
    final GrClosableBlock[] closures = methodCall.getClosureArguments();
    if (closures.length == 1)
        return closures[0];
    if (closures.length > 1)
        return null;
    final GrExpression[] args = methodCall.getExpressionArguments();
    if (args.length == 0)
        return null;
    final GrExpression last = DefaultGroovyMethods.last(args);
    if (last instanceof GrClosableBlock) {
        return (GrClosableBlock) last;
    }
    return null;
}
Also used : GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

GrClosableBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock)116 PsiElement (com.intellij.psi.PsiElement)32 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)31 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)26 GrReferenceExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression)26 Nullable (org.jetbrains.annotations.Nullable)23 GrParameter (org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter)23 GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)18 GroovyPsiElementFactory (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory)17 GrArgumentList (org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList)15 GrMethodCallExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression)15 GrNamedArgument (org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument)14 GrMethodCall (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall)13 GrField (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField)12 ArrayList (java.util.ArrayList)11 NotNull (org.jetbrains.annotations.NotNull)10 GroovyRecursiveElementVisitor (org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor)10 GroovyResolveResult (org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult)10 GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)10 GroovyFile (org.jetbrains.plugins.groovy.lang.psi.GroovyFile)9