reengineer editor assistance
Tasks Left - language support (vue, js / ts, kotlin, php) - Intention system is bounded to Java ATM
This commit is contained in:
parent
0a8a92d3f8
commit
6e9d0671ca
@ -0,0 +1,16 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.completion;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||||
|
import com.intellij.codeInsight.completion.CompletionType;
|
||||||
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
|
import com.intellij.psi.PsiLiteralValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java specific completion contributor
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JavaCompletionContributor extends CompletionContributor {
|
||||||
|
public JavaCompletionContributor() {
|
||||||
|
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(PsiLiteralValue.class), new KeyCompletionProvider());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.completion;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||||
|
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||||
|
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.IconLoader;
|
||||||
|
import com.intellij.util.ProcessingContext;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.assistance.OptionalAssistance;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.Translation;
|
||||||
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides existing translation keys for code completion.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
class KeyCompletionProvider extends CompletionProvider<CompletionParameters> implements OptionalAssistance {
|
||||||
|
|
||||||
|
private static final Icon icon = IconLoader.getIcon("/icons/translate13.svg", KeyCompletionProvider.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||||
|
@NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||||
|
Project project = parameters.getOriginalFile().getProject();
|
||||||
|
|
||||||
|
if(!isAssistance(project)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectSettings settings = ProjectSettingsService.get(project).getState();
|
||||||
|
TranslationData data = InstanceManager.get(project).store().getData();
|
||||||
|
Set<KeyPath> fullKeys = data.getFullKeys();
|
||||||
|
|
||||||
|
for (KeyPath key : fullKeys) {
|
||||||
|
result.addElement(constructLookup(new Translation(key, data.getTranslation(key)), settings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LookupElement constructLookup(Translation translation, ProjectSettings settings) {
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(settings);
|
||||||
|
|
||||||
|
return LookupElementBuilder
|
||||||
|
.create(converter.toString(translation.getKey()))
|
||||||
|
.withTailText(" " + translation.getValue().get(settings.getPreviewLocale()), true)
|
||||||
|
.withIcon(icon);
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,16 @@
|
|||||||
package de.marhali.easyi18n.editor.kotlin;
|
package de.marhali.easyi18n.assistance.completion;
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||||
import com.intellij.codeInsight.completion.CompletionType;
|
import com.intellij.codeInsight.completion.CompletionType;
|
||||||
import com.intellij.patterns.PlatformPatterns;
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
|
|
||||||
import de.marhali.easyi18n.editor.KeyCompletionProvider;
|
|
||||||
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kotlin specific translation key completion contributor.
|
* Kotlin specific completion contributor.
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class KotlinKeyCompletionContributor extends CompletionContributor {
|
public class KtCompletionContributor extends CompletionContributor {
|
||||||
|
public KtCompletionContributor() {
|
||||||
public KotlinKeyCompletionContributor() {
|
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(KtLiteralStringTemplateEntry.class),
|
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(KtLiteralStringTemplateEntry.class),
|
||||||
new KeyCompletionProvider());
|
new KeyCompletionProvider());
|
||||||
}
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.documentation;
|
||||||
|
|
||||||
|
import com.intellij.lang.documentation.DocumentationMarkup;
|
||||||
|
import com.intellij.lang.documentation.DocumentationProvider;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.assistance.OptionalAssistance;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
import de.marhali.easyi18n.model.TranslationNode;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides locale values as documentation for translation keys.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
abstract class AbstractDocumentationProvider implements DocumentationProvider, OptionalAssistance {
|
||||||
|
|
||||||
|
private static final ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided key is a valid translation-key and generates the equivalent documentation for it.
|
||||||
|
* @param project Opened project
|
||||||
|
* @param key Designated translation key
|
||||||
|
* @return Generated documentation or null if not responsible
|
||||||
|
*/
|
||||||
|
protected @Nullable String generateDoc(@NotNull Project project, @Nullable String key) {
|
||||||
|
if(key == null || !isAssistance(project)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectSettings settings = ProjectSettingsService.get(project).getState();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(settings);
|
||||||
|
KeyPath path = converter.fromString(key);
|
||||||
|
|
||||||
|
// So we want to take care of context and pluralization here
|
||||||
|
// we should check the last key section for plural / context delims and if so provide all leafs within the last node
|
||||||
|
|
||||||
|
if(path.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslationData data = InstanceManager.get(project).store().getData();
|
||||||
|
String leaf = path.remove(path.size() - 1);
|
||||||
|
TranslationNode leafNode = data.getRootNode();
|
||||||
|
|
||||||
|
for(String section : path) {
|
||||||
|
leafNode = leafNode.getChildren().get(section);
|
||||||
|
if(leafNode == null) { // Cannot resolve last node before leaf
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> results = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// Filter results for matching leafs (contextual and pluralization support)
|
||||||
|
for (Map.Entry<String, TranslationNode> entry : leafNode.getChildren().entrySet()) {
|
||||||
|
if(entry.getKey().startsWith(leaf) && entry.getValue().isLeaf()) {
|
||||||
|
results.put(entry.getKey(), entry.getValue().getValue().get(settings.getPreviewLocale()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(results.isEmpty()) { // No results to show
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.append(DocumentationMarkup.DEFINITION_START);
|
||||||
|
builder.append(bundle.getString("documentation"));
|
||||||
|
builder.append(DocumentationMarkup.DEFINITION_END);
|
||||||
|
|
||||||
|
if(results.size() == 1) { // Single value
|
||||||
|
builder.append(DocumentationMarkup.CONTENT_START);
|
||||||
|
builder.append("<strong>").append(results.values().toArray()[0]).append("</strong>");
|
||||||
|
builder.append(DocumentationMarkup.CONTENT_END);
|
||||||
|
|
||||||
|
} else { // Pluralization | Contextual relevant values
|
||||||
|
builder.append(DocumentationMarkup.SECTIONS_START);
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : results.entrySet()) {
|
||||||
|
builder.append(DocumentationMarkup.SECTION_HEADER_START);
|
||||||
|
builder.append(entry.getKey()).append(":");
|
||||||
|
builder.append(DocumentationMarkup.SECTION_SEPARATOR);
|
||||||
|
builder.append("<p>");
|
||||||
|
builder.append("<strong>").append(entry.getValue()).append("</strong>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(DocumentationMarkup.SECTIONS_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.documentation;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import de.marhali.easyi18n.assistance.reference.PsiKeyReference;
|
||||||
|
import org.jetbrains.annotations.Nls;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language unspecific documentation provider. Every supported language should register an extension to this EP.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class CommonDocumentationProvider extends AbstractDocumentationProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable
|
||||||
|
@Nls String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
|
||||||
|
if(!(element instanceof PsiKeyReference.TranslationReference)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PsiKeyReference.TranslationReference keyReference = (PsiKeyReference.TranslationReference) element;
|
||||||
|
String value = keyReference.getName();
|
||||||
|
|
||||||
|
return generateDoc(element.getProject(), value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.folding;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.lang.folding.FoldingBuilderEx;
|
||||||
|
import com.intellij.openapi.editor.FoldingGroup;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.DataStore;
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.assistance.OptionalAssistance;
|
||||||
|
import de.marhali.easyi18n.model.TranslationValue;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language specific folding of translation key with preferred locale value.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
abstract class AbstractFoldingBuilder extends FoldingBuilderEx implements OptionalAssistance {
|
||||||
|
|
||||||
|
protected static final FoldingGroup group = FoldingGroup.newGroup("EasyI18n key folding");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the folding text for the provided text.
|
||||||
|
* @param project Opened project
|
||||||
|
* @param text Designated translation key
|
||||||
|
* @return Preferred locale value or null if translation does not exists
|
||||||
|
*/
|
||||||
|
protected @Nullable String getPlaceholderText(@NotNull Project project, @Nullable String text) {
|
||||||
|
if(text == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataStore store = InstanceManager.get(project).store();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(project);
|
||||||
|
TranslationValue localeValues = store.getData().getTranslation(converter.fromString(text));
|
||||||
|
|
||||||
|
if(localeValues == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String previewLocale = ProjectSettingsService.get(project).getState().getPreviewLocale();
|
||||||
|
return localeValues.get(previewLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.folding;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.lang.folding.FoldingDescriptor;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.util.TextRange;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiLiteralExpression;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.DataStore;
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java specific translation key folding.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JavaFoldingBuilder extends AbstractFoldingBuilder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FoldingDescriptor @NotNull [] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
|
||||||
|
List<FoldingDescriptor> descriptors = new ArrayList<>();
|
||||||
|
|
||||||
|
if(!isAssistance(root.getProject())) {
|
||||||
|
return FoldingDescriptor.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<PsiLiteralExpression> literalExpressions =
|
||||||
|
PsiTreeUtil.findChildrenOfType(root, PsiLiteralExpression.class);
|
||||||
|
|
||||||
|
DataStore store = InstanceManager.get(root.getProject()).store();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(root.getProject());
|
||||||
|
|
||||||
|
for(final PsiLiteralExpression literalExpression : literalExpressions) {
|
||||||
|
String value = literalExpression.getValue() instanceof String
|
||||||
|
? (String) literalExpression.getValue() : null;
|
||||||
|
|
||||||
|
if(value == null || store.getData().getTranslation(converter.fromString(value)) == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextRange range = literalExpression.getTextRange();
|
||||||
|
FoldingDescriptor descriptor = new FoldingDescriptor(literalExpression.getNode(),
|
||||||
|
new TextRange(range.getStartOffset() + 1, range.getEndOffset() - 1), group);
|
||||||
|
|
||||||
|
descriptors.add(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptors.toArray(new FoldingDescriptor[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getPlaceholderText(@NotNull ASTNode node) {
|
||||||
|
PsiLiteralExpression literalExpression = node.getPsi(PsiLiteralExpression.class);
|
||||||
|
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
|
||||||
|
return getPlaceholderText(literalExpression.getProject(), value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.folding;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.lang.folding.FoldingDescriptor;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.util.TextRange;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.DataStore;
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.psi.KtStringTemplateEntry;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin specific translation-key folding.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class KtFoldingBuilder extends AbstractFoldingBuilder {
|
||||||
|
@Override
|
||||||
|
public FoldingDescriptor @NotNull [] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
|
||||||
|
List<FoldingDescriptor> descriptors = new ArrayList<>();
|
||||||
|
|
||||||
|
if(!isAssistance(root.getProject())) {
|
||||||
|
return FoldingDescriptor.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<KtStringTemplateEntry> templateEntries =
|
||||||
|
PsiTreeUtil.findChildrenOfType(root, KtStringTemplateEntry.class);
|
||||||
|
|
||||||
|
DataStore store = InstanceManager.get(root.getProject()).store();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(root.getProject());
|
||||||
|
|
||||||
|
for (KtStringTemplateEntry templateEntry : templateEntries) {
|
||||||
|
String value = templateEntry.getText();
|
||||||
|
|
||||||
|
if(value == null || store.getData().getTranslation(converter.fromString(value)) == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextRange range = templateEntry.getTextRange();
|
||||||
|
FoldingDescriptor descriptor = new FoldingDescriptor(templateEntry.getNode(),
|
||||||
|
new TextRange(range.getStartOffset(), range.getEndOffset()), group);
|
||||||
|
|
||||||
|
descriptors.add(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptors.toArray(new FoldingDescriptor[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getPlaceholderText(@NotNull ASTNode node) {
|
||||||
|
KtStringTemplateEntry templateEntry = node.getPsi(KtStringTemplateEntry.class);
|
||||||
|
return getPlaceholderText(templateEntry.getProject(), templateEntry.getText());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.intention;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.intention.FileModifier;
|
||||||
|
import com.intellij.openapi.command.WriteCommandAction;
|
||||||
|
import com.intellij.openapi.editor.Caret;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.intellij.psi.util.PsiEditorUtil;
|
||||||
|
|
||||||
|
import com.siyeh.ipp.base.MutablyNamedIntention;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.assistance.OptionalAssistance;
|
||||||
|
import de.marhali.easyi18n.dialog.AddDialog;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intention for extracting a translation. Either by translation key or preferred locale value
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
abstract class AbstractExtractIntention extends MutablyNamedIntention implements OptionalAssistance {
|
||||||
|
|
||||||
|
protected static final ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String getFamilyName() {
|
||||||
|
return "EasyI18n";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startInWriteAction() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @NotNull String getTextForElement(@NotNull Project project, @Nullable String key) {
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(project);
|
||||||
|
TranslationData data = InstanceManager.get(project).store().getData();
|
||||||
|
|
||||||
|
return key != null && data.getTranslation(converter.fromString(key)) != null
|
||||||
|
? bundle.getString("action.edit")
|
||||||
|
: bundle.getString("action.extract");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void extractTranslation(@NotNull Project project, @NotNull String text, PsiElement psi) {
|
||||||
|
ProjectSettings settings = ProjectSettingsService.get(project).getState();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(settings);
|
||||||
|
|
||||||
|
// Extract translation key
|
||||||
|
// We assume that a text is a translation-key if it contains section delimiters and does not end with them
|
||||||
|
if(text.contains(settings.getSectionDelimiter()) && !text.endsWith(settings.getSectionDelimiter())) {
|
||||||
|
new AddDialog(project, converter.fromString(text), null).showAndHandle();
|
||||||
|
|
||||||
|
} else { // Extract translation value (here preview locale value)
|
||||||
|
AddDialog dialog = new AddDialog(project, new KeyPath(), text);
|
||||||
|
|
||||||
|
// Replace editor caret with chosen translation key
|
||||||
|
dialog.registerCallback(translationUpdate -> {
|
||||||
|
Editor editor = PsiEditorUtil.findEditor(psi);
|
||||||
|
|
||||||
|
if(editor != null) {
|
||||||
|
Document doc = editor.getDocument();
|
||||||
|
Caret caret = editor.getCaretModel().getPrimaryCaret();
|
||||||
|
int start = psi.getTextOffset() + 1;
|
||||||
|
int end = start + text.length();
|
||||||
|
|
||||||
|
WriteCommandAction.runWriteCommandAction(project, () ->
|
||||||
|
doc.replaceString(start, end, converter.toString(translationUpdate.getChange().getKey())));
|
||||||
|
|
||||||
|
caret.removeSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.showAndHandle();;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.intention;
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.util.IntentionName;
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java specific translation key intention.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JavaExtractIntention extends AbstractExtractIntention {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @IntentionName String getTextForElement(PsiElement element) {
|
||||||
|
return getTextForElement(element.getProject(), (String) ((PsiLiteralExpression) element).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processIntention(@NotNull PsiElement element) {
|
||||||
|
System.out.println("proci2");
|
||||||
|
if(!(element instanceof PsiLiteralExpression)
|
||||||
|
|| !(((PsiLiteralExpression) element).getValue() instanceof String)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractTranslation(element.getProject(), (String) ((PsiLiteralExpression) element).getValue(), element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull PsiElementPredicate getElementPredicate() {
|
||||||
|
System.out.println("predi2");
|
||||||
|
return element -> element instanceof PsiLiteralExpression;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.intention;
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.util.IntentionName;
|
||||||
|
import com.intellij.lang.javascript.psi.JSLiteralExpression;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JavaScript specific translation key intention.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
// TODO: current implementation does not support other languages than Java
|
||||||
|
public class JsExtractIntention extends AbstractExtractIntention {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String getFamilyName() {
|
||||||
|
return "JavaScript";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @IntentionName String getTextForElement(PsiElement element) {
|
||||||
|
return "HILFE";
|
||||||
|
//return getTextForElement(element.getProject(), ((JSLiteralExpression) element).getStringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processIntention(@NotNull PsiElement element) {
|
||||||
|
if(!(element instanceof JSLiteralExpression) || ((JSLiteralExpression) element).getStringValue() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractTranslation(element.getProject(), ((JSLiteralExpression) element).getStringValue(), element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull PsiElementPredicate getElementPredicate() {
|
||||||
|
return element -> true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.intention;
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.util.IntentionName;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
||||||
|
import org.jetbrains.kotlin.psi.KtStringTemplateExpression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin specific translation key intention.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
// TODO: kotlin impl does not work - no action
|
||||||
|
public class KtExtractIntention extends AbstractExtractIntention {
|
||||||
|
@Override
|
||||||
|
protected @IntentionName String getTextForElement(PsiElement element) {
|
||||||
|
return "hallo";
|
||||||
|
//return getTextForElement(element.getProject(), element.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processIntention(@NotNull PsiElement element) {
|
||||||
|
System.out.println("Hallo");
|
||||||
|
|
||||||
|
if(!(element instanceof KtStringTemplateExpression)) {
|
||||||
|
System.out.println(element.getClass());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("hallo");
|
||||||
|
|
||||||
|
extractTranslation(element.getProject() , element.getText(), element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull PsiElementPredicate getElementPredicate() {
|
||||||
|
System.out.println("predi");
|
||||||
|
return element -> element instanceof KtLiteralStringTemplateEntry;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.reference;
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiReference;
|
||||||
|
import com.intellij.psi.PsiReferenceContributor;
|
||||||
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.assistance.OptionalAssistance;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.Translation;
|
||||||
|
import de.marhali.easyi18n.model.TranslationValue;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
|
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language specific translation key reference contributor.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
abstract class AbstractKeyReferenceContributor extends PsiReferenceContributor implements OptionalAssistance {
|
||||||
|
/**
|
||||||
|
* Searches for relevant translation-key references
|
||||||
|
* @param project Opened project
|
||||||
|
* @param element Targeted element
|
||||||
|
* @param text Designated translation key
|
||||||
|
* @return Matched translation-key reference(s)
|
||||||
|
*/
|
||||||
|
protected @NotNull PsiReference[] getReferences(
|
||||||
|
@NotNull Project project, @NotNull PsiElement element, @Nullable String text) {
|
||||||
|
|
||||||
|
if(text == null || text.isEmpty() || !isAssistance(project)) {
|
||||||
|
return PsiReference.EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectSettings settings = ProjectSettingsService.get(project).getState();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(settings);
|
||||||
|
|
||||||
|
// TODO: We should provide multiple references if not a leaf node was provided (contextual / plurals support)
|
||||||
|
|
||||||
|
KeyPath path = converter.fromString(text);
|
||||||
|
TranslationValue values = InstanceManager.get(project).store().getData().getTranslation(path);
|
||||||
|
|
||||||
|
if(values == null) { // We only reference valid and existing translations
|
||||||
|
return PsiReference.EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PsiReference[] {
|
||||||
|
new PsiKeyReference(converter, new Translation(path, values), element)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.reference;
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
|
||||||
|
import com.intellij.util.ProcessingContext;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java specific key reference binding.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JavaKeyReferenceContributor extends AbstractKeyReferenceContributor {
|
||||||
|
|
||||||
|
// TODO: why not PsiLiteralExpression?
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
||||||
|
registrar.registerReferenceProvider(
|
||||||
|
PlatformPatterns.psiElement(PsiLiteralValue.class),
|
||||||
|
getProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiReferenceProvider getProvider() {
|
||||||
|
return new PsiReferenceProvider() {
|
||||||
|
@Override
|
||||||
|
public PsiReference @NotNull [] getReferencesByElement(
|
||||||
|
@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||||
|
|
||||||
|
Project project = element.getProject();
|
||||||
|
PsiLiteralValue literalValue = (PsiLiteralValue) element;
|
||||||
|
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
||||||
|
|
||||||
|
return getReferences(project, element, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.reference;
|
||||||
|
|
||||||
|
import com.intellij.lang.javascript.psi.JSLiteralExpression;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiReference;
|
||||||
|
import com.intellij.psi.PsiReferenceProvider;
|
||||||
|
import com.intellij.psi.PsiReferenceRegistrar;
|
||||||
|
import com.intellij.util.ProcessingContext;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JavaScript specific translation-key reference binding.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JsKeyReferenceContributor extends AbstractKeyReferenceContributor {
|
||||||
|
@Override
|
||||||
|
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
||||||
|
registrar.registerReferenceProvider(
|
||||||
|
PlatformPatterns.psiElement(JSLiteralExpression.class),
|
||||||
|
getProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiReferenceProvider getProvider() {
|
||||||
|
return new PsiReferenceProvider() {
|
||||||
|
@Override
|
||||||
|
public PsiReference @NotNull [] getReferencesByElement(
|
||||||
|
@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||||
|
|
||||||
|
Project project = element.getProject();
|
||||||
|
JSLiteralExpression literalExpression = (JSLiteralExpression) element;
|
||||||
|
String value = literalExpression.getStringValue();
|
||||||
|
|
||||||
|
return getReferences(project, element, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.reference;
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiReference;
|
||||||
|
import com.intellij.psi.PsiReferenceProvider;
|
||||||
|
import com.intellij.psi.PsiReferenceRegistrar;
|
||||||
|
import com.intellij.util.ProcessingContext;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
||||||
|
import org.jetbrains.kotlin.psi.KtStringTemplateExpression;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin specific translation-key reference binding.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class KtKeyReferenceContributor extends AbstractKeyReferenceContributor {
|
||||||
|
@Override
|
||||||
|
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
||||||
|
registrar.registerReferenceProvider(
|
||||||
|
PlatformPatterns.psiElement().inside(KtStringTemplateExpression.class),
|
||||||
|
getProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiReferenceProvider getProvider() {
|
||||||
|
return new PsiReferenceProvider() {
|
||||||
|
@Override
|
||||||
|
public PsiReference @NotNull [] getReferencesByElement(
|
||||||
|
@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||||
|
|
||||||
|
Optional<PsiElement> targetElement = Arrays.stream(element.getChildren()).filter(child ->
|
||||||
|
child instanceof KtLiteralStringTemplateEntry).findAny();
|
||||||
|
|
||||||
|
if(targetElement.isEmpty()) {
|
||||||
|
return PsiReference.EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getReferences(element.getProject(), element, targetElement.get().getText());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package de.marhali.easyi18n.assistance.reference;
|
||||||
|
|
||||||
|
import com.intellij.navigation.ItemPresentation;
|
||||||
|
import com.intellij.openapi.util.TextRange;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiReferenceBase;
|
||||||
|
import com.intellij.psi.SyntheticElement;
|
||||||
|
import com.intellij.psi.impl.FakePsiElement;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.dialog.AddDialog;
|
||||||
|
import de.marhali.easyi18n.dialog.EditDialog;
|
||||||
|
import de.marhali.easyi18n.model.Translation;
|
||||||
|
import de.marhali.easyi18n.util.KeyPathConverter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* References translation keys inside editor with corresponding {@link EditDialog} / {@link AddDialog}.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class PsiKeyReference extends PsiReferenceBase<PsiElement> {
|
||||||
|
|
||||||
|
private final @NotNull Translation translation;
|
||||||
|
private final @NotNull KeyPathConverter converter;
|
||||||
|
|
||||||
|
protected PsiKeyReference(
|
||||||
|
@NotNull KeyPathConverter converter, @NotNull Translation translation, @NotNull PsiElement element) {
|
||||||
|
|
||||||
|
super(element, true);
|
||||||
|
this.translation = translation;
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull String getKey() {
|
||||||
|
return converter.toString(translation.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable PsiElement resolve() {
|
||||||
|
return new TranslationReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TranslationReference extends FakePsiElement implements SyntheticElement {
|
||||||
|
@Override
|
||||||
|
public PsiElement getParent() {
|
||||||
|
return myElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void navigate(boolean requestFocus) {
|
||||||
|
new EditDialog(getProject(), translation).showAndHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPresentableText() {
|
||||||
|
return getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable TextRange getTextRange() {
|
||||||
|
TextRange rangeInElement = getRangeInElement();
|
||||||
|
TextRange elementRange = myElement.getTextRange();
|
||||||
|
return elementRange != null ? rangeInElement.shiftRight(elementRange.getStartOffset()) : rangeInElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor;
|
|
||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
|
||||||
import com.intellij.lang.annotation.HighlightSeverity;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.model.KeyPath;
|
|
||||||
import de.marhali.easyi18n.model.KeyPathConverter;
|
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Superclass for managing key annotations.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class KeyAnnotator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds annotations for i18n keys with content preview for preferred locale.
|
|
||||||
* @param key I18n key extracted by psi element
|
|
||||||
* @param project Project instance
|
|
||||||
* @param holder Annotation holder
|
|
||||||
*/
|
|
||||||
protected void annotate(@NotNull String key, @NotNull Project project, @NotNull AnnotationHolder holder) {
|
|
||||||
// Do not annotate keys if service is disabled
|
|
||||||
if(!ProjectSettingsService.get(project).getState().isAssistance()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProjectSettings state = ProjectSettingsService.get(project).getState();
|
|
||||||
//String pathPrefix = state.getPathPrefix();
|
|
||||||
// TODO: Path prefix removal
|
|
||||||
String pathPrefix = "";
|
|
||||||
String previewLocale = state.getPreviewLocale();
|
|
||||||
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(project);
|
|
||||||
|
|
||||||
String searchKey = key.length() >= pathPrefix.length()
|
|
||||||
? key.substring(pathPrefix.length())
|
|
||||||
: key;
|
|
||||||
|
|
||||||
if(searchKey.startsWith(KeyPath.DELIMITER)) {
|
|
||||||
searchKey = searchKey.substring(KeyPath.DELIMITER.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslationNode node = InstanceManager.get(project).store().getData().getNode(converter.split(searchKey));
|
|
||||||
|
|
||||||
if(node == null) { // Unknown translation. Just ignore it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String tooltip = node.isLeaf() ? "I18n(" + previewLocale + ": " + node.getValue().get(previewLocale) + ")"
|
|
||||||
: "I18n ([])";
|
|
||||||
|
|
||||||
holder.newAnnotation(HighlightSeverity.INFORMATION, tooltip).create();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor;
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.*;
|
|
||||||
import com.intellij.codeInsight.lookup.*;
|
|
||||||
import com.intellij.icons.AllIcons;
|
|
||||||
import com.intellij.openapi.project.*;
|
|
||||||
import com.intellij.util.*;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.DataStore;
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.model.KeyPath;
|
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
|
||||||
import org.jetbrains.annotations.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* I18n translation key completion provider.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class KeyCompletionProvider extends CompletionProvider<CompletionParameters> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
|
||||||
@NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
|
||||||
|
|
||||||
Project project = parameters.getOriginalFile().getProject();
|
|
||||||
|
|
||||||
// Do not annotate keys if service is disabled
|
|
||||||
if(!ProjectSettingsService.get(project).getState().isAssistance()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(project).store();
|
|
||||||
|
|
||||||
String previewLocale = ProjectSettingsService.get(project).getState().getPreviewLocale();
|
|
||||||
//String pathPrefix = ProjectSettingsService.get(project).getState().getPathPrefix();
|
|
||||||
// TODO: Path prefix removal
|
|
||||||
String pathPrefix = "";
|
|
||||||
|
|
||||||
if(pathPrefix.length() > 0 && !pathPrefix.endsWith(KeyPath.DELIMITER)) {
|
|
||||||
pathPrefix += KeyPath.DELIMITER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<KeyPath> fullKeys = store.getData().getFullKeys();
|
|
||||||
|
|
||||||
for(KeyPath currentKey : fullKeys) {
|
|
||||||
result.addElement(createElement(
|
|
||||||
pathPrefix,
|
|
||||||
currentKey,
|
|
||||||
previewLocale,
|
|
||||||
Objects.requireNonNull(store.getData().getTranslation(currentKey))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LookupElement createElement(String prefix, KeyPath path, String locale, Translation translation) {
|
|
||||||
return LookupElementBuilder.create(prefix + path.toSimpleString())
|
|
||||||
.withIcon(AllIcons.Actions.PreserveCaseHover)
|
|
||||||
.appendTailText(" I18n(" + locale + ": " + translation.get(locale) + ")", true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor;
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.TextRange;
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
import com.intellij.psi.impl.FakePsiElement;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.dialog.AddDialog;
|
|
||||||
import de.marhali.easyi18n.dialog.EditDialog;
|
|
||||||
import de.marhali.easyi18n.model.KeyPath;
|
|
||||||
import de.marhali.easyi18n.model.KeyPathConverter;
|
|
||||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to declaration reference for i18n keys.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class KeyReference extends PsiReferenceBase<PsiElement> {
|
|
||||||
|
|
||||||
@Nullable private final String myKey;
|
|
||||||
|
|
||||||
public KeyReference(@NotNull final PsiElement element) {
|
|
||||||
this(element, (String)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyReference(@NotNull final PsiElement element, @Nullable final String myKey) {
|
|
||||||
super(element, true);
|
|
||||||
this.myKey = myKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyReference(@NotNull final PsiElement element, @NotNull TextRange textRange) {
|
|
||||||
this(element, textRange, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyReference(@NotNull PsiElement element, TextRange textRange, @Nullable String myKey) {
|
|
||||||
super(element, textRange, true);
|
|
||||||
this.myKey = myKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable PsiElement resolve() {
|
|
||||||
return new TranslationKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return myKey != null ? myKey : getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TranslationKey extends FakePsiElement implements SyntheticElement {
|
|
||||||
@Override
|
|
||||||
public PsiElement getParent() {
|
|
||||||
return myElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void navigate(boolean requestFocus) {
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(getProject());
|
|
||||||
KeyPath path = converter.split(getKey());
|
|
||||||
Translation translation = InstanceManager.get(getProject()).store().getData().getTranslation(path);
|
|
||||||
|
|
||||||
if(translation != null) {
|
|
||||||
new EditDialog(getProject(), new KeyedTranslation(path, translation)).showAndHandle();
|
|
||||||
} else {
|
|
||||||
new AddDialog(getProject(), path).showAndHandle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPresentableText() {
|
|
||||||
return getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable TextRange getTextRange() {
|
|
||||||
final TextRange rangeInElement = getRangeInElement();
|
|
||||||
final TextRange elementRange = myElement.getTextRange();
|
|
||||||
return elementRange != null ? rangeInElement.shiftRight(elementRange.getStartOffset()) : rangeInElement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isReferencable(String value) {
|
|
||||||
return value.matches("^[^\\s:/]+$");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.generic;
|
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
|
||||||
import com.intellij.lang.folding.FoldingBuilderEx;
|
|
||||||
import com.intellij.lang.folding.FoldingDescriptor;
|
|
||||||
import com.intellij.openapi.editor.Document;
|
|
||||||
import com.intellij.openapi.util.TextRange;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.psi.PsiLiteralValue;
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.DataStore;
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.model.KeyPathConverter;
|
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation key folding with actual value based on i18n instance.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class GenericFoldingBuilder extends FoldingBuilderEx {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FoldingDescriptor @NotNull [] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
|
|
||||||
Collection<PsiLiteralValue> literalValues = PsiTreeUtil.findChildrenOfType(root, PsiLiteralValue.class);
|
|
||||||
List<FoldingDescriptor> descriptors = new ArrayList<>();
|
|
||||||
|
|
||||||
if(!ProjectSettingsService.get(root.getProject()).getState().isAssistance()) {
|
|
||||||
return FoldingDescriptor.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(root.getProject()).store();
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(root.getProject());
|
|
||||||
|
|
||||||
for(final PsiLiteralValue literalValue : literalValues) {
|
|
||||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
|
||||||
|
|
||||||
// Undefined string literal or not a translation
|
|
||||||
if(value == null || store.getData().getTranslation(converter.split(value)) == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptors.add(new FoldingDescriptor(literalValue.getNode(),
|
|
||||||
new TextRange(literalValue.getTextRange().getStartOffset() + 1,
|
|
||||||
literalValue.getTextRange().getEndOffset() - 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return descriptors.toArray(new FoldingDescriptor[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public String getPlaceholderText(@NotNull ASTNode node) {
|
|
||||||
PsiLiteralValue literalValue = node.getPsi(PsiLiteralValue.class);
|
|
||||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
|
||||||
|
|
||||||
if(value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(literalValue.getProject()).store();
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(literalValue.getProject());
|
|
||||||
|
|
||||||
Translation translation = store.getData().getTranslation(converter.split(value));
|
|
||||||
|
|
||||||
if(translation == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String previewLocale = ProjectSettingsService.get(literalValue.getProject()).getState().getPreviewLocale();
|
|
||||||
|
|
||||||
return translation.get(previewLocale);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.generic;
|
|
||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
|
||||||
import com.intellij.lang.annotation.Annotator;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.psi.PsiLiteralValue;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.editor.KeyAnnotator;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation key annotator for generic languages which support {@link PsiLiteralValue}.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class GenericKeyAnnotator extends KeyAnnotator implements Annotator {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
|
||||||
if(!(element instanceof PsiLiteralValue)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiLiteralValue literalValue = (PsiLiteralValue) element;
|
|
||||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
|
||||||
|
|
||||||
if(value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
annotate(value, element.getProject(), holder);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.generic;
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
|
||||||
import com.intellij.codeInsight.completion.CompletionType;
|
|
||||||
import com.intellij.patterns.*;
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
import com.intellij.psi.xml.*;
|
|
||||||
import de.marhali.easyi18n.editor.KeyCompletionProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation key completion for generic languages which support {@link PsiLiteralValue}.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class GenericKeyCompletionContributor extends CompletionContributor {
|
|
||||||
|
|
||||||
public GenericKeyCompletionContributor() {
|
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(PlainTextTokenTypes.PLAIN_TEXT),
|
|
||||||
new KeyCompletionProvider());
|
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(XmlElement.class),
|
|
||||||
new KeyCompletionProvider());
|
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(PsiLiteralValue.class),
|
|
||||||
new KeyCompletionProvider());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.generic;
|
|
||||||
|
|
||||||
import com.intellij.patterns.PlatformPatterns;
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
import com.intellij.util.ProcessingContext;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.editor.KeyReference;
|
|
||||||
import de.marhali.easyi18n.model.KeyPathConverter;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic translation key reference contributor.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class GenericKeyReferenceContributor extends PsiReferenceContributor {
|
|
||||||
@Override
|
|
||||||
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralValue.class), getProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
private PsiReferenceProvider getProvider() {
|
|
||||||
return new PsiReferenceProvider() {
|
|
||||||
@Override
|
|
||||||
public PsiReference @NotNull [] getReferencesByElement(
|
|
||||||
@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
|
||||||
|
|
||||||
PsiLiteralValue literalValue = (PsiLiteralValue) element;
|
|
||||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
|
||||||
|
|
||||||
if(value == null) {
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not reference keys if service is disabled
|
|
||||||
if(!ProjectSettingsService.get(element.getProject()).getState().isAssistance()) {
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(element.getProject());
|
|
||||||
|
|
||||||
if(InstanceManager.get(element.getProject()).store().getData().getTranslation(converter.split(value)) == null) {
|
|
||||||
if(!KeyReference.isReferencable(value)) { // Creation policy
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PsiReference[] { new KeyReference(element, value) };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.kotlin;
|
|
||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
|
||||||
import com.intellij.lang.annotation.Annotator;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.editor.KeyAnnotator;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kotlin specific translation key annotator
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class KotlinKeyAnnotator extends KeyAnnotator implements Annotator {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
|
||||||
if(!(element instanceof KtLiteralStringTemplateEntry)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = element.getText();
|
|
||||||
|
|
||||||
if(value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
annotate(value, element.getProject(), holder);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package de.marhali.easyi18n.editor.kotlin;
|
|
||||||
|
|
||||||
import com.intellij.patterns.PlatformPatterns;
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
|
|
||||||
import com.intellij.util.ProcessingContext;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
|
||||||
import de.marhali.easyi18n.editor.KeyReference;
|
|
||||||
import de.marhali.easyi18n.model.KeyPathConverter;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettingsService;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry;
|
|
||||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kotlin translation key reference contributor.
|
|
||||||
* @author marhali
|
|
||||||
*/
|
|
||||||
public class KotlinKeyReferenceContributor extends PsiReferenceContributor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement().inside(KtStringTemplateExpression.class), getProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
private PsiReferenceProvider getProvider() {
|
|
||||||
return new PsiReferenceProvider() {
|
|
||||||
@Override
|
|
||||||
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
|
||||||
String value = null;
|
|
||||||
|
|
||||||
for (PsiElement child : element.getChildren()) {
|
|
||||||
if(child instanceof KtLiteralStringTemplateEntry) {
|
|
||||||
value = child.getText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(value == null) {
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not reference keys if service is disabled
|
|
||||||
if(!ProjectSettingsService.get(element.getProject()).getState().isAssistance()) {
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPathConverter converter = new KeyPathConverter(element.getProject());
|
|
||||||
|
|
||||||
if(InstanceManager.get(element.getProject()).store().getData().getNode(converter.split(value)) == null) {
|
|
||||||
return PsiReference.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PsiReference[] { new KeyReference(element, value) };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,27 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<lang.foldingBuilder language="JAVA" implementationClass="de.marhali.easyi18n.editor.generic.GenericFoldingBuilder" />
|
<intentionAction>
|
||||||
|
<className>de.marhali.easyi18n.assistance.intention.JavaExtractIntention</className>
|
||||||
|
</intentionAction>
|
||||||
|
|
||||||
|
<psi.referenceContributor
|
||||||
|
language="JAVA"
|
||||||
|
implementation="de.marhali.easyi18n.assistance.reference.JavaKeyReferenceContributor"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<lang.foldingBuilder
|
||||||
|
language="JAVA"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.folding.JavaFoldingBuilder"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<lang.documentationProvider
|
||||||
|
language="JAVA"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.documentation.CommonDocumentationProvider"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<completion.contributor
|
||||||
|
language="JAVA"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.completion.JavaCompletionContributor"
|
||||||
|
/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
@ -1,6 +1,17 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<lang.foldingBuilder language="JavaScript" implementationClass="de.marhali.easyi18n.editor.generic.GenericFoldingBuilder" />
|
<psi.referenceContributor
|
||||||
<lang.foldingBuilder language="TypeScript" implementationClass="de.marhali.easyi18n.editor.generic.GenericFoldingBuilder" />
|
language="JavaScript"
|
||||||
|
implementation="de.marhali.easyi18n.assistance.reference.JsKeyReferenceContributor"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<lang.documentationProvider
|
||||||
|
language="JavaScript"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.documentation.CommonDocumentationProvider"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<intentionAction>
|
||||||
|
<className>de.marhali.easyi18n.assistance.intention.JsExtractIntention</className>
|
||||||
|
</intentionAction>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
@ -1,11 +1,27 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<annotator language="kotlin" implementationClass="de.marhali.easyi18n.editor.kotlin.KotlinKeyAnnotator" />
|
<intentionAction>
|
||||||
|
<className>de.marhali.easyi18n.assistance.intention.KtExtractIntention</className>
|
||||||
|
</intentionAction>
|
||||||
|
|
||||||
<completion.contributor language="kotlin"
|
<psi.referenceContributor
|
||||||
implementationClass="de.marhali.easyi18n.editor.kotlin.KotlinKeyCompletionContributor" />
|
language="kotlin"
|
||||||
|
implementation="de.marhali.easyi18n.assistance.reference.KtKeyReferenceContributor"
|
||||||
|
/>
|
||||||
|
|
||||||
<psi.referenceContributor language="kotlin"
|
<lang.documentationProvider
|
||||||
implementation="de.marhali.easyi18n.editor.kotlin.KotlinKeyReferenceContributor" />
|
language="kotlin"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.documentation.CommonDocumentationProvider"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<completion.contributor
|
||||||
|
language="kotlin"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.completion.KtCompletionContributor"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<lang.foldingBuilder
|
||||||
|
language="kotlin"
|
||||||
|
implementationClass="de.marhali.easyi18n.assistance.folding.KtFoldingBuilder"
|
||||||
|
/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
@ -34,15 +34,6 @@
|
|||||||
id="de.marhali.easyi18n.service.AppSettingsConfigurable"
|
id="de.marhali.easyi18n.service.AppSettingsConfigurable"
|
||||||
displayName="Easy I18n" nonDefaultProject="true"/>
|
displayName="Easy I18n" nonDefaultProject="true"/>
|
||||||
|
|
||||||
<completion.contributor language="any"
|
|
||||||
implementationClass="de.marhali.easyi18n.editor.generic.GenericKeyCompletionContributor"/>
|
|
||||||
|
|
||||||
<annotator language=""
|
|
||||||
implementationClass="de.marhali.easyi18n.editor.generic.GenericKeyAnnotator"/>
|
|
||||||
|
|
||||||
<psi.referenceContributor
|
|
||||||
implementation="de.marhali.easyi18n.editor.generic.GenericKeyReferenceContributor"/>
|
|
||||||
|
|
||||||
<notificationGroup displayType="BALLOON" id="Easy I18n Notification Group"/>
|
<notificationGroup displayType="BALLOON" id="Easy I18n Notification Group"/>
|
||||||
|
|
||||||
<errorHandler implementation="de.marhali.easyi18n.service.ErrorReportHandler"/>
|
<errorHandler implementation="de.marhali.easyi18n.service.ErrorReportHandler"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user