Skip to content

Commit

Permalink
add support for Symfony flex: templates, configurations, yml -> yaml …
Browse files Browse the repository at this point in the history
…extension change, %kernel.project_dir% for Twig config path resolve #922
  • Loading branch information
Haehnchen committed Sep 24, 2017
1 parent 13e1285 commit ba6e35a
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 78 deletions.
37 changes: 22 additions & 15 deletions src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2285,31 +2285,38 @@ public static Collection<Pair<String, String>> getTwigPathFromYamlConfig(@NotNul
public static Collection<Pair<String, String>> getTwigPathFromYamlConfigResolved(@NotNull YAMLFile yamlFile) {
VirtualFile baseDir = yamlFile.getProject().getBaseDir();

VirtualFile appDir = VfsUtil.findRelativeFile(baseDir, "app");
if(appDir == null) {
return Collections.emptyList();
}

Collection<Pair<String, String>> paths = new ArrayList<>();

for (Pair<String, String> pair : getTwigPathFromYamlConfig(yamlFile)) {
String second = pair.getSecond();
if(!second.startsWith("%kernel.root_dir%")) {
continue;
}

String path = StringUtils.stripStart(second.substring("%kernel.root_dir%".length()), "/");
if(second.startsWith("%kernel.root_dir%")) {
VirtualFile appDir = VfsUtil.findRelativeFile(baseDir, "app");
if(appDir != null) {
String path = StringUtils.stripStart(second.substring("%kernel.root_dir%".length()), "/");

VirtualFile relativeFile = VfsUtil.findRelativeFile(appDir, path.split("/"));
if(relativeFile != null) {
String relativePath = VfsUtil.getRelativePath(relativeFile, baseDir, '/');
if(relativePath != null) {
paths.add(Pair.create(pair.getFirst(), relativePath));
VirtualFile relativeFile = VfsUtil.findRelativeFile(appDir, path.split("/"));
if(relativeFile != null) {
String relativePath = VfsUtil.getRelativePath(relativeFile, baseDir, '/');
if(relativePath != null) {
paths.add(Pair.create(pair.getFirst(), relativePath));
}
}
}
} else if(second.startsWith("%kernel.project_dir%")) {
String path = StringUtils.stripStart(second.substring("%kernel.project_dir%".length()), "/");

VirtualFile relativeFile = VfsUtil.findRelativeFile(yamlFile.getProject().getBaseDir(), path.split("/"));
if(relativeFile != null) {
String relativePath = VfsUtil.getRelativePath(relativeFile, baseDir, '/');
if(relativePath != null) {
paths.add(Pair.create(pair.getFirst(), relativePath));
}
}
}
}

return paths;
return paths;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ private static String[] getInvalidArgumentAttributes() {
}

public static void buildFile(AnActionEvent event, final Project project, String templatePath) {
String extension = templatePath.endsWith(".yml") ? "yml" : "xml" ;
String extension = (templatePath.endsWith(".yml") || templatePath.endsWith(".yaml")) ? "yml" : "xml" ;

String fileName = Messages.showInputDialog(project, "File name (without extension)", String.format("Create %s Service", extension), Symfony2Icons.SYMFONY);
if(fileName == null || StringUtils.isBlank(fileName)) {
return;
}

FileType fileType = templatePath.endsWith(".yml") ? YAMLFileType.YML : XmlFileType.INSTANCE ;
FileType fileType = (templatePath.endsWith(".yml") || templatePath.endsWith(".yaml")) ? YAMLFileType.YML : XmlFileType.INSTANCE ;

if(!fileName.endsWith("." + extension)) {
fileName = fileName.concat("." + extension);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ProcessingContext;
import fr.adrienbrault.idea.symfony2plugin.util.VfsExUtil;
import fr.adrienbrault.idea.symfony2plugin.util.psi.ParentPathPatternCondition;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLElementTypes;
import org.jetbrains.yaml.YAMLFileType;
import org.jetbrains.yaml.YAMLLanguage;
import org.jetbrains.yaml.YAMLTokenTypes;
import org.jetbrains.yaml.psi.*;
Expand All @@ -33,6 +35,29 @@ public class YamlElementPatternHelper {
*/
private static PatternCondition<YAMLKeyValue> YAML_KEY_SERVICES = new YAMLKeyValuePatternCondition("services");

/**
* config.yml, config_dev.yml,
* security.yml, security_dev.yml
*
* /../config/packages/doctrine.yml
* /../config/packages/test/doctrine.yml
*/
private static final PatternCondition<PsiFile> CONFIG_YAML_PATTERN = new PatternCondition<PsiFile>("Yaml Configuration") {
@Override
public boolean accepts(@NotNull PsiFile psiFile, ProcessingContext processingContext) {
if (psiFile.getFileType() != YAMLFileType.YML) {
return false;
}

if (psiFile.getName().matches("(security|config).*\\.(yml|yaml)")) {
return true;
}

String relativePath = VfsExUtil.getRelativeProjectPath(psiFile.getProject(), psiFile.getVirtualFile());
return relativePath != null && relativePath.contains("/config/packages/");
}
};

/**
* auto complete on
*
Expand Down Expand Up @@ -493,7 +518,13 @@ private static ElementPattern<? extends PsiFile> getOrmFilePattern() {
PlatformPatterns.string().endsWith("couchdb.yml"),
PlatformPatterns.string().endsWith("odm.yml"),
PlatformPatterns.string().endsWith("mongodb.yml"),
PlatformPatterns.string().endsWith("document.yml")
PlatformPatterns.string().endsWith("document.yml"),

PlatformPatterns.string().endsWith("orm.yaml"),
PlatformPatterns.string().endsWith("couchdb.yaml"),
PlatformPatterns.string().endsWith("odm.yaml"),
PlatformPatterns.string().endsWith("mongodb.yaml"),
PlatformPatterns.string().endsWith("document.yaml")
));
}

Expand Down Expand Up @@ -530,10 +561,13 @@ public static ElementPattern<PsiElement> getConfigKeyPattern() {
/**
* config.yml, config_dev.yml,
* security.yml, security_dev.yml
*
* /../config/packages/doctrine.yml
* /../config/packages/test/doctrine.yml
*/
@NotNull
public static PsiFilePattern.Capture<PsiFile> getConfigFileNamePattern() {
return PlatformPatterns.psiFile().withName(PlatformPatterns.string().matches("(security|config).*\\.yml"));
return PlatformPatterns.psiFile().with(CONFIG_YAML_PATTERN);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public static PsiElement[] getModelFieldTargets(@NotNull PhpClass phpClass,@NotN
@Nullable
private static PsiFile getEntityMetadataFile(@NotNull Project project, @NotNull SymfonyBundle symfonyBundleUtil, @NotNull String className, @NotNull String modelShortcut) {

for(String s: new String[] {"yml", "xml"}) {
for(String s: new String[] {"yml", "yaml", "xml"}) {

String entityFile = "Resources/config/doctrine/" + className + String.format(".%s.%s", modelShortcut, s);
VirtualFile virtualFile = symfonyBundleUtil.getRelative(entityFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ private void attachRelationClass(Collection<LineMarkerInfo> lineMarkerInfos, Psi

private boolean isMetadataFile(String fileName) {
fileName = fileName.toLowerCase();
return fileName.endsWith("orm.yml") || fileName.endsWith("odm.yml") || fileName.endsWith("mongodb.yml") || fileName.endsWith("couchdb.yml") || fileName.endsWith("document.yml");
return fileName.endsWith("orm.yml") || fileName.endsWith("odm.yml") || fileName.endsWith("mongodb.yml") || fileName.endsWith("couchdb.yml") || fileName.endsWith("document.yml")
|| fileName.endsWith("orm.yaml") || fileName.endsWith("odm.yaml") || fileName.endsWith("mongodb.yaml") || fileName.endsWith("couchdb.yaml") || fileName.endsWith("document.yaml");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,70 +51,72 @@ public static void visitAttribute(@NotNull Project project, @NotNull Consumer<Pa
}
}

for (PsiFile psiFile : FilenameIndex.getFilesByName(project, "security.yml", GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), YAMLFileType.YML))) {
if(!(psiFile instanceof YAMLFile)) {
continue;
}

YAMLKeyValue roleHierarchy = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, "security", "role_hierarchy");
if(roleHierarchy != null) {
YAMLValue value = roleHierarchy.getValue();
if(!(value instanceof YAMLMapping)) {
for (String files : new String[]{"security.yml", "security.yaml"}) {
for (PsiFile psiFile : FilenameIndex.getFilesByName(project, files, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), YAMLFileType.YML))) {
if(!(psiFile instanceof YAMLFile)) {
continue;
}

for (YAMLPsiElement yamlPsiElement : value.getYAMLElements()) {
if(!(yamlPsiElement instanceof YAMLKeyValue)) {
YAMLKeyValue roleHierarchy = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, "security", "role_hierarchy");
if(roleHierarchy != null) {
YAMLValue value = roleHierarchy.getValue();
if(!(value instanceof YAMLMapping)) {
continue;
}

String keyText = ((YAMLKeyValue) yamlPsiElement).getKeyText();
if(StringUtils.isNotBlank(keyText)) {
consumer.accept(Pair.create(keyText, yamlPsiElement));
}
for (YAMLPsiElement yamlPsiElement : value.getYAMLElements()) {
if(!(yamlPsiElement instanceof YAMLKeyValue)) {
continue;
}

YAMLValue yamlValue = ((YAMLKeyValue) yamlPsiElement).getValue();
if(yamlValue instanceof YAMLSequence) {
for (String item : YamlHelper.getYamlArrayValuesAsString((YAMLSequence) yamlValue)) {
consumer.accept(Pair.create(item, yamlValue));
String keyText = ((YAMLKeyValue) yamlPsiElement).getKeyText();
if(StringUtils.isNotBlank(keyText)) {
consumer.accept(Pair.create(keyText, yamlPsiElement));
}
}
}
}

YAMLKeyValue accessControl = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, "security", "access_control");
if(accessControl != null) {
YAMLValue value = accessControl.getValue();
if(!(value instanceof YAMLSequence)) {
continue;
YAMLValue yamlValue = ((YAMLKeyValue) yamlPsiElement).getValue();
if(yamlValue instanceof YAMLSequence) {
for (String item : YamlHelper.getYamlArrayValuesAsString((YAMLSequence) yamlValue)) {
consumer.accept(Pair.create(item, yamlValue));
}
}
}
}

for (YAMLPsiElement yamlPsiElement : value.getYAMLElements()) {
if(!(yamlPsiElement instanceof YAMLSequenceItem)) {
YAMLKeyValue accessControl = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, "security", "access_control");
if(accessControl != null) {
YAMLValue value = accessControl.getValue();
if(!(value instanceof YAMLSequence)) {
continue;
}

YAMLValue value1 = ((YAMLSequenceItem) yamlPsiElement).getValue();
if(!(value1 instanceof YAMLMapping)) {
continue;
}
for (YAMLPsiElement yamlPsiElement : value.getYAMLElements()) {
if(!(yamlPsiElement instanceof YAMLSequenceItem)) {
continue;
}

YAMLKeyValue roles = ((YAMLMapping) value1).getKeyValueByKey("roles");
if(roles == null) {
continue;
}
YAMLValue value1 = ((YAMLSequenceItem) yamlPsiElement).getValue();
if(!(value1 instanceof YAMLMapping)) {
continue;
}

YAMLValue value2 = roles.getValue();
if(value2 instanceof YAMLScalar) {
// roles: FOOBAR
String textValue = ((YAMLScalar) value2).getTextValue();
if(StringUtils.isNotBlank(textValue)) {
consumer.accept(Pair.create(textValue, value2));
YAMLKeyValue roles = ((YAMLMapping) value1).getKeyValueByKey("roles");
if(roles == null) {
continue;
}
} else if(value2 instanceof YAMLSequence) {
// roles: [FOOBAR, FOOBAR_1]
for (String item : YamlHelper.getYamlArrayValuesAsString((YAMLSequence) value2)) {
consumer.accept(Pair.create(item, value2));

YAMLValue value2 = roles.getValue();
if(value2 instanceof YAMLScalar) {
// roles: FOOBAR
String textValue = ((YAMLScalar) value2).getTextValue();
if(StringUtils.isNotBlank(textValue)) {
consumer.accept(Pair.create(textValue, value2));
}
} else if(value2 instanceof YAMLSequence) {
// roles: [FOOBAR, FOOBAR_1]
for (String item : YamlHelper.getYamlArrayValuesAsString((YAMLSequence) value2)) {
consumer.accept(Pair.create(item, value2));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static boolean isValidForIndex(FileContent inputData, PsiFile psiFile) {

// container file need to be xml file, eg xsd filetypes are not valid
String extension = inputData.getFile().getExtension();
if(extension == null || !(extension.equalsIgnoreCase("xml") || extension.equalsIgnoreCase("yml"))) {
if(extension == null || !(extension.equalsIgnoreCase("xml") || extension.equalsIgnoreCase("yml") || extension.equalsIgnoreCase("yaml"))) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtension;
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtensionParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLFileType;
import org.jetbrains.yaml.psi.YAMLFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

/**
* Extract Twig path of config.yml
Expand Down Expand Up @@ -50,19 +52,33 @@ public Collection<TwigPath> getNamespaces(@NotNull TwigNamespaceExtensionParamet

@NotNull
private Collection<TwigPath> getTwigPaths(@NotNull TwigNamespaceExtensionParameter parameter) {
Collection<String[]> paths = Arrays.asList(
new String[] {"config", "packages", "twig", "config.yml"},
new String[] {"config", "packages", "twig", "config.yaml"}
);

Collection<VirtualFile> virtualFiles = new HashSet<>();

for (String[] path : paths) {
VirtualFile configFile = VfsUtil.findRelativeFile(parameter.getProject().getBaseDir(), path);
if(configFile != null) {
virtualFiles.add(configFile);
}
}

VirtualFile configDir = VfsUtil.findRelativeFile(parameter.getProject().getBaseDir(), "app", "config");
if(configDir == null) {
return Collections.emptyList();
if(configDir != null) {
for (VirtualFile configFile : configDir.getChildren()) {
// app/config/config*yml
if(configFile.getFileType() == YAMLFileType.YML && configFile.getName().startsWith("config")) {
virtualFiles.add(configFile);
}
}
}

Collection<TwigPath> twigPaths = new ArrayList<>();

// app/config/config*yml
for (VirtualFile file : configDir.getChildren()) {
if(!file.getName().startsWith("config.yml")) {
continue;
}

for (VirtualFile file : virtualFiles) {
PsiFile psiFile = PsiManager.getInstance(parameter.getProject()).findFile(file);
if(!(psiFile instanceof YAMLFile)) {
continue;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package fr.adrienbrault.idea.symfony2plugin.tests.config.yaml;

import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlElementPatternHelper;
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
* @see fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlElementPatternHelper
*/
public class YamlElementPatternHelperTest extends SymfonyLightCodeInsightFixtureTestCase {
public String getTestDataPath() {
return new File(this.getClass().getResource("fixtures").getFile()).getAbsolutePath();
}

private String[] dataProviders() {
return new String[] {
Expand Down Expand Up @@ -172,6 +178,23 @@ public void testGetSuperParentArrayKey() {
)));
}

public void testGetConfigFileNamePattern() {
assertTrue(YamlElementPatternHelper.getConfigFileNamePattern().accepts(
myFixture.configureByText("config.yml", "")
));

myFixture.copyFileToProject("config.yaml", "config/packages/doctrine.yml");
myFixture.copyFileToProject("config.yaml", "config/packages/test/doctrine.yaml");

assertTrue(YamlElementPatternHelper.getConfigFileNamePattern().accepts(
myFixture.configureByFile("config/packages/doctrine.yml")
));

assertTrue(YamlElementPatternHelper.getConfigFileNamePattern().accepts(
myFixture.configureByFile("config/packages/test/doctrine.yaml")
));
}

private PsiElement createCaretElement(@NotNull String contents) {
return createCaretElement(contents, null);
}
Expand Down
Loading

0 comments on commit ba6e35a

Please sign in to comment.