Skip to content

Commit 4c6e314

Browse files
authored
Merge pull request #1083 from Haehnchen/feature/app-resolver
provide add better "app" folder detection and add more tests for related features #1036
2 parents beb0da7 + 22b5291 commit 4c6e314

File tree

11 files changed

+211
-80
lines changed

11 files changed

+211
-80
lines changed

META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@
593593
<TwigNamespaceExtension implementation="fr.adrienbrault.idea.symfony2plugin.templating.path.ContainerTwigNamespaceExtension"/>
594594
<TwigNamespaceExtension implementation="fr.adrienbrault.idea.symfony2plugin.templating.path.GlobalAppTwigNamespaceExtension"/>
595595
<TwigNamespaceExtension implementation="fr.adrienbrault.idea.symfony2plugin.templating.path.BundleTwigNamespaceExtension"/>
596+
<TwigNamespaceExtension implementation="fr.adrienbrault.idea.symfony2plugin.templating.path.BundleOverwriteNamespaceExtensions"/>
596597

597598
<ServiceCollector implementation="fr.adrienbrault.idea.symfony2plugin.dic.DefaultServiceCollector"/>
598599

src/fr/adrienbrault/idea/symfony2plugin/Symfony2ProjectComponent.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,6 @@ public Collection<File> getContainerFiles() {
124124
return validFiles;
125125
}
126126

