Search in sources :

Example 26 with PsiElementVisitor

use of com.intellij.psi.PsiElementVisitor in project phpinspectionsea by kalessil.

the class UselessReturnInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpReturn(@NotNull PhpReturn expression) {
            final PhpExpression returnValue = ExpressionSemanticUtil.getReturnValue(expression);
            if (returnValue instanceof AssignmentExpression) {
                final AssignmentExpression assignment = (AssignmentExpression) returnValue;
                final PsiElement assignmentVariable = assignment.getVariable();
                final PsiElement assignmentValue = assignment.getValue();
                if (assignmentValue != null && assignmentVariable instanceof Variable) {
                    final Function scope = ExpressionSemanticUtil.getScope(expression);
                    if (scope != null) {
                        final Variable variable = (Variable) assignmentVariable;
                        final boolean isTarget = !this.isArgumentReference(variable, scope) && !this.isBoundReference(variable, scope) && !this.isStaticVariable(variable, scope) && !this.isUsedInFinally(variable, scope);
                        if (isTarget) {
                            final String replacement = String.format("return %s;", assignmentValue.getText());
                            holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(messageConfusing), new SimplifyFix(replacement));
                        }
                    }
                }
            }
        }

        @Override
        public void visitPhpMethod(@NotNull Method method) {
            if (!method.isAbstract()) {
                this.inspectForSenselessReturn(method);
            }
        }

        @Override
        public void visitPhpFunction(@NotNull Function function) {
            this.inspectForSenselessReturn(function);
        }

        private void inspectForSenselessReturn(@NotNull Function callable) {
            final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(callable);
            final PsiElement lastStatement = body == null ? null : ExpressionSemanticUtil.getLastStatement(body);
            if (lastStatement instanceof PhpReturn) {
                final PhpExpression returnValue = ExpressionSemanticUtil.getReturnValue((PhpReturn) lastStatement);
                if (returnValue == null) {
                    holder.registerProblem(lastStatement, MessagesPresentationUtil.prefixWithEa(messageSenseless), ProblemHighlightType.LIKE_UNUSED_SYMBOL);
                }
            }
        }

        private boolean isArgumentReference(@NotNull Variable variable, @NotNull Function function) {
            boolean result = false;
            final String variableName = variable.getName();
            for (final Parameter parameter : function.getParameters()) {
                if (parameter.getName().equals(variableName) && parameter.isPassByRef()) {
                    result = true;
                    break;
                }
            }
            return result;
        }

        private boolean isBoundReference(@NotNull Variable variable, @NotNull Function function) {
            boolean result = false;
            final String variableName = variable.getName();
            if (!variableName.isEmpty() && !(result = this.isReferenceBoundTo(variableName, function))) {
                final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(function);
                if (body != null) {
                    result = PsiTreeUtil.findChildrenOfType(body, Function.class).stream().anyMatch(l -> this.isReferenceBoundTo(variableName, l));
                }
            }
            return result;
        }

        private boolean isReferenceBoundTo(@NotNull String variableName, @NotNull Function function) {
            boolean result = false;
            if (OpenapiTypesUtil.isLambda(function)) {
                final List<Variable> used = ExpressionSemanticUtil.getUseListVariables(function);
                if (used != null) {
                    final Optional<Variable> match = used.stream().filter(v -> v.getName().equals(variableName)).findFirst();
                    if (match.isPresent()) {
                        final PsiElement previous = match.get().getPrevSibling();
                        final PsiElement candidate = previous instanceof PsiWhiteSpace ? previous.getPrevSibling() : previous;
                        result = OpenapiTypesUtil.is(candidate, PhpTokenTypes.opBIT_AND);
                    }
                    used.clear();
                }
            }
            return result;
        }

        private boolean isUsedInFinally(@NotNull Variable variable, @NotNull Function function) {
            boolean result = false;
            final Try tryScope = PsiTreeUtil.getParentOfType(variable, Try.class, false, Function.class);
            if (tryScope != null) {
                final Finally finallyScope = tryScope.getFinallyBlock();
                final GroupStatement body = finallyScope == null ? null : ExpressionSemanticUtil.getGroupStatement(finallyScope);
                if (body != null) {
                    final String variableName = variable.getName();
                    result = PsiTreeUtil.findChildrenOfType(body, Variable.class).stream().anyMatch(v -> variableName.equals(v.getName()));
                }
            }
            return result;
        }

        private boolean isStaticVariable(@NotNull Variable variable, @NotNull Function function) {
            boolean result = false;
            final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(function);
            if (body != null) {
                final String variableName = variable.getName();
                for (final PhpStaticStatement candidate : PsiTreeUtil.findChildrenOfType(body, PhpStaticStatement.class)) {
                    result = candidate.getDeclarations().stream().anyMatch(declaration -> {
                        final PhpPsiElement declared = declaration.getVariable();
                        return declared instanceof Variable && variableName.equals(declared.getName());
                    });
                    if (result) {
                        break;
                    }
                }
            }
            return result;
        }
    };
}
Also used : PhpPsiElementFactory(com.jetbrains.php.lang.psi.PhpPsiElementFactory) BasePhpInspection(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection) ExpressionSemanticUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.ExpressionSemanticUtil) com.jetbrains.php.lang.psi.elements(com.jetbrains.php.lang.psi.elements) PhpTokenTypes(com.jetbrains.php.lang.lexer.PhpTokenTypes) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) OpenapiTypesUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiTypesUtil) List(java.util.List) ProblemDescriptor(com.intellij.codeInspection.ProblemDescriptor) MessagesPresentationUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil) PsiElement(com.intellij.psi.PsiElement) PsiWhiteSpace(com.intellij.psi.PsiWhiteSpace) Project(com.intellij.openapi.project.Project) Optional(java.util.Optional) ProblemHighlightType(com.intellij.codeInspection.ProblemHighlightType) NotNull(org.jetbrains.annotations.NotNull) LocalQuickFix(com.intellij.codeInspection.LocalQuickFix) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) NotNull(org.jetbrains.annotations.NotNull) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PsiElement(com.intellij.psi.PsiElement) PsiWhiteSpace(com.intellij.psi.PsiWhiteSpace) NotNull(org.jetbrains.annotations.NotNull)

