Search in sources :

Example 1 with ViewInfo

use of com.nvlad.yii2support.views.entities.ViewInfo in project yii2support by nvlad.

the class CompletionProvider method addCompletions.

@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
    final PsiElement psiElement = completionParameters.getPosition();
    final MethodReference method = PsiTreeUtil.getParentOfType(psiElement, MethodReference.class);
    if (method == null || method.getParameters().length == 0) {
        return;
    }
    if (!ViewUtil.isValidRenderMethod(method)) {
        return;
    }
    PsiElement viewParameter = psiElement;
    while (viewParameter != null && !(viewParameter.getParent() instanceof ParameterList)) {
        viewParameter = viewParameter.getParent();
    }
    if (viewParameter == null || !viewParameter.equals(method.getParameters()[0])) {
        return;
    }
    final ViewResolve resolve = ViewUtil.resolveView(viewParameter);
    if (resolve == null) {
        return;
    }
    final Project project = psiElement.getProject();
    final GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
    final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
    int prefixLength = resolve.key.length();
    int lastSlashPosition = resolve.key.lastIndexOf('/');
    if (lastSlashPosition != -1 && !resolve.key.endsWith("/")) {
        prefixLength = lastSlashPosition + 1;
    }
    if (!completionParameters.isAutoPopup()) {
        if (completionResultSet.getPrefixMatcher().getPrefix().startsWith("@") && lastSlashPosition == -1) {
            final String prefix = completionResultSet.getPrefixMatcher().getPrefix();
            completionResultSet = completionResultSet.withPrefixMatcher(prefix.substring(1));
            prefixLength = 1;
        } else {
            completionResultSet = completionResultSet.withPrefixMatcher(resolve.key.substring(prefixLength));
        }
    }
    if (completionResultSet.getPrefixMatcher().getPrefix().equals("@")) {
        completionResultSet = completionResultSet.withPrefixMatcher("");
    }
    final String prefixFilter = resolve.key.substring(0, prefixLength);
    final Set<String> keys = new HashSet<>();
    fileBasedIndex.processAllKeys(ViewFileIndex.identity, key -> {
        if (key.startsWith(prefixFilter)) {
            keys.add(key);
        }
        return true;
    }, scope, null);
    final PsiManager psiManager = PsiManager.getInstance(project);
    boolean localViewSearch = false;
    if (resolve.from == ViewResolveFrom.View) {
        final String value = PhpUtil.getValue(viewParameter);
        localViewSearch = !value.startsWith("@") && !value.startsWith("//");
    }
    final String defaultViewExtension = '.' + Yii2SupportSettings.getInstance(psiElement.getProject()).defaultViewExtension;
    for (String key : keys) {
        Collection<ViewInfo> views = fileBasedIndex.getValues(ViewFileIndex.identity, key, scope);
        for (ViewInfo view : views) {
            if (!resolve.application.equals(view.application)) {
                continue;
            }
            if (localViewSearch && !resolve.theme.equals(view.theme)) {
                continue;
            }
            PsiFile psiFile = psiManager.findFile(view.getVirtualFile());
            if (psiFile != null) {
                String insertText = key.substring(prefixLength);
                if (insertText.endsWith(defaultViewExtension)) {
                    insertText = insertText.substring(0, insertText.length() - defaultViewExtension.length());
                }
                completionResultSet.addElement(new ViewLookupElement(psiFile, insertText));
                break;
            } else {
                System.out.println(view.fileUrl + " => not exists");
            }
        }
    }
}
Also used : ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) PsiManager(com.intellij.psi.PsiManager) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) Project(com.intellij.openapi.project.Project) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) MethodReference(com.jetbrains.php.lang.psi.elements.MethodReference) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) FileBasedIndex(com.intellij.util.indexing.FileBasedIndex) HashSet(java.util.HashSet)

Example 2 with ViewInfo

use of com.nvlad.yii2support.views.entities.ViewInfo in project yii2support by nvlad.

