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");
}
}
}
}
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);
}
}
}
}
}
};
}
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]);
}
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]));
}
};
}
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);
}
}
}
};
}
Aggregations