Search in sources :

Example 1 with ViewResolve

use of com.nvlad.yii2support.views.entities.ViewResolve 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 ViewResolve

use of com.nvlad.yii2support.views.entities.ViewResolve 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 ViewResolve

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

the class ViewUtil method resolveViewFromController.

@NotNull
private static ViewResolve resolveViewFromController(PhpClass clazz, String value) {
    ViewResolve result = new ViewResolve(ViewResolveFrom.Controller);
    final String classFQN = clazz.getFQN().replace('\\', '/');
    StringBuilder key = new StringBuilder("@app");
    String path = deletePathPart(classFQN);
    if (path.startsWith("/modules/")) {
        key.append("/modules");
        path = deletePathPart(path);
    }
    int controllersPathPartPosition = path.indexOf("/controllers/");
    if (controllersPathPartPosition == -1) {
        throw new InvalidPathException(path, "Not found \"controllers\" directory.");
    }
    result.application = getFirstPathPart(classFQN);
    if (controllersPathPartPosition > 0) {
        final String module = path.substring(0, controllersPathPartPosition);
        key.append(module);
        path = path.substring(controllersPathPartPosition);
        result.module = module;
    }
    path = deletePathPart(path);
    key.append("/views");
    if (value.startsWith("/")) {
        result.key = normalizePath(key + value);
        return result;
    }
    final String className = clazz.getName();
    key.append(path, 0, path.length() - className.length());
    key.append(StringUtils.CamelToId(className.substring(0, className.length() - 10), "-"));
    key.append('/');
    key.append(value);
    result.key = normalizePath(key.toString());
    return result;
}
Also used : ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) InvalidPathException(java.nio.file.InvalidPathException) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with ViewResolve

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

the class ViewUtil method resolveViewFromWidget.

@NotNull
private static ViewResolve resolveViewFromWidget(PhpClass clazz, String value) {
    ViewResolve result = new ViewResolve(ViewResolveFrom.Widget);
    final String classFQN = clazz.getFQN().replace('\\', '/');
    StringBuilder key = new StringBuilder("@app");
    String path = deletePathPart(classFQN);
    final int widgetsPathPartPosition = path.indexOf("/widgets/");
    if (widgetsPathPartPosition == -1) {
        throw new InvalidPathException(path, "Not found \"widgets\" directory.");
    }
    result.application = getFirstPathPart(classFQN);
    if (widgetsPathPartPosition > 0) {
        final String modulePath = path.substring(0, widgetsPathPartPosition);
        key.append(modulePath);
        result.module = modulePath.substring(modulePath.lastIndexOf('/') + 1);
        path = path.substring(modulePath.length());
    }
    if (value.startsWith("/")) {
        key.append("/views");
    } else {
        key.append("/widgets");
        path = deletePathPart(path);
        key.append(path, 0, path.length() - clazz.getName().length());
        key.append("views/");
    }
    key.append(value);
    result.key = normalizePath(key.toString());
    return result;
}
Also used : ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) InvalidPathException(java.nio.file.InvalidPathException) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with ViewResolve

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

the class ViewUtil method resolveView.

@Nullable
public static ViewResolve resolveView(VirtualFile virtualFile, Project project) {
    final String projectPath = YiiApplicationUtils.getYiiRootPath(project);
    if (projectPath == null) {
        return null;
    }
    int projectBaseDirLength = projectPath.length();
    final String absolutePath = virtualFile.getPath();
    if (!absolutePath.startsWith(projectPath)) {
        return null;
    }
    String path = absolutePath.substring(projectBaseDirLength);
    if (!path.startsWith("/vendor/")) {
        ViewResolve result = new ViewResolve();
        result.application = YiiApplicationUtils.getApplicationName(virtualFile, project);
        result.theme = "";
        if (path.startsWith("/" + result.application + "/")) {
            path = path.substring(result.application.length() + 1);
        }
        result.relativePath = path;
        path = "@app" + path;
        if (!path.startsWith("@app/views/") && !(path.startsWith("@app/modules/") && path.contains("/views/")) && !(path.startsWith("@app/widgets/") && path.contains("/views/"))) {
            String viewPath = null;
            for (Map.Entry<Pattern, String> entry : ViewUtil.getPatterns(project).entrySet()) {
                Matcher matcher = entry.getKey().matcher(path);
                if (matcher.find()) {
                    viewPath = entry.getValue() + path.substring(matcher.end(1));
                    result.theme = matcher.group(2);
                    break;
                }
            }
            if (viewPath == null) {
                return null;
            }
            path = viewPath;
        }
        result.key = path;
        return result;
    }
    return null;
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

ViewResolve (com.nvlad.yii2support.views.entities.ViewResolve)11 NotNull (org.jetbrains.annotations.NotNull)8 Project (com.intellij.openapi.project.Project)6 ViewInfo (com.nvlad.yii2support.views.entities.ViewInfo)5 PsiElement (com.intellij.psi.PsiElement)4 MethodReference (com.jetbrains.php.lang.psi.elements.MethodReference)4 PhpElementVisitor (com.jetbrains.php.lang.psi.visitors.PhpElementVisitor)4 InvalidPathException (java.nio.file.InvalidPathException)4 HashSet (java.util.HashSet)4 VirtualFile (com.intellij.openapi.vfs.VirtualFile)2 PsiFile (com.intellij.psi.PsiFile)2 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)2 Nullable (org.jetbrains.annotations.Nullable)2 LocalQuickFix (com.intellij.codeInspection.LocalQuickFix)1 PsiManager (com.intellij.psi.PsiManager)1 PsiReference (com.intellij.psi.PsiReference)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 FileBasedIndex (com.intellij.util.indexing.FileBasedIndex)1 PhpIndex (com.jetbrains.php.PhpIndex)1 PhpDocVariable (com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocVariable)1