the class MissedViewInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
    return new PhpElementVisitor() {

        @Override
        public void visitPhpMethodReference(MethodReference reference) {
            if (!ViewUtil.isValidRenderMethod(reference)) {
                return;
            }
            if (ArrayUtil.contains(reference.getName(), ViewUtil.renderMethods)) {
                if (reference.getParameters().length > 0) {
                    final PsiElement pathParameter = reference.getParameters()[0];
                    final ViewResolve resolve = ViewUtil.resolveView(pathParameter);
                    if (resolve == null) {
                        return;
                    }
                    String key = resolve.key;
                    if (Files.getFileExtension(key).isEmpty()) {
                        key = key + '.' + Yii2SupportSettings.getInstance(reference.getProject()).defaultViewExtension;
                    }
                    final Project project = reference.getProject();
                    final Collection<ViewInfo> views = FileBasedIndex.getInstance().getValues(ViewFileIndex.identity, key, GlobalSearchScope.projectScope(project));
                    final String application = YiiApplicationUtils.getApplicationName(reference.getContainingFile());
                    final boolean localViewSearch;
                    final String value = PhpUtil.getValue(pathParameter);
                    if (resolve.from == ViewResolveFrom.View) {
                        localViewSearch = !value.startsWith("@") && !value.startsWith("//");
                    } else {
                        localViewSearch = false;
                    }
                    views.removeIf(view -> {
                        if (!application.equals(view.application)) {
                            return true;
                        }
                        return localViewSearch && !resolve.theme.equals(view.theme);
                    });
                    if (views.size() != 0) {
                        return;
                    }
                    if (pathParameter instanceof StringLiteralExpression) {
                        Collection<String> paths = ViewUtil.viewResolveToPaths(resolve, project);
                        if (!paths.iterator().hasNext()) {
                            return;
                        }
                        VirtualFile yiiRoot = YiiApplicationUtils.getYiiRootVirtualFile(project);
                        if (yiiRoot == null) {
                            return;
                        }
                        int projectUrlLength = project.getBaseDir().getUrl().length();
                        String yiiRootUrl = yiiRoot.getUrl();
                        String path;
                        if (projectUrlLength > yiiRootUrl.length()) {
                            path = paths.iterator().next();
                        } else {
                            path = yiiRootUrl.substring(projectUrlLength) + paths.iterator().next();
                        }
                        final String viewNotFoundMessage = "View file for \"" + value + "\" not found in \"" + path + "\".";
                        final MissedViewLocalQuickFix quickFix = new MissedViewLocalQuickFix(value, path, RenderUtil.getViewArguments(reference));
                        final PsiElement stringPart = pathParameter.findElementAt(1);
                        if (stringPart != null) {
                            problemsHolder.registerProblem(stringPart, viewNotFoundMessage, quickFix);
                        }
                    }
                }
            }
        }
    };
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PhpElementVisitor(com.jetbrains.php.lang.psi.visitors.PhpElementVisitor) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) Project(com.intellij.openapi.project.Project) MethodReference(com.jetbrains.php.lang.psi.elements.MethodReference) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with ViewInfo

use of com.nvlad.yii2support.views.entities.ViewInfo in project yii2support by nvlad.

the class PsiReferenceProvider method getReferencesByElement.

@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
    Set<PsiReference> references = new HashSet<>();
    final ViewResolve resolve = ViewUtil.resolveView(psiElement);
    if (resolve != null) {
        Project project = psiElement.getProject();
        String key = resolve.key;
        if (Files.getFileExtension(key).isEmpty()) {
            key = key + '.' + Yii2SupportSettings.getInstance(psiElement.getProject()).defaultViewExtension;
        }
        final Collection<ViewInfo> views = FileBasedIndex.getInstance().getValues(ViewFileIndex.identity, key, GlobalSearchScope.projectScope(project));
        if (views.size() > 0) {
            boolean localViewSearch = false;
            if (resolve.from == ViewResolveFrom.View) {
                final String value = PhpUtil.getValue(psiElement);
                localViewSearch = !value.startsWith("@") && !value.startsWith("//");
            }
            for (ViewInfo view : views) {
                if (!resolve.application.equals(view.application)) {
                    continue;
                }
                if (localViewSearch && !resolve.theme.equals(view.theme)) {
                    continue;
                }
                PsiFile file = PsiManager.getInstance(project).findFile(view.getVirtualFile());
                if (file != null) {
                    references.add(new PsiReference(psiElement, file));
                }
            }
        }
    }
    return references.toArray(new PsiReference[0]);
}
Also used : Project(com.intellij.openapi.project.Project) ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) PsiFile(com.intellij.psi.PsiFile) HashSet(java.util.HashSet) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with ViewInfo

use of com.nvlad.yii2support.views.entities.ViewInfo in project yii2support by nvlad.