Example 27 with PsiElementVisitor

use of com.intellij.psi.PsiElementVisitor in project intellij-plugins by JetBrains.

the class JstdConfigFileUtils method buildSequenceTextFragment.

@Nullable
public static PsiElementFragment<YAMLSequenceItem> buildSequenceTextFragment(@NotNull YAMLSequenceItem sequence) {
    final Ref<Integer> startOffsetRef = Ref.create(null);
    final Ref<Integer> endOffsetRef = Ref.create(null);
    sequence.acceptChildren(new PsiElementVisitor() {

        @Override
        public void visitElement(PsiElement element) {
            if (JsPsiUtils.isElementOfType(element, YAMLTokenTypes.TEXT, YAMLTokenTypes.SCALAR_DSTRING, YAMLTokenTypes.SCALAR_STRING)) {
                UnquotedText unquotedText = new UnquotedText(element);
                TextRange usefulTextRange = unquotedText.getUnquotedDocumentTextRange();
                if (startOffsetRef.isNull()) {
                    startOffsetRef.set(usefulTextRange.getStartOffset());
                }
                endOffsetRef.set(usefulTextRange.getEndOffset());
            }
        }
    });
    Integer startOffset = startOffsetRef.get();
    Integer endOffset = endOffsetRef.get();
    if (startOffset == null || endOffset == null) {
        return null;
    }
    int sequenceStartOffset = sequence.getTextRange().getStartOffset();
    TextRange textRangeInSequence = TextRange.create(startOffset - sequenceStartOffset, endOffset - sequenceStartOffset);
    return PsiElementFragment.create(sequence, textRangeInSequence);
}
Also used : TextRange(com.intellij.openapi.util.TextRange) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 28 with PsiElementVisitor

use of com.intellij.psi.PsiElementVisitor in project intellij-community by JetBrains.

the class InjectedReferencesInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new PsiElementVisitor() {

        @Override
        public void visitElement(PsiElement element) {
            PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element);
            if (injected != null) {
                for (PsiReference reference : injected) {
                    if (reference.resolve() == null) {
                        TextRange range = reference.getRangeInElement();
                        if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals(element.getText())) {
                            String message = ProblemsHolder.unresolvedReferenceMessage(reference);
                            holder.registerProblem(element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create(0, 2));
                        } else {
                            holder.registerProblem(reference);
                        }
                    }
                }
            }
            super.visitElement(element);
        }
    };
}
Also used : PsiReference(com.intellij.psi.PsiReference) TextRange(com.intellij.openapi.util.TextRange) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 29 with PsiElementVisitor

