diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProvider.java new file mode 100644 index 000000000..d9df7c019 --- /dev/null +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProvider.java @@ -0,0 +1,30 @@ +package fr.adrienbrault.idea.symfony2plugin.extension; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Provide extension implementation for new translator source + * + * @author Daniel Espendiller + */ +public interface TranslatorProvider { + boolean hasTranslationKey(@NotNull Project project, @NotNull String keyName, @NotNull String domainName); + boolean hasDomain(@NotNull Project project, @NotNull String domainName); + + @NotNull + Collection getTranslationDomains(@NotNull Project project); + + @NotNull + Collection getTranslationTargets(@NotNull Project project, @NotNull String translationKey, @NotNull String domain); + + @NotNull + Collection getDomainPsiFiles(final Project project, @NotNull String domainName); + + @NotNull + Collection getTranslationsForDomain(@NotNull Project project, @NotNull String domainName); +} diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProviderDict.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProviderDict.java new file mode 100644 index 000000000..3442ffce0 --- /dev/null +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/extension/TranslatorProviderDict.java @@ -0,0 +1,58 @@ +package fr.adrienbrault.idea.symfony2plugin.extension; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Daniel Espendiller + */ +public class TranslatorProviderDict { + public static class TranslationDomain { + @NotNull + private final String domain; + private final boolean weak; + + public TranslationDomain(@NotNull String domain) { + this.domain = domain; + this.weak = false; + } + + public TranslationDomain(@NotNull String domain, boolean weak) { + this.domain = domain; + this.weak = weak; + } + + @NotNull + public String getDomain() { + return domain; + } + + public boolean isWeak() { + return weak; + } + } + + public static class TranslationKey { + @NotNull + private final String domain; + private final boolean weak; + + public TranslationKey(@NotNull String domain) { + this.domain = domain; + this.weak = false; + } + + public TranslationKey(@NotNull String domain, boolean weak) { + this.domain = domain; + this.weak = weak; + } + + @NotNull + public String getDomain() { + return domain; + } + + public boolean isWeak() { + return weak; + } + } +} diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/dict/TranslationUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/dict/TranslationUtil.java index 3744724a3..af8df7b04 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/dict/TranslationUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/dict/TranslationUtil.java @@ -1,37 +1,24 @@ package fr.adrienbrault.idea.symfony2plugin.translation.dict; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.Consumer; -import com.intellij.util.indexing.FileBasedIndex; -import com.jetbrains.php.PhpIndex; -import fr.adrienbrault.idea.symfony2plugin.stubs.SymfonyProcessors; -import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TranslationStubIndex; -import fr.adrienbrault.idea.symfony2plugin.translation.TranslationIndex; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProvider; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProviderDict; import fr.adrienbrault.idea.symfony2plugin.translation.TranslatorLookupElement; -import fr.adrienbrault.idea.symfony2plugin.translation.collector.YamlTranslationCollector; -import fr.adrienbrault.idea.symfony2plugin.translation.collector.YamlTranslationVisitor; import fr.adrienbrault.idea.symfony2plugin.translation.parser.DomainMappings; -import fr.adrienbrault.idea.symfony2plugin.translation.parser.TranslationStringMap; import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher; import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils; import fr.adrienbrault.idea.symfony2plugin.util.service.ServiceXmlParserFactory; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.yaml.YAMLFileType; -import org.jetbrains.yaml.YAMLUtil; -import org.jetbrains.yaml.psi.YAMLDocument; -import org.jetbrains.yaml.psi.YAMLFile; -import org.jetbrains.yaml.psi.YAMLKeyValue; import org.jetbrains.yaml.psi.YAMLScalar; import org.w3c.dom.*; import org.xml.sax.SAXException; @@ -46,6 +33,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.*; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -54,6 +42,8 @@ * @author Daniel Espendiller */ public class TranslationUtil { + public static final ExtensionPointName TRANSLATION_PROVIDER = new ExtensionPointName<>("fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProvider"); + public static MethodMatcher.CallToSignature[] PHP_TRANSLATION_SIGNATURES = new MethodMatcher.CallToSignature[] { new MethodMatcher.CallToSignature("\\Symfony\\Component\\Translation\\TranslatorInterface", "trans"), new MethodMatcher.CallToSignature("\\Symfony\\Component\\Translation\\TranslatorInterface", "transChoice"), @@ -84,76 +74,14 @@ static public VirtualFile[] getDomainFilePsiElements(Project project, String dom return virtualFiles.toArray(new VirtualFile[virtualFiles.size()]); } - public static PsiElement[] getTranslationPsiElements(final Project project, final String translationKey, final String domain) { - List psiFoundElements = new ArrayList<>(); - List virtualFilesFound = new ArrayList<>(); - - // @TODO: completely remove this? support translation paths from service compiler - // search for available domain files - for(VirtualFile translationVirtualFile : getDomainFilePsiElements(project, domain)) { - if(translationVirtualFile.getFileType() != YAMLFileType.YML) { - continue; - } - - PsiFile psiFile = PsiElementUtils.virtualFileToPsiFile(project, translationVirtualFile); - if(psiFile instanceof YAMLFile) { - PsiElement yamlDocu = PsiTreeUtil.findChildOfType(psiFile, YAMLDocument.class); - if(yamlDocu != null) { - YAMLKeyValue goToPsi = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, translationKey.split("\\.")); - if(goToPsi != null) { - // multiline are line values are not resolve properly on psiElements use key as fallback target - PsiElement valuePsiElement = goToPsi.getValue(); - psiFoundElements.add(valuePsiElement != null ? valuePsiElement : goToPsi); - virtualFilesFound.add(translationVirtualFile); - } - } - } - } - - // collect on index - final YamlTranslationCollector translationCollector = (keyName, yamlKeyValue) -> { - if (keyName.equals(translationKey)) { - - // multiline "line values" are not resolve properly on psiElements use key as fallback target - PsiElement valuePsiElement = yamlKeyValue.getValue(); - psiFoundElements.add(valuePsiElement != null ? valuePsiElement : yamlKeyValue); - - return false; - } - - return true; - }; - - FileBasedIndex.getInstance().getFilesWithKey(TranslationStubIndex.KEY, new HashSet<>(Collections.singletonList(domain)), virtualFile -> { - // prevent duplicate targets and dont walk same file twice - if(virtualFilesFound.contains(virtualFile)) { - return true; - } + public static PsiElement[] getTranslationPsiElements(@NotNull Project project, @NotNull String translationKey, @NotNull String domain) { + Collection targets = new HashSet<>(); - PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); - if(psiFile == null) { - return true; - } - - if(psiFile instanceof YAMLFile) { - YamlTranslationVisitor.collectFileTranslations((YAMLFile) psiFile, translationCollector); - } else if(isSupportedXlfFile(psiFile)) { - // fine: xlf registered as XML file. try to find source value - psiFoundElements.addAll(getTargetForXlfAsXmlFile((XmlFile) psiFile, translationKey)); - } else if(("xlf".equalsIgnoreCase(virtualFile.getExtension()) || "xliff".equalsIgnoreCase(virtualFile.getExtension()))) { - // xlf are plain text because not supported by jetbrains - // for now we can only set file target - psiFoundElements.addAll(FileBasedIndex.getInstance() - .getValues(TranslationStubIndex.KEY, domain, GlobalSearchScope.filesScope(project, Collections.singletonList(virtualFile))).stream() - .filter(string -> string.contains(translationKey)).map(string -> psiFile) - .collect(Collectors.toList()) - ); - } + Arrays.stream(getTranslationProviders()) + .map(translationProvider -> translationProvider.getTranslationTargets(project, translationKey, domain)) + .forEach(targets::addAll); - return true; - }, GlobalSearchScope.allScope(project)); - - return psiFoundElements.toArray(new PsiElement[psiFoundElements.size()]); + return targets.toArray(new PsiElement[0]); } /** @@ -217,125 +145,80 @@ public static Collection getTargetForXlfAsXmlFile(@NotNull XmlFile x return psiElements; } - public static boolean hasDomain(Project project, String domainName) { - return TranslationIndex.getInstance(project).getTranslationMap().getDomainList().contains(domainName) || - FileBasedIndex.getInstance().getValues( - TranslationStubIndex.KEY, - domainName, - GlobalSearchScope.allScope(project) - ).size() > 0; + public static boolean hasDomain(@NotNull Project project, @NotNull String domainName) { + return Arrays.stream(getTranslationProviders()) + .anyMatch(translatorProvider -> translatorProvider.hasDomain(project, domainName)); } public static boolean hasTranslationKey(@NotNull Project project, String keyName, String domainName) { - if(!hasDomain(project, domainName)) { return false; } - Set domainMap = TranslationIndex.getInstance(project).getTranslationMap().getDomainMap(domainName); - if(domainMap != null && domainMap.contains(keyName)) { - return true; - } - - for(Set keys: FileBasedIndex.getInstance().getValues(TranslationStubIndex.KEY, domainName, GlobalSearchScope.allScope(project))){ - if(keys.contains(keyName)) { - return true; - } - } - - return false; + return Arrays.stream(getTranslationProviders()) + .anyMatch(translatorProvider -> translatorProvider.hasTranslationKey(project, keyName, domainName)); } @NotNull public static List getTranslationLookupElementsOnDomain(@NotNull Project project, @NotNull String domainName) { - - Set keySet = new HashSet<>(); - List> test = FileBasedIndex.getInstance().getValues(TranslationStubIndex.KEY, domainName, GlobalSearchScope.allScope(project)); - for(Set keys: test ){ - keySet.addAll(keys); - } - List lookupElements = new ArrayList<>(); - TranslationStringMap map = TranslationIndex.getInstance(project).getTranslationMap(); - Collection domainMap = map.getDomainMap(domainName); - - if(domainMap != null) { - - // php translation parser; are not weak and valid keys - for(String stringId : domainMap) { - lookupElements.add(new TranslatorLookupElement(stringId, domainName)); - } + Map keys = new HashMap<>(); - // attach weak translations keys on file index - for(String stringId : keySet) { - if(!domainMap.contains(stringId)) { - lookupElements.add(new TranslatorLookupElement(stringId, domainName, true)); + for (TranslatorProvider translationProvider : getTranslationProviders()) { + for (TranslatorProviderDict.TranslationKey translationKey : translationProvider.getTranslationsForDomain(project, domainName)) { + String domain = translationKey.getDomain(); + if (keys.containsKey(domain)) { + // weak to full + if(!keys.get(domain) && !translationKey.isWeak()) { + keys.put(domain, translationKey.isWeak()); + } + } else { + keys.put(domain, translationKey.isWeak()); } } - - return lookupElements; } // fallback on index - for(String stringId : keySet) { - lookupElements.add(new TranslatorLookupElement(stringId, domainName, true)); + for(Map.Entry entry : keys.entrySet()) { + lookupElements.add(new TranslatorLookupElement(entry.getKey(), domainName, entry.getValue())); } return lookupElements; } @NotNull - public static List getTranslationDomainLookupElements(Project project) { - - List lookupElements = new ArrayList<>(); - - // domains on complied file - TranslationStringMap map = TranslationIndex.getInstance(project).getTranslationMap(); - Set domainList = map.getDomainList(); - for(String domainKey : domainList) { - lookupElements.add(new TranslatorLookupElement(domainKey, domainKey)); - } - - // attach index domains as weak one - for(String domainKey: SymfonyProcessors.createResult(project, TranslationStubIndex.KEY, domainList)) { - if(!domainList.contains(domainKey)) { - lookupElements.add(new TranslatorLookupElement(domainKey, domainKey, true)); + public static List getTranslationDomainLookupElements(@NotNull Project project) { + Map domains = new HashMap<>(); + + for (TranslatorProvider translationProvider : getTranslationProviders()) { + for (TranslatorProviderDict.TranslationDomain translationDomain : translationProvider.getTranslationDomains(project)) { + String domain = translationDomain.getDomain(); + if (domains.containsKey(domain)) { + // weak to full + if(!domains.get(domain) && !translationDomain.isWeak()) { + domains.put(domain, translationDomain.isWeak()); + } + } else { + domains.put(domain, translationDomain.isWeak()); + } } } - return lookupElements; + return domains.entrySet().stream() + .map((Function, LookupElement>) entry -> + new TranslatorLookupElement(entry.getKey(), entry.getKey(), entry.getValue()) + ).collect(Collectors.toList()); } - public static List getDomainPsiFiles(final Project project, String domainName) { + public static List getDomainPsiFiles(@NotNull Project project, @NotNull String domainName) { + Set files = new HashSet<>(); - final List results = new ArrayList<>(); - final List uniqueFileList = new ArrayList<>(); - - // get translation files from compiler - for(VirtualFile virtualFile : TranslationUtil.getDomainFilePsiElements(project, domainName)) { - PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); - if(psiFile != null) { - uniqueFileList.add(virtualFile); - results.add(psiFile); - } + for (TranslatorProvider translationProvider : getTranslationProviders()) { + files.addAll(translationProvider.getDomainPsiFiles(project, domainName)); } - FileBasedIndex.getInstance().getFilesWithKey(TranslationStubIndex.KEY, new HashSet<>(Collections.singletonList(domainName)), virtualFile -> { - if(uniqueFileList.contains(virtualFile)) { - return true; - } - - PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); - if(psiFile != null) { - uniqueFileList.add(virtualFile); - results.add(psiFile); - } - - return true; - }, PhpIndex.getInstance(project).getSearchScope()); - - return results; + return new ArrayList<>(PsiElementUtils.convertVirtualFilesToPsiFiles(project, files)); } @NotNull @@ -414,6 +297,10 @@ public static Set getPlaceholderFromTranslation(@NotNull String text) { return placeholder; } + private static TranslatorProvider[] getTranslationProviders() { + return TRANSLATION_PROVIDER.getExtensions(); + } + /** * Extract common placeholder pattern from translation content */ diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/CompiledTranslatorProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/CompiledTranslatorProvider.java new file mode 100644 index 000000000..6aa1f459d --- /dev/null +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/CompiledTranslatorProvider.java @@ -0,0 +1,108 @@ +package fr.adrienbrault.idea.symfony2plugin.translation.provider; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.indexing.FileBasedIndex; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProviderDict; +import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TranslationStubIndex; +import fr.adrienbrault.idea.symfony2plugin.translation.TranslationIndex; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProvider; +import fr.adrienbrault.idea.symfony2plugin.translation.dict.TranslationUtil; +import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.yaml.YAMLFileType; +import org.jetbrains.yaml.YAMLUtil; +import org.jetbrains.yaml.psi.YAMLDocument; +import org.jetbrains.yaml.psi.YAMLFile; +import org.jetbrains.yaml.psi.YAMLKeyValue; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Extract translations out of compiled php file inside Symfony cache folder + * + * @author Daniel Espendiller + */ +public class CompiledTranslatorProvider implements TranslatorProvider { + @Override + public boolean hasTranslationKey(@NotNull Project project, @NotNull String keyName, @NotNull String domainName) { + for(Set keys: FileBasedIndex.getInstance().getValues(TranslationStubIndex.KEY, domainName, GlobalSearchScope.allScope(project))){ + if(keys.contains(keyName)) { + return true; + } + } + + return false; + } + + @Override + public boolean hasDomain(@NotNull Project project, @NotNull String domainName) { + return FileBasedIndex.getInstance().getValues( + TranslationStubIndex.KEY, + domainName, + GlobalSearchScope.allScope(project) + ).size() > 0; + } + + @NotNull + @Override + public Collection getTranslationDomains(@NotNull Project project) { + return TranslationIndex.getInstance(project) + .getTranslationMap() + .getDomainList() + .stream() + .map(TranslatorProviderDict.TranslationDomain::new) + .collect(Collectors.toList()); + } + + @NotNull + @Override + public Collection getTranslationTargets(@NotNull Project project, @NotNull String translationKey, @NotNull String domain) { + Collection psiFoundElements = new ArrayList<>(); + + // @TODO: completely remove this? support translation paths from service compiler + // search for available domain files + for(VirtualFile translationVirtualFile : TranslationUtil.getDomainFilePsiElements(project, domain)) { + if(translationVirtualFile.getFileType() != YAMLFileType.YML) { + continue; + } + + PsiFile psiFile = PsiElementUtils.virtualFileToPsiFile(project, translationVirtualFile); + if(psiFile instanceof YAMLFile) { + PsiElement yamlDocu = PsiTreeUtil.findChildOfType(psiFile, YAMLDocument.class); + if(yamlDocu != null) { + YAMLKeyValue goToPsi = YAMLUtil.getQualifiedKeyInFile((YAMLFile) psiFile, translationKey.split("\\.")); + if(goToPsi != null) { + // multiline are line values are not resolve properly on psiElements use key as fallback target + PsiElement valuePsiElement = goToPsi.getValue(); + psiFoundElements.add(valuePsiElement != null ? valuePsiElement : goToPsi); + } + } + } + } + + return psiFoundElements; + } + + @NotNull + @Override + public Collection getDomainPsiFiles(Project project, @NotNull String domainName) { + return Arrays.asList(TranslationUtil.getDomainFilePsiElements(project, domainName)); + } + + @NotNull + @Override + public Collection getTranslationsForDomain(@NotNull Project project, @NotNull String domainName) { + Set domainMap = TranslationIndex.getInstance(project).getTranslationMap().getDomainMap(domainName); + if (domainMap == null) { + return Collections.emptyList(); + } + + return domainMap.stream().map(TranslatorProviderDict.TranslationKey::new).collect(Collectors.toList()); + } +} diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/IndexTranslatorProvider.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/IndexTranslatorProvider.java new file mode 100644 index 000000000..87d75c66b --- /dev/null +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/translation/provider/IndexTranslatorProvider.java @@ -0,0 +1,127 @@ +package fr.adrienbrault.idea.symfony2plugin.translation.provider; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.xml.XmlFile; +import com.intellij.util.indexing.FileBasedIndex; +import com.jetbrains.php.PhpIndex; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProviderDict; +import fr.adrienbrault.idea.symfony2plugin.stubs.SymfonyProcessors; +import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TranslationStubIndex; +import fr.adrienbrault.idea.symfony2plugin.translation.TranslationIndex; +import fr.adrienbrault.idea.symfony2plugin.extension.TranslatorProvider; +import fr.adrienbrault.idea.symfony2plugin.translation.collector.YamlTranslationCollector; +import fr.adrienbrault.idea.symfony2plugin.translation.collector.YamlTranslationVisitor; +import fr.adrienbrault.idea.symfony2plugin.translation.dict.TranslationUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.yaml.psi.YAMLFile; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Use the internal index (yaml, xlf, ...) to provide translations + * + * @author Daniel Espendiller + */ +public class IndexTranslatorProvider implements TranslatorProvider { + @Override + public boolean hasTranslationKey(@NotNull Project project, @NotNull String keyName, @NotNull String domainName) { + Set domainMap = TranslationIndex.getInstance(project).getTranslationMap().getDomainMap(domainName); + return domainMap != null && domainMap.contains(keyName); + } + + @Override + public boolean hasDomain(@NotNull Project project, @NotNull String domainName) { + return TranslationIndex.getInstance(project).getTranslationMap().getDomainList().contains(domainName); + } + + @NotNull + @Override + public Collection getTranslationDomains(@NotNull Project project) { + return SymfonyProcessors + .createResult(project, TranslationStubIndex.KEY) + .stream() + .map(s -> new TranslatorProviderDict.TranslationDomain(s, true)) + .collect(Collectors.toList()); + } + + @NotNull + @Override + public Collection getTranslationTargets(@NotNull Project project, @NotNull String translationKey, @NotNull String domain) { + Collection psiFoundElements = new ArrayList<>(); + + // collect on index + final YamlTranslationCollector translationCollector = (keyName, yamlKeyValue) -> { + if (keyName.equals(translationKey)) { + + // multiline "line values" are not resolve properly on psiElements use key as fallback target + PsiElement valuePsiElement = yamlKeyValue.getValue(); + psiFoundElements.add(valuePsiElement != null ? valuePsiElement : yamlKeyValue); + + return false; + } + + return true; + }; + + FileBasedIndex.getInstance().getFilesWithKey(TranslationStubIndex.KEY, new HashSet<>(Collections.singletonList(domain)), virtualFile -> { + // prevent duplicate targets and dont walk same file twice + // if(virtualFilesFound.contains(virtualFile)) { + // return true; + // } + + PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); + if(psiFile == null) { + return true; + } + + if(psiFile instanceof YAMLFile) { + YamlTranslationVisitor.collectFileTranslations((YAMLFile) psiFile, translationCollector); + } else if(TranslationUtil.isSupportedXlfFile(psiFile)) { + // fine: xlf registered as XML file. try to find source value + psiFoundElements.addAll(TranslationUtil.getTargetForXlfAsXmlFile((XmlFile) psiFile, translationKey)); + } else if(("xlf".equalsIgnoreCase(virtualFile.getExtension()) || "xliff".equalsIgnoreCase(virtualFile.getExtension()))) { + // xlf are plain text because not supported by jetbrains + // for now we can only set file target + psiFoundElements.addAll(FileBasedIndex.getInstance() + .getValues(TranslationStubIndex.KEY, domain, GlobalSearchScope.filesScope(project, Collections.singletonList(virtualFile))).stream() + .filter(string -> string.contains(translationKey)).map(string -> psiFile) + .collect(Collectors.toList()) + ); + } + + return true; + }, GlobalSearchScope.allScope(project)); + + return psiFoundElements; + } + + @NotNull + @Override + public Collection getDomainPsiFiles(Project project, @NotNull String domainName) { + Collection targets = new HashSet<>(); + + FileBasedIndex.getInstance().getFilesWithKey(TranslationStubIndex.KEY, new HashSet<>(Collections.singletonList(domainName)), virtualFile -> { + targets.add(virtualFile); + return true; + }, PhpIndex.getInstance(project).getSearchScope()); + + return targets; + } + + @NotNull + @Override + public Collection getTranslationsForDomain(@NotNull Project project, @NotNull String domainName) { + return FileBasedIndex.getInstance() + .getValues(TranslationStubIndex.KEY, domainName, GlobalSearchScope.allScope(project)) + .stream() + .flatMap(Collection::stream) + .map(key -> new TranslatorProviderDict.TranslationKey(key, true)) + .collect(Collectors.toSet()); + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index b42988987..46cb7347c 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -541,6 +541,7 @@ + @@ -591,6 +592,9 @@ + + + com.jetbrains.twig