summaryrefslogtreecommitdiff
path: root/plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java')
-rw-r--r--plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java281
1 files changed, 281 insertions, 0 deletions
diff --git a/plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java b/plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
new file mode 100644
index 000000000000..ff7b379a161f
--- /dev/null
+++ b/plugins/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
@@ -0,0 +1,281 @@
+package com.intellij.structuralsearch;
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.codeInsight.template.TemplateContextType;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
+import com.intellij.structuralsearch.impl.matcher.GlobalMatchingVisitor;
+import com.intellij.structuralsearch.impl.matcher.PatternTreeContext;
+import com.intellij.structuralsearch.impl.matcher.compiler.GlobalCompilingVisitor;
+import com.intellij.structuralsearch.impl.matcher.filters.LexicalNodesFilter;
+import com.intellij.structuralsearch.plugin.replace.ReplaceOptions;
+import com.intellij.structuralsearch.plugin.replace.impl.ParameterInfo;
+import com.intellij.structuralsearch.plugin.replace.impl.ReplacementBuilder;
+import com.intellij.structuralsearch.plugin.replace.impl.ReplacementContext;
+import com.intellij.structuralsearch.plugin.replace.impl.Replacer;
+import com.intellij.structuralsearch.plugin.ui.Configuration;
+import com.intellij.structuralsearch.plugin.ui.SearchContext;
+import com.intellij.structuralsearch.plugin.ui.UIUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.LocalTimeCounter;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class StructuralSearchProfile {
+ public static final ExtensionPointName<StructuralSearchProfile> EP_NAME =
+ ExtensionPointName.create("com.intellij.structuralsearch.profile");
+
+ public abstract void compile(PsiElement[] elements, @NotNull GlobalCompilingVisitor globalVisitor);
+
+ @NotNull
+ public abstract PsiElementVisitor createMatchingVisitor(@NotNull GlobalMatchingVisitor globalVisitor);
+
+ @NotNull
+ public abstract PsiElementVisitor getLexicalNodesFilter(@NotNull LexicalNodesFilter filter);
+
+ @NotNull
+ public abstract CompiledPattern createCompiledPattern();
+
+ public static String getTypeName(FileType fileType) {
+ return fileType.getName().toLowerCase();
+ }
+
+ public abstract boolean canProcess(@NotNull FileType fileType);
+
+ public abstract boolean isMyLanguage(@NotNull Language language);
+
+ public boolean isMyFile(PsiFile file, @NotNull Language language, Language... patternLanguages) {
+ if (isMyLanguage(language) && ArrayUtil.find(patternLanguages, language) >= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @NotNull
+ public PsiElement[] createPatternTree(@NotNull String text,
+ @NotNull PatternTreeContext context,
+ @NotNull FileType fileType,
+ @Nullable Language language,
+ @Nullable String contextName,
+ @Nullable String extension,
+ @NotNull Project project,
+ boolean physical) {
+ final String ext = extension != null ? extension : fileType.getDefaultExtension();
+ final String name = "__dummy." + ext;
+ final PsiFileFactory factory = PsiFileFactory.getInstance(project);
+
+ final PsiFile file = language == null
+ ? factory.createFileFromText(name, fileType, text, LocalTimeCounter.currentTime(), physical, true)
+ : factory.createFileFromText(name, language, text, physical, true);
+
+ return file != null ? file.getChildren() : PsiElement.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ public PsiElement[] createPatternTree(@NotNull String text,
+ @NotNull PatternTreeContext context,
+ @NotNull FileType fileType,
+ @NotNull Project project,
+ boolean physical) {
+ return createPatternTree(text, context, fileType, null, null, null, project, physical);
+ }
+
+ @NotNull
+ public Editor createEditor(@NotNull SearchContext searchContext,
+ @NotNull FileType fileType,
+ Language dialect,
+ String text,
+ boolean useLastConfiguration) {
+ PsiFile codeFragment = createCodeFragment(searchContext.getProject(), text, null);
+ if (codeFragment == null) {
+ codeFragment = createFileFragment(searchContext, fileType, dialect, text);
+ }
+
+ if (codeFragment != null) {
+ final Document doc = PsiDocumentManager.getInstance(searchContext.getProject()).getDocument(codeFragment);
+ assert doc != null : "code fragment element should be physical";
+ DaemonCodeAnalyzer.getInstance(searchContext.getProject()).setHighlightingEnabled(codeFragment, false);
+ return UIUtil.createEditor(doc, searchContext.getProject(), true, true, getTemplateContextType());
+ }
+
+ final EditorFactory factory = EditorFactory.getInstance();
+ final Document document = factory.createDocument(text);
+ final EditorEx editor = (EditorEx)factory.createEditor(document, searchContext.getProject());
+ editor.getSettings().setFoldingOutlineShown(false);
+ return editor;
+ }
+
+ private static PsiFile createFileFragment(SearchContext searchContext, FileType fileType, Language dialect, String text) {
+ final String name = "__dummy." + fileType.getDefaultExtension();
+ final PsiFileFactory factory = PsiFileFactory.getInstance(searchContext.getProject());
+
+ return dialect == null ?
+ factory.createFileFromText(name, fileType, text, LocalTimeCounter.currentTime(), true, true) :
+ factory.createFileFromText(name, dialect, text, true, true);
+ }
+
+ @Nullable
+ public PsiCodeFragment createCodeFragment(Project project, String text, @Nullable PsiElement context) {
+ return null;
+ }
+
+ @Nullable
+ public Class<? extends TemplateContextType> getTemplateContextTypeClass() {
+ return null;
+ }
+
+ public final TemplateContextType getTemplateContextType() {
+ final Class<? extends TemplateContextType> clazz = getTemplateContextTypeClass();
+ return clazz != null ? ContainerUtil.findInstance(TemplateContextType.EP_NAME.getExtensions(), clazz) : null;
+ }
+
+ @Nullable
+ public FileType detectFileType(@NotNull PsiElement context) {
+ return null;
+ }
+
+ @Nullable
+ public StructuralReplaceHandler getReplaceHandler(@NotNull ReplacementContext context) {
+ return null;
+ }
+
+ public void checkSearchPattern(Project project, MatchOptions options) {
+ }
+
+ public void checkReplacementPattern(Project project, ReplaceOptions options) {
+ String fileType = getTypeName(options.getMatchOptions().getFileType());
+ throw new UnsupportedPatternException(SSRBundle.message("replacement.not.supported.for.filetype", fileType));
+ }
+
+ @NotNull
+ public Language getLanguage(PsiElement element) {
+ return element.getLanguage();
+ }
+
+ // only for nodes not filtered by lexical-nodes filter; they can be by default
+ public boolean canBeVarDelimeter(@NotNull PsiElement element) {
+ return false;
+ }
+
+ public String getText(PsiElement match, int start, int end) {
+ final String matchText = match.getText();
+ if (start==0 && end==-1) return matchText;
+ return matchText.substring(start, end == -1 ? matchText.length() : end);
+ }
+
+ public Class getElementContextByPsi(PsiElement element) {
+ return element.getClass();
+ }
+
+ public String getTypedVarString(PsiElement element) {
+ if (element instanceof PsiNamedElement) {
+ return ((PsiNamedElement)element).getName();
+ }
+ return element.getText();
+ }
+
+ public String getMeaningfulText(PsiElement element) {
+ return getTypedVarString(element);
+ }
+
+ public PsiElement updateCurrentNode(PsiElement node) {
+ return node;
+ }
+
+ public PsiElement extendMatchedByDownUp(PsiElement node) {
+ return node;
+ }
+
+ public PsiElement extendMatchOnePsiFile(PsiElement file) {
+ return file;
+ }
+
+ public LanguageFileType getDefaultFileType(@Nullable LanguageFileType fileType) {
+ return fileType;
+ }
+
+ Configuration[] getPredefinedTemplates() {
+ return Configuration.EMPTY_ARRAY;
+ }
+
+ public void provideAdditionalReplaceOptions(@NotNull PsiElement node, ReplaceOptions options, ReplacementBuilder builder) {}
+
+ public int handleSubstitution(final ParameterInfo info,
+ MatchResult match,
+ StringBuilder result,
+ int offset,
+ HashMap<String, MatchResult> matchMap) {
+ return defaultHandleSubstitution(info, match, result, offset);
+ }
+
+ public static int defaultHandleSubstitution(ParameterInfo info, MatchResult match, StringBuilder result, int offset) {
+ if (info.getName().equals(match.getName())) {
+ String replacementString = match.getMatchImage();
+ boolean forceAddingNewLine = false;
+ if (match.getAllSons().size() > 0 && !match.isScopeMatch()) {
+ // compound matches
+ StringBuilder buf = new StringBuilder();
+
+ for (final MatchResult matchResult : match.getAllSons()) {
+ final PsiElement currentElement = matchResult.getMatch();
+
+ if (buf.length() > 0) {
+ if (info.isParameterContext()) {
+ buf.append(',');
+ } else {
+ buf.append(' ');
+ }
+ }
+
+ buf.append(matchResult.getMatchImage());
+ forceAddingNewLine = currentElement instanceof PsiComment;
+ }
+ replacementString = buf.toString();
+ } else {
+ if (info.isStatementContext()) {
+ forceAddingNewLine = match.getMatch() instanceof PsiComment;
+ }
+ }
+
+ offset = Replacer.insertSubstitution(result, offset, info, replacementString);
+ if (forceAddingNewLine && info.isStatementContext()) {
+ result.insert(info.getStartIndex() + offset + 1, '\n');
+ offset ++;
+ }
+ }
+ return offset;
+ }
+
+ public int processAdditionalOptions(ParameterInfo info, int offset, StringBuilder result, MatchResult r) {
+ return offset;
+ }
+
+ public boolean isIdentifier(PsiElement element) {
+ return false;
+ }
+
+ public Collection<String> getReservedWords() {
+ return Collections.emptySet();
+ }
+
+ public boolean isDocCommentOwner(PsiElement match) {
+ return false;
+ }
+}