use of com.intellij.psi.PsiElementVisitor in project intellij-community by JetBrains.

the class XmlLanguageInjector method getInjectedLanguage.

void getInjectedLanguage(final PsiElement place, final Ref<Boolean> unparsableRef, final PairProcessor<Language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>> processor) {
    if (place instanceof XmlTag) {
        final XmlTag xmlTag = (XmlTag) place;
        List<BaseInjection> injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
        //noinspection ForLoopReplaceableByForEach
        for (int i = 0, injectionsSize = injections.size(); i < injectionsSize; i++) {
            final BaseInjection injection = injections.get(i);
            if (injection.acceptsPsiElement(xmlTag)) {
                final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
                if (language == null)
                    continue;
                final boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern());
                final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result = ContainerUtil.newArrayList();
                xmlTag.acceptChildren(new PsiElementVisitor() {

                    @Override
                    public void visitElement(final PsiElement element) {
                        if (element instanceof XmlText) {
                            if (!(element instanceof PsiLanguageInjectionHost) || element.getTextLength() == 0)
                                return;
                            final List<TextRange> list = injection.getInjectedArea(element);
                            final InjectedLanguage l = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
                            for (TextRange textRange : list) {
                                result.add(Trinity.create((PsiLanguageInjectionHost) element, l, textRange));
                            }
                        } else if (element instanceof XmlTag) {
                            if (!separateFiles)
                                unparsableRef.set(Boolean.TRUE);
                            if (injection instanceof AbstractTagInjection && ((AbstractTagInjection) injection).isApplyToSubTags()) {
                                element.acceptChildren(this);
                            }
                        }
                    }
                });
                if (!result.isEmpty()) {
                    if (separateFiles) {
                        for (Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> trinity : result) {
                            processor.process(language, Collections.singletonList(trinity));
                        }
                    } else {
                        processor.process(language, result);
                    }
                }
                if (injection.isTerminal()) {
                    break;
                }
            }
        }
    } else if (place instanceof XmlAttributeValue && place.getParent() instanceof XmlAttribute) {
        final XmlAttribute attribute = (XmlAttribute) place.getParent();
        final XmlAttributeValue value = (XmlAttributeValue) place;
        //if (value == null) return;
        // Check that we don't inject anything into embedded (e.g. JavaScript) content:
        // XmlToken: "
        // JSEmbeddedContent
        // XmlToken "
        // Actually IDEA shouldn't ask for injected languages at all in this case.
        final PsiElement[] children = value.getChildren();
        if (children.length < 3 || !(children[1] instanceof XmlToken) || ((XmlToken) children[1]).getTokenType() != XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
            return;
        }
        List<BaseInjection> injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
        //noinspection ForLoopReplaceableByForEach
        for (int i = 0, size = injections.size(); i < size; i++) {
            BaseInjection injection = injections.get(i);
            if (injection.acceptsPsiElement(attribute)) {
                final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
                if (language == null)
                    continue;
                final boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern());
                final List<TextRange> ranges = injection.getInjectedArea(value);
                if (ranges.isEmpty())
                    continue;
                final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result = new ArrayList<>();
                final InjectedLanguage l = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
                for (TextRange textRange : ranges) {
                    result.add(Trinity.create((PsiLanguageInjectionHost) value, l, textRange));
                }
                if (separateFiles) {
                    for (Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> trinity : result) {
                        processor.process(language, Collections.singletonList(trinity));
                    }
                } else {
                    processor.process(language, result);
                }
                if (injection.isTerminal()) {
                    break;
                }
            }
        }
    }
}
Also used : Trinity(com.intellij.openapi.util.Trinity) TextRange(com.intellij.openapi.util.TextRange) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) BaseInjection(org.intellij.plugins.intelliLang.inject.config.BaseInjection) Language(com.intellij.lang.Language) InjectedLanguage(org.intellij.plugins.intelliLang.inject.InjectedLanguage) InjectedLanguage(org.intellij.plugins.intelliLang.inject.InjectedLanguage) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) AbstractTagInjection(org.intellij.plugins.intelliLang.inject.config.AbstractTagInjection) PsiElement(com.intellij.psi.PsiElement)

