Skip to content

Commit 5ab89e8

Browse files
committed
Add annotator for missing paths
1 parent 359b201 commit 5ab89e8

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.cedricziel.idea.typo3.annotation;
2+
3+
import com.intellij.lang.annotation.AnnotationHolder;
4+
import com.intellij.lang.annotation.Annotator;
5+
import com.intellij.openapi.vfs.VirtualFile;
6+
import com.intellij.psi.PsiElement;
7+
import com.intellij.psi.PsiFile;
8+
import com.intellij.psi.search.FilenameIndex;
9+
import com.intellij.psi.search.GlobalSearchScope;
10+
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
11+
import org.codehaus.plexus.util.DirectoryScanner;
12+
import org.jetbrains.annotations.NotNull;
13+
14+
import java.util.Arrays;
15+
import java.util.List;
16+
17+
/**
18+
* Matches {@link StringLiteralExpression} elements and annotates them if a resource does not exist.
19+
* <p>
20+
* Example strings:
21+
* "EXT:foo/bar/baz.typoscript"
22+
*/
23+
public class PathResourceAnnotator implements Annotator {
24+
@Override
25+
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
26+
if (!(element instanceof StringLiteralExpression)) {
27+
return;
28+
}
29+
30+
String content = ((StringLiteralExpression) element).getContents();
31+
if (!content.startsWith("EXT:") || element.getProject().getBasePath() == null) {
32+
return;
33+
}
34+
35+
String resourceName = content.substring(4, content.length());
36+
if (resourceName.contains(":")) {
37+
// resource name points to a sub-resource such as a translation string, not here.
38+
return;
39+
}
40+
41+
String[] split = resourceName.split("/");
42+
String fileName = split[split.length - 1];
43+
DirectoryScanner scanner = new DirectoryScanner();
44+
45+
scanner.setBasedir(element.getProject().getBasePath());
46+
scanner.addDefaultExcludes();
47+
scanner.setIncludes(new String[]{"**/" + resourceName + "/"});
48+
scanner.scan();
49+
50+
String[] paths = scanner.getIncludedFiles();
51+
if (paths.length != 0) {
52+
// the resource is a directory
53+
return;
54+
}
55+
56+
List<PsiFile> filesByName = Arrays.asList(FilenameIndex.getFilesByName(element.getProject(), fileName, GlobalSearchScope.allScope(element.getProject())));
57+
if (filesByName.size() == 0) {
58+
createErrorMessage(element, holder, resourceName);
59+
60+
return;
61+
}
62+
63+
for (PsiFile file : filesByName) {
64+
VirtualFile virtualFile = file.getVirtualFile();
65+
66+
67+
if (virtualFile.getPath().contains("typo3conf/ext/" + resourceName) || virtualFile.getPath().contains("sysext/" + resourceName)) {
68+
// all good
69+
return;
70+
}
71+
72+
if (virtualFile.isDirectory() && virtualFile.getPath().endsWith(resourceName)) {
73+
return;
74+
}
75+
}
76+
77+
createErrorMessage(element, holder, resourceName);
78+
}
79+
80+
private void createErrorMessage(@NotNull PsiElement element, @NotNull AnnotationHolder holder, String resourceName) {
81+
String message = "Resource \"%s\" could not be found in your current project.".replace("%s", resourceName);
82+
holder.createErrorAnnotation(element, message);
83+
}
84+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ It is a great inspiration for possible solutions and parts of the code.</p>
275275
<!-- annotation -->
276276
<annotator language="PHP" implementationClass="com.cedricziel.idea.typo3.annotation.IconAnnotator"/>
277277
<annotator language="PHP" implementationClass="com.cedricziel.idea.typo3.annotation.RouteAnnotator"/>
278+
<annotator language="PHP" implementationClass="com.cedricziel.idea.typo3.annotation.PathResourceAnnotator"/>
278279

279280
<!-- marker -->
280281
<codeInsight.lineMarkerProvider language="PHP"

0 commit comments

Comments
 (0)