List<AnAction> (final Project project, final Editor editor, PsiFile file, @Nullable Surrounder surrounder) { SelectionModel selectionModel = editor.getSelectionModel(); boolean hasSelection = selectionModel.hasSelection(); if (!hasSelection) { selectLogicalLineContents(editor); } int[] startOffsets = editor.getCaretModel().getAllCarets().stream() .mapToInt(Caret::getSelectionStart) .toArray(); int[] endOffsets = editor.getCaretModel().getAllCarets().stream() .mapToInt(Caret::getSelectionEnd) .toArray(); final Language baseLanguage = file.getViewProvider().getBaseLanguage(); Language previousLanguage = null; for (int i = 0; i < startOffsets.length; ++i) { PsiElement element1 = file.findElementAt(startOffsets[i]); PsiElement element2 = file.findElementAt(endOffsets[i] - 1); if (element1 == null || element2 == null) return null; TextRange textRange = new TextRange(startOffsets[i], endOffsets[i]); for (SurroundWithRangeAdjuster adjuster : SurroundWithRangeAdjuster.EP_NAME.getExtensionList()) { textRange = adjuster.adjustSurroundWithRange(file, textRange, hasSelection); if (textRange == null) return null; } startOffsets[i] = textRange.getStartOffset(); endOffsets[i] = textRange.getEndOffset(); element1 = file.findElementAt(startOffsets[0]); assert element1 != null; final Language currentLanguage = element1.getParent().getLanguage(); if (previousLanguage != null && !currentLanguage.equals(previousLanguage)) { return null; } previousLanguage = currentLanguage; } assert previousLanguage != null; List<SurroundDescriptor> surroundDescriptors = new ArrayList<>(LanguageSurrounders.INSTANCE.allForLanguage(previousLanguage)); if (previousLanguage != baseLanguage) surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(baseLanguage)); surroundDescriptors.add(CustomFoldingSurroundDescriptor.INSTANCE); int exclusiveCount = 0; List<SurroundDescriptor> exclusiveSurroundDescriptors = new ArrayList<>(); for (SurroundDescriptor sd : surroundDescriptors) { if (sd.isExclusive()) { exclusiveCount++; exclusiveSurroundDescriptors.add(sd); } } if (exclusiveCount > 0) { surroundDescriptors = exclusiveSurroundDescriptors; } if (surrounder != null) { invokeSurrounderInTests(project, editor, file, surrounder, startOffsets, endOffsets, surroundDescriptors); return null; } Map<Surrounder, PsiElement[]> surrounders = new LinkedHashMap<>(); for (SurroundDescriptor descriptor : surroundDescriptors) { final PsiElement[] elements = getElementsToSurround(descriptor, file, startOffsets, endOffsets); if (elements.length > 0) { for (PsiElement element : elements) { assert element != null : "descriptor " + descriptor + " returned null element"; assert element.isValid() : descriptor; } for (Surrounder s : descriptor.getSurrounders()) { surrounders.put(s, elements); } } } return doBuildSurroundActions(project, editor, file, surrounders); }