Example 30 with PsiElementVisitor

use of com.intellij.psi.PsiElementVisitor in project intellij-community by JetBrains.

the class InconsistentLanguageLevelInspection method runInspection.

@Override
public void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager, @NotNull GlobalInspectionContext globalContext, @NotNull ProblemDescriptionsProcessor problemProcessor) {
    final Set<Module> modules = new THashSet<>();
    scope.accept(new PsiElementVisitor() {

        @Override
        public void visitElement(PsiElement element) {
            final Module module = ModuleUtilCore.findModuleForPsiElement(element);
            if (module != null) {
                modules.add(module);
            }
        }
    });
    LanguageLevel projectLanguageLevel = LanguageLevelProjectExtension.getInstance(manager.getProject()).getLanguageLevel();
    for (Module module : modules) {
        LanguageLevel languageLevel = LanguageLevelModuleExtensionImpl.getInstance(module).getLanguageLevel();
        if (languageLevel == null) {
            languageLevel = projectLanguageLevel;
        }
        RefManager refManager = globalContext.getRefManager();
        final RefModule refModule = refManager.getRefModule(module);
        for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
            if (!(entry instanceof ModuleOrderEntry))
                continue;
            final Module dependantModule = ((ModuleOrderEntry) entry).getModule();
            if (dependantModule == null)
                continue;
            LanguageLevel dependantLanguageLevel = LanguageLevelModuleExtensionImpl.getInstance(dependantModule).getLanguageLevel();
            if (dependantLanguageLevel == null) {
                dependantLanguageLevel = projectLanguageLevel;
            }
            if (languageLevel.compareTo(dependantLanguageLevel) < 0) {
                final CommonProblemDescriptor problemDescriptor = manager.createProblemDescriptor("Inconsistent language level settings: module " + module.getName() + " with language level " + languageLevel + " depends on module " + dependantModule.getName() + " with language level " + dependantLanguageLevel, new UnnecessaryModuleDependencyInspection.RemoveModuleDependencyFix(module, dependantModule), (QuickFix) QuickFixFactory.getInstance().createShowModulePropertiesFix(module));
                problemProcessor.addProblemElement(refModule, problemDescriptor);
            }
        }
    }
}
Also used : RefManager(com.intellij.codeInspection.reference.RefManager) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) THashSet(gnu.trove.THashSet) RefModule(com.intellij.codeInspection.reference.RefModule) UnnecessaryModuleDependencyInspection(com.intellij.codeInspection.unnecessaryModuleDependency.UnnecessaryModuleDependencyInspection) LanguageLevel(com.intellij.pom.java.LanguageLevel) RefModule(com.intellij.codeInspection.reference.RefModule) Module(com.intellij.openapi.module.Module) PsiElement(com.intellij.psi.PsiElement)

Aggregations

PsiElementVisitor (com.intellij.psi.PsiElementVisitor)60 PsiElement (com.intellij.psi.PsiElement)54 NotNull (org.jetbrains.annotations.NotNull)49 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)39 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)37 BasePhpInspection (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection)37 com.jetbrains.php.lang.psi.elements (com.jetbrains.php.lang.psi.elements)27 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)21 Project (com.intellij.openapi.project.Project)19 MessagesPresentationUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil)19 PhpTokenTypes (com.jetbrains.php.lang.lexer.PhpTokenTypes)17 Set (java.util.Set)17 com.kalessil.phpStorm.phpInspectionsEA.utils (com.kalessil.phpStorm.phpInspectionsEA.utils)16 HashSet (java.util.HashSet)16 OptionsComponent (com.kalessil.phpStorm.phpInspectionsEA.options.OptionsComponent)15 javax.swing (javax.swing)15 LocalQuickFix (com.intellij.codeInspection.LocalQuickFix)14 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)14 ProblemDescriptor (com.intellij.codeInspection.ProblemDescriptor)12 ProblemHighlightType (com.intellij.codeInspection.ProblemHighlightType)12