127-
private String getPath(Project project, String path) {
128-
if (!FileUtil.isAbsolute(path)) { // Project relative path
129-
path = project.getBasePath() + "/" + path;
130-
}
131-
132-
return path;
133-
}
134-
135127
private void checkProject() {
136128
if(!this.isEnabled()
137129
&& !Settings.getInstance(project).dismissEnableNotification

src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import fr.adrienbrault.idea.symfony2plugin.templating.path.TwigPathIndex;
4141
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigTypeResolveUtil;
4242
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
43+
import fr.adrienbrault.idea.symfony2plugin.util.FilesystemUtil;
4344
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
4445
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyBundleUtil;
4546
import fr.adrienbrault.idea.symfony2plugin.util.dict.SymfonyBundle;
@@ -151,35 +152,6 @@ private static Map<String, Set<VirtualFile>> getTemplateMapProxy(@NotNull Projec
151152
return Collections.emptyMap();
152153
}
153154

154-
// app/Resources/ParentBundle/Resources/views
155-
Map<String, SymfonyBundle> parentBundles = new SymfonyBundleUtil(project).getParentBundles();
156-
if(parentBundles.size() > 0) {
157-
for (Map.Entry<String, SymfonyBundle> entry : parentBundles.entrySet()) {
158-
VirtualFile views = entry.getValue().getRelative("Resources/views");
159-
if(views != null) {
160-
twigPaths.add(new TwigPath(views.getPath(), entry.getKey(), TwigPathIndex.NamespaceType.BUNDLE));
161-
}
162-
}
163-
}
164-
165-
// app/Resources/FooBundle/views
166-
VirtualFile relativeFile = VfsUtil.findRelativeFile(project.getBaseDir(), "app", "Resources");
167-
if(relativeFile != null) {
168-
for (VirtualFile virtualFile : relativeFile.getChildren()) {
169-
170-
if(!virtualFile.isDirectory() || !virtualFile.getName().endsWith("Bundle")) {
171-
continue;
172-
}
173-
174-
VirtualFile views = virtualFile.findChild("views");
175-
if(views == null) {
176-
continue;
177-
}
178-
179-
twigPaths.add(new TwigPath(views.getPath(), virtualFile.getName(), TwigPathIndex.NamespaceType.BUNDLE));
180-
}
181-
}
182-
183155
Map<String, Set<VirtualFile>> templateNames = new HashMap<>();
184156

185157
for (TwigPath twigPath : twigPaths) {
@@ -2547,8 +2519,9 @@ public static Collection<Pair<String, String>> getTwigPathFromYamlConfigResolved
25472519
String second = pair.getSecond();
25482520

25492521
if(second.startsWith("%kernel.root_dir%")) {
2550-
VirtualFile appDir = VfsUtil.findRelativeFile(baseDir, "app");
2551-
if(appDir != null) {
2522+
// %kernel.root_dir%/../app
2523+
// %kernel.root_dir%/foo
2524+
for (VirtualFile appDir : FilesystemUtil.getAppDirectories(yamlFile.getProject())) {
25522525
String path = StringUtils.stripStart(second.substring("%kernel.root_dir%".length()), "/");
25532526

25542527
VirtualFile relativeFile = VfsUtil.findRelativeFile(appDir, path.split("/"));
@@ -2560,6 +2533,7 @@ public static Collection<Pair<String, String>> getTwigPathFromYamlConfigResolved
25602533
}
25612534
}
25622535
} else if(second.startsWith("%kernel.project_dir%")) {
2536+
// '%kernel.root_dir%/test'
25632537
String path = StringUtils.stripStart(second.substring("%kernel.project_dir%".length()), "/");
25642538

25652539
VirtualFile relativeFile = VfsUtil.findRelativeFile(yamlFile.getProject().getBaseDir(), path.split("/"));

src/fr/adrienbrault/idea/symfony2plugin/config/utils/ConfigUtil.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.jetbrains.php.lang.psi.elements.Method;
1212
import com.jetbrains.php.lang.psi.elements.MethodReference;
1313
import com.jetbrains.php.lang.psi.elements.PhpClass;
14+
import fr.adrienbrault.idea.symfony2plugin.util.FilesystemUtil;
1415
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
1516
import org.apache.commons.lang.StringUtils;
1617
import org.jetbrains.annotations.NotNull;
@@ -151,7 +152,7 @@ public TreeVisitor(@NotNull PhpClass phpClass, @NotNull PsiElement psiElement, @
151152
public static Collection<VirtualFile> getConfigurations(@NotNull Project project, @NotNull String packageName) {
152153
Collection<String[]> paths = Arrays.asList(
153154
new String[] {"config", "packages", packageName +".yml"},
154-
new String[] {"config", "packages", packageName + "config.yaml"}
155+
new String[] {"config", "packages", packageName, "config.yaml"}
155156
);
156157

157158
Collection<VirtualFile> virtualFiles = new HashSet<>();
@@ -163,12 +164,15 @@ public static Collection<VirtualFile> getConfigurations(@NotNull Project project
163164
}
164165
}
165166

166-
VirtualFile configDir = VfsUtil.findRelativeFile(project.getBaseDir(), "app", "config");
167-
if(configDir != null) {
168-
for (VirtualFile configFile : configDir.getChildren()) {
169-
// app/config/config*yml
170-
if(configFile.getFileType() == YAMLFileType.YML && configFile.getName().startsWith("config")) {
171-
virtualFiles.add(configFile);
167+
// note
168+
for (VirtualFile virtualFile : FilesystemUtil.getAppDirectories(project)) {
169+
VirtualFile configDir = VfsUtil.findRelativeFile(virtualFile, "config");
170+
if(configDir != null) {
171+
for (VirtualFile configFile : configDir.getChildren()) {
172+
// app/config/config*yml
173+
if(configFile.getFileType() == YAMLFileType.YML && configFile.getName().startsWith("config")) {
174+
virtualFiles.add(configFile);
175+
}
172176
}
173177
}
174178
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package fr.adrienbrault.idea.symfony2plugin.templating.path;
2+
3+
import com.intellij.openapi.vfs.VirtualFile;
4+
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtension;
5+
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtensionParameter;
6+
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyBundleUtil;
7+
import org.jetbrains.annotations.NotNull;
8+
9+
import java.util.ArrayList;
10+
import java.util.Collection;
11+
12+
/**
13+
* "app/Resources/ParentBundle/Resources/views"
14+
*
15+
* @author Daniel Espendiller <daniel@espendiller.net>
16+
*/
17+
public class BundleOverwriteNamespaceExtensions implements TwigNamespaceExtension {
18+
@NotNull
19+
@Override
20+
public Collection<TwigPath> getNamespaces(@NotNull TwigNamespaceExtensionParameter parameter) {
21+
Collection<TwigPath> twigPaths = new ArrayList<>();
22+
23+
new SymfonyBundleUtil(parameter.getProject()).getParentBundles().forEach((key, virtualFile) -> {
24+
VirtualFile views = virtualFile.getRelative("Resources/views");
25+
if (views != null) {
26+
twigPaths.add(new TwigPath(views.getPath(), key, TwigPathIndex.NamespaceType.BUNDLE));
27+
}
28+
});
29+
30+
return twigPaths;
31+
}
32+
}

src/fr/adrienbrault/idea/symfony2plugin/templating/path/GlobalAppTwigNamespaceExtension.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
import com.intellij.openapi.vfs.VfsUtil;
44
import com.intellij.openapi.vfs.VirtualFile;
5-
import fr.adrienbrault.idea.symfony2plugin.Settings;
65
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtension;
76
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtensionParameter;
7+
import fr.adrienbrault.idea.symfony2plugin.util.FilesystemUtil;
88
import org.jetbrains.annotations.NotNull;
99

1010
import java.util.ArrayList;
11-
import java.util.Arrays;
1211
import java.util.Collection;
13-
import java.util.List;
12+
import java.util.Objects;
13+
import java.util.stream.Collectors;
1414

1515
/**
1616
* app/Resources/views/foo.html.twig => :foo.html.twig
@@ -27,25 +27,24 @@ public class GlobalAppTwigNamespaceExtension implements TwigNamespaceExtension {
2727
public Collection<TwigPath> getNamespaces(@NotNull TwigNamespaceExtensionParameter parameter) {
2828
VirtualFile baseDir = parameter.getProject().getBaseDir();
2929

30-
Collection<TwigPath> paths = new ArrayList<>();
31-
32-
List<String[]> templatePaths = Arrays.asList(
33-
new String[]{Settings.getInstance(parameter.getProject()).directoryToApp, "Resources", "views"},
34-
new String[]{"templates"}
35-
);
36-
37-
for (String[] strings1 : templatePaths) {
38-
VirtualFile globalDirectory = VfsUtil.findRelativeFile(baseDir, strings1);
30+
// "app" folder
31+
Collection<VirtualFile> directories = FilesystemUtil.getAppDirectories(parameter.getProject()).stream()
32+
.map(path -> VfsUtil.findRelativeFile(path, "Resources", "views"))
33+
.filter(Objects::nonNull)
34+
.collect(Collectors.toSet());
3935

40-
if(globalDirectory == null) {
41-
continue;
42-
}
36+
// flex "templates" in root
37+
VirtualFile templates = VfsUtil.findRelativeFile(baseDir, "templates");
38+
if(templates != null) {
39+
directories.add(templates);
40+
}
4341

44-
String path = globalDirectory.getPath();
42+
Collection<TwigPath> paths = new ArrayList<>();
4543

44+
directories.stream().map(VirtualFile::getPath).forEach(path -> {
4645
paths.add(new TwigPath(path, TwigPathIndex.MAIN, TwigPathIndex.NamespaceType.BUNDLE));
4746
paths.add(new TwigPath(path, TwigPathIndex.MAIN, TwigPathIndex.NamespaceType.ADD_PATH));
48-
}
47+
});
4948

5049
return paths;
5150
}

src/fr/adrienbrault/idea/symfony2plugin/util/FilesystemUtil.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
package fr.adrienbrault.idea.symfony2plugin.util;
22

3+
import com.intellij.openapi.project.Project;
4+
import com.intellij.openapi.util.io.FileUtil;
5+
import com.intellij.openapi.vfs.VfsUtil;
6+
import com.intellij.openapi.vfs.VirtualFile;
37
import com.intellij.psi.PsiDirectory;
8+
import fr.adrienbrault.idea.symfony2plugin.Settings;
49
import org.jetbrains.annotations.NotNull;
510
import org.jetbrains.annotations.Nullable;
611

12+
import java.io.File;
13+
import java.util.Collection;
14+
import java.util.HashSet;
15+
716
/**
817
* @author Daniel Espendiller <daniel@espendiller.net>
918
*/
@@ -26,4 +35,41 @@ public static PsiDirectory findParentBundleFolder(@NotNull PsiDirectory director
2635
return null;
2736
}
2837

38+
/**
39+
* Try to find an "app" directory on configuration or on project directory in root
40+
* We also support absolute path in configuration
41+
*/
42+
@NotNull
43+
public static Collection<VirtualFile> getAppDirectories(@NotNull Project project) {
44+
Collection<VirtualFile> virtualFiles = new HashSet<>();
45+
46+
// find "app" folder on user settings
47+
String directoryToApp = Settings.getInstance(project).directoryToApp;
48+
49+
if(FileUtil.isAbsolute(directoryToApp)) {
50+
// absolute dir given
51+
VirtualFile fileByIoFile = VfsUtil.findFileByIoFile(new File(directoryToApp), true);
52+
if(fileByIoFile != null) {
53+
virtualFiles.add(fileByIoFile);
54+
}
55+
} else {
56+
// relative path resolve
57+
VirtualFile globalDirectory = VfsUtil.findRelativeFile(
58+
project.getBaseDir(),
59+
directoryToApp.replace("\\", "/").split("/")
60+
);
61+
62+
if(globalDirectory != null) {
63+
virtualFiles.add(globalDirectory);
64+
}
65+
}
66+
67+
// global "app" in root
68+
VirtualFile templates = VfsUtil.findRelativeFile(project.getBaseDir(), "app");
69+
if(templates != null) {
70+
virtualFiles.add(templates);
71+
}
72+
73+
return virtualFiles;
74+
}
2975
}

src/fr/adrienbrault/idea/symfony2plugin/util/yaml/YamlPsiElementFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void visitElement(PsiElement element) {
5555

5656

5757
@NotNull
58-
private static PsiFile createDummyFile(Project p, String fileText) {
58+
public static PsiFile createDummyFile(Project p, String fileText) {
5959
return PsiFileFactory.getInstance(p).createFileFromText("DUMMY__." + YAMLFileType.YML.getDefaultExtension(), YAMLFileType.YML, fileText, System.currentTimeMillis(), false);
6060
}
6161

tests/fr/adrienbrault/idea/symfony2plugin/tests/TwigHelperTempTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests;
22

3+
import com.intellij.openapi.util.Pair;
34
import com.intellij.psi.PsiDirectory;
45
import com.intellij.psi.PsiElement;
56
import com.intellij.psi.PsiFile;
67
import fr.adrienbrault.idea.symfony2plugin.Settings;
78
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
89
import fr.adrienbrault.idea.symfony2plugin.templating.path.TwigNamespaceSetting;
910
import fr.adrienbrault.idea.symfony2plugin.templating.path.TwigPathIndex;
11+
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlPsiElementFactory;
1012
import org.jetbrains.annotations.NotNull;
13+
import org.jetbrains.yaml.psi.YAMLFile;
1114

1215
import java.util.Arrays;
1316
import java.util.Collection;
@@ -139,6 +142,35 @@ public void testGetTemplateTargetOnOffset() {
139142
assertTrue(TwigHelper.getTemplateTargetOnOffset(getProject(), "foo.html.twig", 40).size() == 0);
140143
}
141144

145+
/**
146+
* @see fr.adrienbrault.idea.symfony2plugin.TwigHelper#getTwigPathFromYamlConfigResolved
147+
*/
148+
public void testGetTwigPathFromYamlConfigResolved() {
149+
createFile("app/test/foo.yaml");
150+
151+
PsiFile dummyFile = YamlPsiElementFactory.createDummyFile(getProject(), "" +
152+
"twig:\n" +
153+
" paths:\n" +
154+
" '%kernel.root_dir%/test': foo\n" +
155+
" '%kernel.project_dir%/app/test': project\n" +
156+
" '%kernel.root_dir%/../app': app\n"
157+
);
158+
159+
Collection<Pair<String, String>> paths = TwigHelper.getTwigPathFromYamlConfigResolved((YAMLFile) dummyFile);
160+
161+
assertNotNull(
162+
paths.stream().filter(pair -> "foo".equals(pair.getFirst()) && "app/test".equals(pair.getSecond())).findFirst()
163+
);
164+
165+
assertNotNull(
166+
paths.stream().filter(pair -> "project".equals(pair.getFirst()) && "app/test".equals(pair.getSecond())).findFirst()
167+
);
168+
169+
assertNotNull(
170+
paths.stream().filter(pair -> "app".equals(pair.getFirst()) && "app".equals(pair.getSecond())).findFirst()
171+
);
172+
}
173+
142174
private void assertIsDirectoryAtOffset(@NotNull String templateName, int offset, @NotNull String directory) {
143175
assertTrue(TwigHelper.getTemplateTargetOnOffset(getProject(), templateName, offset).stream().filter(psiElement -> psiElement instanceof PsiDirectory && directory.equals(((PsiDirectory) psiElement).getName())).count() > 0);
144176
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.config.utils;
2+
3+
import fr.adrienbrault.idea.symfony2plugin.config.utils.ConfigUtil;
4+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyTempCodeInsightFixtureTestCase;
5+
6+
/**
7+
* @author Daniel Espendiller <daniel@espendiller.net>
8+
* @see fr.adrienbrault.idea.symfony2plugin.config.utils.ConfigUtil
9+
*/
10+
public class ConfigUtilTempTest extends SymfonyTempCodeInsightFixtureTestCase {
11+
/**
12+
* @see ConfigUtil#getConfigurations
13+
*/
14+
public void testGetConfigurations() {
15+
createFile("config/packages/twig.yml");
16+
createFile("config/packages/twig/config.yaml");
17+
createFile("app/config/config_dev.yml");
18+
19+
assertEquals(3, ConfigUtil.getConfigurations(getProject(), "twig").size());
20+
}
21+
}

0 commit comments

Comments
 (0)