Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
IntelliJ plugin to perform multiple structural search and replace actions. Can be installed with https://github.com/dkandalov/live-plugin
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.application.*
import com.intellij.openapi.command.*
import com.intellij.openapi.diagnostic.*
import com.intellij.openapi.fileTypes.*
import com.intellij.openapi.progress.*
import com.intellij.openapi.project.*
import com.intellij.openapi.ui.*
import com.intellij.openapi.vfs.*
import com.intellij.psi.*
import com.intellij.psi.search.*
import com.intellij.structuralsearch.*
import com.intellij.structuralsearch.plugin.*
import com.intellij.structuralsearch.plugin.replace.*
import com.intellij.structuralsearch.plugin.replace.impl.*
import com.intellij.structuralsearch.plugin.ui.*
import com.intellij.structuralsearch.plugin.util.*
import java.util.*
import static liveplugin.PluginUtil.registerAction
import static liveplugin.PluginUtil.show
/**
* IntelliJ Plugin action to do multiple structural find/replaces.
* Can be installed with https://github.com/dkandalov/live-plugin v0.6.1 on IntelliJ 2018.3.
*/
class FindMatchesAction extends AnAction {
Logger logger = Logger.getInstance("FindMatches")
@Override void actionPerformed(AnActionEvent event) {
Project project = event.project
show("Finding matches in ${project.name}...")
VirtualFile searchRootFile = project.baseDir.findFileByRelativePath("libraries/feature")
PsiDirectory searchRoot = PsiManager.getInstance(project).findDirectory(searchRootFile)
GlobalSearchScope scope = GlobalSearchScopesCore.directoryScope(searchRoot, true)
/*** Do one or more calls to findMatches() here... ***/
findMatches(project, scope, "short label",
'com.example.Foo($params$)', // structural search pattern
'com.example.Barr($params$)', // structural replace pattern
Collections.emptyList())
}
private void findMatches(Project project, GlobalSearchScope scope, String name, String find, String replace, List<MatchVariableConstraint> constraints) {
try {
MatchOptions options = new MatchOptions()
options.setFileType(StdFileTypes.JAVA)
options.setScope(scope)
options.setRecursiveSearch(true)
options.setCaseSensitiveMatch(true)
options.fillSearchCriteria(find)
constraints.forEach {
options.addVariableConstraint(it)
}
ReplaceOptions replaceOptions = new ReplaceOptions(options)
replaceOptions.setToShortenFQN(true)
replaceOptions.setToUseStaticImport(true)
replaceOptions.setReplacement(replace)
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Finding matches for $name") {
void run(ProgressIndicator progressIndicator) {
CollectingMatchResultSink sink = new CollectingMatchResultSink() {
@Override ProgressIndicator getProgressIndicator() {
return progressIndicator
}
}
Matcher matcher = new Matcher(project, options)
matcher.findMatches(sink, options)
int count = sink.getMatches().size()
logger.info("Found ${count} matches for $name")
ApplicationManager.getApplication().invokeLater { show("Found ${count} matches for $name") }
WriteCommandAction.runWriteCommandAction(project) {
Replacer replacer = new Replacer(project, replaceOptions)
sink.getMatches().forEach { MatchResult matchResult ->
replacer.replace(replacer.buildReplacement(matchResult))
}
}
logger.info("Replaced ${count} matches for $name")
ApplicationManager.getApplication().invokeLater { show("Replaced ${count} matches for $name") }
}
})
} catch (Throwable throwable) {
logger.error(throwable)
Messages.showErrorDialog(project, throwable.getStackTrace().toString(), "Error finding matches for $name")
}
}
private static MatchVariableConstraint createConstraint(String name, int minCount, int maxCount, String type = null) {
MatchVariableConstraint constraint = new MatchVariableConstraint()
constraint.setName(name)
constraint.setMinCount(minCount)
constraint.setMaxCount(maxCount)
if (type != null) {
constraint.setNameOfExprType(type)
}
return constraint
}
}
registerAction("Find Matches", "alt shift M", new FindMatchesAction())
if (!isIdeStartup) show("Loaded 'Find Matches'<br/>Use alt+shift+M to run it")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.