mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
allow same-named template macros for different languages (IDEA-145973)
This commit is contained in:
@@ -19,7 +19,7 @@ public class MacroParserTest extends LightIdeaTestCase {
|
||||
Expression e = MacroParser.parse(" variableOfType( \"java.util.Collection\" ) ");
|
||||
assertTrue(e instanceof MacroCallNode);
|
||||
MacroCallNode n = (MacroCallNode) e;
|
||||
assertTrue(n.getMacro() instanceof VariableOfTypeMacro);
|
||||
assertTrue(n.getMacro(new TemplateContextType[0]) instanceof VariableOfTypeMacro);
|
||||
Expression[] parameters = n.getParameters();
|
||||
assertEquals(1, parameters.length);
|
||||
assertTrue(parameters [0] instanceof ConstantNode);
|
||||
@@ -46,7 +46,7 @@ public class MacroParserTest extends LightIdeaTestCase {
|
||||
Expression e = MacroParser.parse("variableOfType(\"A\", \"B\")");
|
||||
assertTrue(e instanceof MacroCallNode);
|
||||
MacroCallNode n = (MacroCallNode) e;
|
||||
assertTrue(n.getMacro() instanceof VariableOfTypeMacro);
|
||||
assertTrue(n.getMacro(new TemplateContextType[0]) instanceof VariableOfTypeMacro);
|
||||
Expression[] parameters = n.getParameters();
|
||||
assertEquals(2, parameters.length);
|
||||
assertTrue(parameters [0] instanceof ConstantNode);
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ExpressionContext {
|
||||
@@ -36,5 +37,11 @@ public interface ExpressionContext {
|
||||
<T> T getProperty(Key<T> key);
|
||||
@Nullable
|
||||
PsiElement getPsiElementAtStartOffset();
|
||||
|
||||
/**
|
||||
* @return all template context types matching the template invocation place
|
||||
*/
|
||||
@NotNull
|
||||
TemplateContextType[] getCompatibleContexts();
|
||||
}
|
||||
|
||||
|
||||
+9
-16
@@ -40,6 +40,9 @@ import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class EditVariableDialog extends DialogWrapper {
|
||||
private ArrayList<Variable> myVariables = new ArrayList<Variable>();
|
||||
@@ -108,23 +111,13 @@ class EditVariableDialog extends DialogWrapper {
|
||||
myTable.getSelectionModel().setSelectionInterval(0, 0);
|
||||
}
|
||||
|
||||
Predicate<Macro> isAcceptableInContext = macro -> myContextTypes.stream().anyMatch(macro::isAcceptableInContext);
|
||||
Stream<String> availableMacroNames = Arrays.stream(MacroFactory.getMacros()).filter(isAcceptableInContext).map(Macro::getPresentableName).sorted();
|
||||
Set<String> uniqueNames = availableMacroNames.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
ComboBox comboField = new ComboBox();
|
||||
Macro[] macros = MacroFactory.getMacros();
|
||||
Arrays.sort(macros, new Comparator<Macro> () {
|
||||
@Override
|
||||
public int compare(@NotNull Macro m1, @NotNull Macro m2) {
|
||||
return m1.getPresentableName().compareTo(m2.getPresentableName());
|
||||
}
|
||||
});
|
||||
eachMacro:
|
||||
for (Macro macro : macros) {
|
||||
for (TemplateContextType contextType : myContextTypes) {
|
||||
if (macro.isAcceptableInContext(contextType)) {
|
||||
comboField.addItem(macro.getPresentableName());
|
||||
continue eachMacro;
|
||||
}
|
||||
}
|
||||
}
|
||||
uniqueNames.forEach(comboField::addItem);
|
||||
|
||||
comboField.setEditable(true);
|
||||
DefaultCellEditor cellEditor = new DefaultCellEditor(comboField);
|
||||
cellEditor.setClickCountToStart(1);
|
||||
|
||||
@@ -17,46 +17,53 @@
|
||||
package com.intellij.codeInsight.template.impl;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.template.Expression;
|
||||
import com.intellij.codeInsight.template.ExpressionContext;
|
||||
import com.intellij.codeInsight.template.Macro;
|
||||
import com.intellij.codeInsight.template.Result;
|
||||
import com.intellij.codeInsight.template.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class MacroCallNode extends Expression {
|
||||
public Macro getMacro() {
|
||||
return myMacro;
|
||||
}
|
||||
|
||||
private final Macro myMacro;
|
||||
private final ArrayList<Expression> myParameters = new ArrayList<Expression>();
|
||||
private final List<Macro> myMacros;
|
||||
private final ArrayList<Expression> myParameters = new ArrayList<>();
|
||||
|
||||
public MacroCallNode(@NotNull Macro macro) {
|
||||
myMacro = macro;
|
||||
this(Collections.singletonList(macro));
|
||||
}
|
||||
|
||||
public MacroCallNode(List<Macro> macros) {
|
||||
myMacros = macros;
|
||||
assert macros.size() > 0;
|
||||
}
|
||||
|
||||
public void addParameter(Expression node) {
|
||||
myParameters.add(node);
|
||||
}
|
||||
|
||||
public Macro getMacro(TemplateContextType[] context) {
|
||||
Predicate<Macro> isAcceptableInContext = macro -> Arrays.stream(context).anyMatch(macro::isAcceptableInContext);
|
||||
return myMacros.stream().filter(isAcceptableInContext).findFirst().orElse(myMacros.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result calculateResult(ExpressionContext context) {
|
||||
Expression[] parameters = myParameters.toArray(new Expression[myParameters.size()]);
|
||||
return myMacro.calculateResult(parameters, context);
|
||||
return getMacro(context.getCompatibleContexts()).calculateResult(parameters, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result calculateQuickResult(ExpressionContext context) {
|
||||
Expression[] parameters = myParameters.toArray(new Expression[myParameters.size()]);
|
||||
return myMacro.calculateQuickResult(parameters, context);
|
||||
return getMacro(context.getCompatibleContexts()).calculateQuickResult(parameters, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupElement[] calculateLookupItems(ExpressionContext context) {
|
||||
Expression[] parameters = myParameters.toArray(new Expression[myParameters.size()]);
|
||||
return myMacro.calculateLookupItems(parameters, context);
|
||||
return getMacro(context.getCompatibleContexts()).calculateLookupItems(parameters, context);
|
||||
}
|
||||
|
||||
public Expression[] getParameters() {
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@VisibleForTesting
|
||||
public class MacroParser {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.impl.MacroParser");
|
||||
@@ -76,13 +78,13 @@ public class MacroParser {
|
||||
return new ConstantNode("");
|
||||
}
|
||||
|
||||
Macro macro = MacroFactory.createMacro(token);
|
||||
if (macro == null) {
|
||||
List<Macro> macros = MacroFactory.getMacros(token);
|
||||
if (macros.isEmpty()) {
|
||||
return parseVariable(lexer, expression);
|
||||
}
|
||||
|
||||
advance(lexer);
|
||||
MacroCallNode macroCallNode = new MacroCallNode(macro);
|
||||
MacroCallNode macroCallNode = new MacroCallNode(macros);
|
||||
if (lexer.getTokenType() == null) {
|
||||
return macroCallNode;
|
||||
}
|
||||
|
||||
@@ -99,11 +99,19 @@ public class TemplateState implements Disposable {
|
||||
@Nullable private PairProcessor<String, String> myProcessor;
|
||||
private boolean mySelectionCalculated = false;
|
||||
private boolean myStarted;
|
||||
private final TemplateContextType[] myCompatibleContexts;
|
||||
|
||||
public TemplateState(@NotNull Project project, final Editor editor) {
|
||||
TemplateState(@NotNull Project project, @NotNull final Editor editor) {
|
||||
myProject = project;
|
||||
myEditor = editor;
|
||||
myDocument = myEditor.getDocument();
|
||||
|
||||
PsiFile file = getPsiFile();
|
||||
if (file != null) {
|
||||
myCompatibleContexts = TemplateManagerImpl.getApplicableContextTypes(file, editor.getCaretModel().getOffset()).toArray(new TemplateContextType[0]);
|
||||
} else {
|
||||
myCompatibleContexts = new TemplateContextType[0];
|
||||
}
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
@@ -927,6 +935,12 @@ public class TemplateState implements Disposable {
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
return file == null ? null : file.findElementAt(offset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TemplateContextType[] getCompatibleContexts() {
|
||||
return myCompatibleContexts;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1071,7 +1085,7 @@ public class TemplateState implements Disposable {
|
||||
Expression e = myTemplate.getExpressionAt(j);
|
||||
@NonNls String marker = "a";
|
||||
if (e instanceof MacroCallNode) {
|
||||
marker = ((MacroCallNode)e).getMacro().getDefaultValue();
|
||||
marker = ((MacroCallNode)e).getMacro(myCompatibleContexts).getDefaultValue();
|
||||
}
|
||||
replaceString(marker, mySegments.getSegmentStart(i), mySegments.getSegmentEnd(i), i);
|
||||
indices.add(i);
|
||||
|
||||
@@ -18,48 +18,36 @@ package com.intellij.codeInsight.template.macro;
|
||||
|
||||
import com.intellij.codeInsight.template.Macro;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class MacroFactory {
|
||||
private static HashMap<String,Macro> myMacroTable = null;
|
||||
|
||||
private MacroFactory() {
|
||||
}
|
||||
private static final MultiMap<String, Macro> myMacroTable = init();
|
||||
|
||||
public static Macro createMacro(@NonNls String name) {
|
||||
if(myMacroTable == null) {
|
||||
init();
|
||||
}
|
||||
return ContainerUtil.getFirstItem(myMacroTable.get(name));
|
||||
}
|
||||
|
||||
return myMacroTable.get(name);
|
||||
public static List<Macro> getMacros(@NonNls String name) {
|
||||
return (List<Macro>)myMacroTable.get(name);
|
||||
}
|
||||
|
||||
public static Macro[] getMacros() {
|
||||
if(myMacroTable == null) {
|
||||
init();
|
||||
}
|
||||
|
||||
final Collection<Macro> values = myMacroTable.values();
|
||||
final Collection<? extends Macro> values = myMacroTable.values();
|
||||
return values.toArray(new Macro[values.size()]);
|
||||
}
|
||||
|
||||
private static void init() {
|
||||
myMacroTable = new HashMap<String, Macro>();
|
||||
|
||||
private static MultiMap<String, Macro> init() {
|
||||
MultiMap<String, Macro> result = MultiMap.create();
|
||||
for(Macro macro: Extensions.getExtensions(Macro.EP_NAME)) {
|
||||
myMacroTable.put(macro.getName(), macro);
|
||||
result.putValue(macro.getName(), macro);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use com.intellij.liveTemplateMacro extension point instead
|
||||
*/
|
||||
public static void register(Macro macro) {
|
||||
if (myMacroTable == null) init();
|
||||
myMacroTable.put(macro.getName(), macro);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user