the class RequireParameterInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
    return new PhpElementVisitor() {

        @Override
        public void visitPhpMethodReference(MethodReference reference) {
            if (!ViewUtil.isValidRenderMethod(reference)) {
                return;
            }
            final String name = reference.getName();
            if (name == null || !ArrayUtil.contains(name, ViewUtil.renderMethods)) {
                return;
            }
            final PsiElement[] renderParameters = reference.getParameters();
            if (renderParameters.length == 0 || !(renderParameters[0] instanceof StringLiteralExpression)) {
                return;
            }
            final ViewResolve resolve = ViewUtil.resolveView(renderParameters[0]);
            if (resolve == null) {
                return;
            }
            String key = resolve.key;
            if (Files.getFileExtension(key).isEmpty()) {
                key = key + '.' + Yii2SupportSettings.getInstance(reference.getProject()).defaultViewExtension;
            }
            final Project project = reference.getProject();
            final Collection<ViewInfo> views = FileBasedIndex.getInstance().getValues(ViewFileIndex.identity, key, GlobalSearchScope.projectScope(project));
            final String application = YiiApplicationUtils.getApplicationName(reference.getContainingFile());
            views.removeIf(viewInfo -> !application.equals(viewInfo.application));
            if (views.size() == 0) {
                return;
            }
            final Collection<String> viewParameters = new HashSet<>();
            for (ViewInfo view : views) {
                viewParameters.addAll(view.parameters);
            }
            if (viewParameters.size() == 0) {
                return;
            }
            final Collection<String> existKeys;
            if (renderParameters.length > 1) {
                if (renderParameters[1] instanceof ArrayCreationExpression) {
                    existKeys = PhpUtil.getArrayKeys((ArrayCreationExpression) renderParameters[1]);
                } else if (renderParameters[1] instanceof FunctionReference) {
                    FunctionReference function = (FunctionReference) renderParameters[1];
                    if (function.getName() != null && function.getName().equals("compact")) {
                        existKeys = new HashSet<>();
                        for (PsiElement element : function.getParameters()) {
                            if (element instanceof StringLiteralExpression) {
                                existKeys.add(((StringLiteralExpression) element).getContents());
                            }
                        }
                    } else {
                        return;
                    }
                } else {
                    return;
                }
            } else {
                existKeys = new HashSet<>();
            }
            viewParameters.removeIf(existKeys::contains);
            if (viewParameters.size() == 0) {
                return;
            }
            String description = "View " + renderParameters[0].getText() + " require ";
            final Iterator<String> parameterIterator = viewParameters.iterator();
            if (!isOnTheFly) {
                while (parameterIterator.hasNext()) {
                    final String parameter = parameterIterator.next();
                    final String problemDescription = description + "\"" + parameter + "\" parameter.";
                    problemsHolder.registerProblem(reference, problemDescription, new RequireParameterLocalQuickFix(parameter));
                }
                return;
            }
            final Collection<LocalQuickFix> fixes = new HashSet<>();
            if (viewParameters.size() > 1) {
                fixes.add(new RequireParameterLocalQuickFix(viewParameters.toArray(new String[0])));
                StringBuilder parameterString = new StringBuilder();
                String parameter = parameterIterator.next();
                while (parameterIterator.hasNext()) {
                    if (parameterString.length() > 0) {
                        parameterString.append(", ");
                    }
                    parameterString.append("\"").append(parameter).append("\"");
                    fixes.add(new RequireParameterLocalQuickFix(parameter));
                    parameter = parameterIterator.next();
                }
                parameterString.append(" and \"").append(parameter).append("\" parameters.");
                description += parameterString.toString();
                fixes.add(new RequireParameterLocalQuickFix(parameter));
            } else {
                String parameter = parameterIterator.next();
                description += "\"" + parameter + "\" parameter.";
                fixes.add(new RequireParameterLocalQuickFix(parameter));
            }
            problemsHolder.registerProblem(reference, description, fixes.toArray(new LocalQuickFix[0]));
        }
    };
}
Also used : PhpElementVisitor(com.jetbrains.php.lang.psi.visitors.PhpElementVisitor) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) LocalQuickFix(com.intellij.codeInspection.LocalQuickFix) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) Project(com.intellij.openapi.project.Project) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) MethodReference(com.jetbrains.php.lang.psi.elements.MethodReference) PsiElement(com.intellij.psi.PsiElement) HashSet(java.util.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with ViewInfo

use of com.nvlad.yii2support.views.entities.ViewInfo in project yii2support by nvlad.

the class UnusedParameterInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
    return new PhpElementVisitor() {

        @Override
        public void visitPhpMethodReference(MethodReference reference) {
            if (!ViewUtil.isValidRenderMethod(reference)) {
                return;
            }
            final String name = reference.getName();
            if (name == null || !ArrayUtil.contains(name, ViewUtil.renderMethods)) {
                return;
            }
            final PsiElement[] renderParameters = reference.getParameters();
            if (renderParameters.length < 2 || !(renderParameters[0] instanceof StringLiteralExpression)) {
                return;
            }
            final ViewResolve resolve = ViewUtil.resolveView(renderParameters[0]);
            if (resolve == null) {
                return;
            }
            String key = resolve.key;
            if (Files.getFileExtension(key).isEmpty()) {
                key = key + '.' + Yii2SupportSettings.getInstance(reference.getProject()).defaultViewExtension;
            }
            final Project project = reference.getProject();
            final Collection<ViewInfo> views = FileBasedIndex.getInstance().getValues(ViewFileIndex.identity, key, GlobalSearchScope.projectScope(project));
            final String application = YiiApplicationUtils.getApplicationName(reference.getContainingFile());
            views.removeIf(viewInfo -> !application.equals(viewInfo.application));
            if (views.size() == 0) {
                return;
            }
            final Collection<String> viewParameters = new HashSet<>();
            for (ViewInfo view : views) {
                viewParameters.addAll(view.parameters);
            }
            if (viewParameters.size() == 0) {
                if (renderParameters[1] instanceof ArrayCreationExpression || renderParameters[1] instanceof FunctionReference) {
                    String errorUnusedParameters = "This View does not use parameters";
                    UnusedParametersLocalQuickFix fix = new UnusedParametersLocalQuickFix();
                    problemsHolder.registerProblem(renderParameters[1], errorUnusedParameters, ProblemHighlightType.LIKE_UNUSED_SYMBOL, fix);
                    if (isOnTheFly) {
                        problemsHolder.registerProblem(reference, errorUnusedParameters, ProblemHighlightType.INFORMATION, fix);
                    }
                }
                return;
            }
            final String errorUnusedParameter = "View " + renderParameters[0].getText() + " not use \"%parameter%\" parameter";
            final Set<String> unusedParameters = new HashSet<>();
            BiConsumer<String, PsiElement> processParameter = (String arrayKey, PsiElement element) -> {
                if (!viewParameters.contains(arrayKey)) {
                    UnusedParameterLocalQuickFix fix = new UnusedParameterLocalQuickFix(arrayKey);
                    String description = errorUnusedParameter.replace("%parameter%", arrayKey);
                    problemsHolder.registerProblem(element, description, ProblemHighlightType.LIKE_UNUSED_SYMBOL, fix);
                    unusedParameters.add(arrayKey);
                }
            };
            if (renderParameters[1] instanceof ArrayCreationExpression) {
                for (ArrayHashElement element : ((ArrayCreationExpression) renderParameters[1]).getHashElements()) {
                    if (element.getKey() != null && element.getKey() instanceof StringLiteralExpression) {
                        final String arrayKey = ((StringLiteralExpression) element.getKey()).getContents();
                        processParameter.accept(arrayKey, element);
                    }
                }
            }
            if (renderParameters[1] instanceof FunctionReference) {
                FunctionReference function = ((FunctionReference) renderParameters[1]);
                if (function.getName() != null && function.getName().contains("compact")) {
                    for (PsiElement element : function.getParameters()) {
                        if (element instanceof StringLiteralExpression) {
                            String arrayKey = ((StringLiteralExpression) element).getContents();
                            processParameter.accept(arrayKey, element);
                        }
                    }
                }
            }
            if (unusedParameters.size() > 0 && isOnTheFly) {
                if (viewParameters.containsAll(unusedParameters)) {
                    String errorUnusedParameters = "This View does not use parameters";
                    UnusedParametersLocalQuickFix fix = new UnusedParametersLocalQuickFix();
                    problemsHolder.registerProblem(renderParameters[1], errorUnusedParameters, ProblemHighlightType.LIKE_UNUSED_SYMBOL, fix);
                    problemsHolder.registerProblem(reference, errorUnusedParameters, ProblemHighlightType.INFORMATION, fix);
                } else {
                    String errorUnusedParameters = "This View have unused parameters";
                    UnusedParametersLocalQuickFix fix = new UnusedParametersLocalQuickFix(unusedParameters);
                    problemsHolder.registerProblem(reference, errorUnusedParameters, ProblemHighlightType.INFORMATION, fix);
                }
            }
        }
    };
}
Also used : PhpElementVisitor(com.jetbrains.php.lang.psi.visitors.PhpElementVisitor) ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) Project(com.intellij.openapi.project.Project) PsiElement(com.intellij.psi.PsiElement) HashSet(java.util.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Project (com.intellij.openapi.project.Project)5 ViewInfo (com.nvlad.yii2support.views.entities.ViewInfo)5 ViewResolve (com.nvlad.yii2support.views.entities.ViewResolve)5 PsiElement (com.intellij.psi.PsiElement)4 HashSet (java.util.HashSet)4 NotNull (org.jetbrains.annotations.NotNull)4 MethodReference (com.jetbrains.php.lang.psi.elements.MethodReference)3 PhpElementVisitor (com.jetbrains.php.lang.psi.visitors.PhpElementVisitor)3 PsiFile (com.intellij.psi.PsiFile)2 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)2 LocalQuickFix (com.intellij.codeInspection.LocalQuickFix)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 PsiManager (com.intellij.psi.PsiManager)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 FileBasedIndex (com.intellij.util.indexing.FileBasedIndex)1 ArrayCreationExpression (com.jetbrains.php.lang.psi.elements.ArrayCreationExpression)1 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)1 ParameterList (com.jetbrains.php.lang.psi.elements.ParameterList)1