@Nullable private String expandMacroSet( String str, boolean firstQueueExpand, DataContext dataContext, Iterator<Macro> macros) throws Macro.ExecutionCancelledException { if (str == null) return null; while (macros.hasNext()) { Macro macro = macros.next(); if (macro instanceof SecondQueueExpandMacro && firstQueueExpand) continue; String name = "$" + macro.getName() + "$"; String macroNameWithParamStart = "$" + macro.getName() + "("; if (str.contains(name)) { String expanded = macro.expand(dataContext); // if (dataContext instanceof DataManagerImpl.MyDataContext) { // // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) // which may 'invalidate' the datacontext // // since we know exactly that context is valid, we need to update its event count // // ((DataManagerImpl.MyDataContext)dataContext).setEventCount(IdeEventQueue.getInstance().getEventCount()); // } if (expanded == null) { expanded = ""; } str = StringUtil.replace(str, name, expanded); } else if (str.contains(macroNameWithParamStart)) { String macroNameWithParamEnd = ")$"; Map<String, String> toReplace = null; int i = str.indexOf(macroNameWithParamStart); while (i != -1) { int j = str.indexOf(macroNameWithParamEnd, i + macroNameWithParamStart.length()); if (j > i) { String param = str.substring(i + macroNameWithParamStart.length(), j); if (toReplace == null) toReplace = new THashMap<String, String>(); String expanded = macro.expand(dataContext, param); if (expanded == null) { expanded = ""; } toReplace.put(macroNameWithParamStart + param + macroNameWithParamEnd, expanded); i = j + macroNameWithParamEnd.length(); } else { break; } } if (toReplace != null) { for (Map.Entry<String, String> entry : toReplace.entrySet()) { str = StringUtil.replace(str, entry.getKey(), entry.getValue()); } } } } return str; }