mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
run live template to adjust template from selection
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.structuralsearch;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.template.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
|
||||
import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StructuralSearchTemplateBuilder {
|
||||
|
||||
private final TemplateBuilder myBuilder;
|
||||
private final PsiFile myPsiFile;
|
||||
|
||||
private final PlaceholderCount myClassCount = new PlaceholderCount("Class");
|
||||
private final PlaceholderCount myVarCount = new PlaceholderCount("Var");
|
||||
private final PlaceholderCount myFunCount = new PlaceholderCount("Fun");
|
||||
|
||||
private int myShift;
|
||||
|
||||
public StructuralSearchTemplateBuilder(@NotNull PsiFile psiFile) {
|
||||
myBuilder = TemplateBuilderFactory.getInstance().createTemplateBuilder(psiFile);
|
||||
myPsiFile = psiFile;
|
||||
}
|
||||
|
||||
public TemplateBuilder buildTemplate() {
|
||||
|
||||
JavaRecursiveElementVisitor visitor = new JavaRecursiveElementVisitor() {
|
||||
|
||||
@Override
|
||||
public void visitIdentifier(PsiIdentifier identifier) {
|
||||
PsiElement parent = identifier.getParent();
|
||||
if (parent instanceof PsiClass) {
|
||||
replaceElement(identifier, myClassCount, true);
|
||||
}
|
||||
else if (parent instanceof PsiReferenceExpression) {
|
||||
if (parent.getParent() instanceof PsiMethodCallExpression)
|
||||
replaceElement(identifier, myFunCount, true);
|
||||
else
|
||||
replaceElement(identifier, myVarCount, false);
|
||||
}
|
||||
else if (parent instanceof PsiJavaCodeReferenceElement) {
|
||||
replaceElement(identifier, myClassCount, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceList(PsiReferenceList list) {
|
||||
PsiJavaCodeReferenceElement[] elements = list.getReferenceElements();
|
||||
for (PsiJavaCodeReferenceElement element : elements) {
|
||||
replaceElement(element.getReferenceNameElement(), myClassCount, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MatchOptions matchOptions = new MatchOptions();
|
||||
String text = myPsiFile.getText();
|
||||
matchOptions.setSearchPattern(text);
|
||||
CompiledPattern pattern = PatternCompiler.compilePattern(myPsiFile.getProject(), matchOptions, false);
|
||||
if (pattern == null)
|
||||
return myBuilder;
|
||||
|
||||
PsiElement current = pattern.getNodes().current();
|
||||
if (current != null) {
|
||||
myShift = current.getTextRange().getStartOffset();
|
||||
current.accept(visitor);
|
||||
}
|
||||
|
||||
return myBuilder;
|
||||
}
|
||||
|
||||
private void replaceElement(@Nullable PsiElement element, PlaceholderCount count, boolean preferOriginal) {
|
||||
if (element == null) {
|
||||
return;
|
||||
}
|
||||
myBuilder.replaceRange(element.getTextRange().shiftLeft(myShift), new MyExpression(count.getPlaceholder(), element, preferOriginal));
|
||||
}
|
||||
|
||||
private static class MyExpression extends Expression {
|
||||
|
||||
private final String myPlaceholder;
|
||||
private final String myOriginalText;
|
||||
private final boolean myPreferOriginal;
|
||||
|
||||
private MyExpression(String placeholder, PsiElement original, boolean preferOriginal) {
|
||||
myPlaceholder = placeholder;
|
||||
myOriginalText = original.getText();
|
||||
myPreferOriginal = preferOriginal;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Result calculateResult(ExpressionContext context) {
|
||||
return new TextResult(myPreferOriginal ? myOriginalText : myPlaceholder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Result calculateQuickResult(ExpressionContext context) {
|
||||
return calculateResult(context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LookupElement[] calculateLookupItems(ExpressionContext context) {
|
||||
LookupElement[] elements = {LookupElementBuilder.create(myPlaceholder), LookupElementBuilder.create(myOriginalText)};
|
||||
return myPreferOriginal ? ArrayUtil.reverseArray(elements) : elements;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PlaceholderCount {
|
||||
private final String myName;
|
||||
private int myCount;
|
||||
|
||||
private PlaceholderCount(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public String getPlaceholder() {
|
||||
return "$" + myName + ++myCount + "$";
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -2,6 +2,7 @@
|
||||
package com.intellij.structuralsearch.plugin.ui;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.template.TemplateBuilder;
|
||||
import com.intellij.codeInsight.template.impl.TemplateEditorUtil;
|
||||
import com.intellij.codeInsight.template.impl.TemplateImplUtil;
|
||||
import com.intellij.find.FindBundle;
|
||||
@@ -74,6 +75,7 @@ import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
@@ -644,6 +646,12 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
setSize(otherSize.width, getSize().height);
|
||||
}
|
||||
}
|
||||
|
||||
Document document = mySearchCriteriaEdit.getDocument();
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(getProject()).getPsiFile(document);
|
||||
assert psiFile != null;
|
||||
TemplateBuilder builder = new StructuralSearchTemplateBuilder(psiFile).buildTemplate();
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> builder.run(Objects.requireNonNull(mySearchCriteriaEdit.getEditor()), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.structuralsearch;
|
||||
|
||||
import com.intellij.codeInsight.template.Template;
|
||||
import com.intellij.codeInsight.template.TemplateBuilderImpl;
|
||||
import com.intellij.codeInsight.template.TemplateManager;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
|
||||
public class SSTemplateBuilderTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testClassTemplate() {
|
||||
doTest("class foo extends bar, next implements xxx", "class foo extends $Class2$, $Class3$ implements $Class4$");
|
||||
}
|
||||
|
||||
public void testStatement() {
|
||||
doTest("i=1", "$Var1$=1");
|
||||
}
|
||||
|
||||
public void testMethodCall() {
|
||||
Template template = doTest("foo()", "foo()");
|
||||
assertEquals(1, template.getSegmentsCount());
|
||||
}
|
||||
|
||||
private Template doTest(String text, String expected) {
|
||||
PsiFile psiFile = myFixture.configureByText(JavaFileType.INSTANCE, text);
|
||||
TemplateBuilderImpl builder = (TemplateBuilderImpl)new StructuralSearchTemplateBuilder(getFile()).buildTemplate();
|
||||
Template template = WriteCommandAction.writeCommandAction(getProject()).compute(() -> {
|
||||
Template inlineTemplate = builder.buildInlineTemplate();
|
||||
TemplateManager.getInstance(getProject()).startTemplate(getEditor(), inlineTemplate);
|
||||
return inlineTemplate;
|
||||
});
|
||||
assertEquals(expected, psiFile.getText());
|
||||
return template;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user