Search in sources :

Example 1 with OffsetKey

use of com.intellij.codeInsight.completion.OffsetKey in project intellij-community by JetBrains.

the class SaveAsTemplateAction method actionPerformed.

@Override
public void actionPerformed(AnActionEvent e) {
    DataContext dataContext = e.getDataContext();
    Editor editor = Objects.requireNonNull(CommonDataKeys.EDITOR.getData(dataContext));
    PsiFile file = Objects.requireNonNull(CommonDataKeys.PSI_FILE.getData(dataContext));
    final Project project = file.getProject();
    PsiDocumentManager.getInstance(project).commitAllDocuments();
    final TextRange selection = new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd());
    PsiElement current = file.findElementAt(selection.getStartOffset());
    int startOffset = selection.getStartOffset();
    while (current instanceof PsiWhiteSpace) {
        current = current.getNextSibling();
        if (current == null)
            break;
        startOffset = current.getTextRange().getStartOffset();
    }
    if (startOffset >= selection.getEndOffset())
        startOffset = selection.getStartOffset();
    final PsiElement[] psiElements = PsiTreeUtil.collectElements(file, new PsiElementFilter() {

        @Override
        public boolean isAccepted(PsiElement element) {
            return selection.contains(element.getTextRange()) && element.getReferences().length > 0;
        }
    });
    final Document document = EditorFactory.getInstance().createDocument(editor.getDocument().getText().substring(startOffset, selection.getEndOffset()));
    final boolean isXml = file.getLanguage().is(StdLanguages.XML);
    final int offsetDelta = startOffset;
    new WriteCommandAction.Simple(project, (String) null) {

        @Override
        protected void run() throws Throwable {
            Map<RangeMarker, String> rangeToText = new HashMap<>();
            for (PsiElement element : psiElements) {
                for (PsiReference reference : element.getReferences()) {
                    if (!(reference instanceof PsiQualifiedReference) || ((PsiQualifiedReference) reference).getQualifier() == null) {
                        String canonicalText = reference.getCanonicalText();
                        TextRange referenceRange = reference.getRangeInElement();
                        final TextRange elementTextRange = element.getTextRange();
                        LOG.assertTrue(elementTextRange != null, elementTextRange);
                        final TextRange range = elementTextRange.cutOut(referenceRange).shiftRight(-offsetDelta);
                        final String oldText = document.getText(range);
                        // workaround for Java references: canonicalText contains generics, and we need to cut them off because otherwise
                        // they will be duplicated
                        int pos = canonicalText.indexOf('<');
                        if (pos > 0 && !oldText.contains("<")) {
                            canonicalText = canonicalText.substring(0, pos);
                        }
                        if (isXml) {
                            //strip namespace prefixes
                            pos = canonicalText.lastIndexOf(':');
                            if (pos >= 0 && pos < canonicalText.length() - 1 && !oldText.contains(":")) {
                                canonicalText = canonicalText.substring(pos + 1);
                            }
                        }
                        if (!canonicalText.equals(oldText)) {
                            rangeToText.put(document.createRangeMarker(range), canonicalText);
                        }
                    }
                }
            }
            List<RangeMarker> markers = new ArrayList<>();
            for (RangeMarker m1 : rangeToText.keySet()) {
                boolean nested = false;
                for (RangeMarker m2 : rangeToText.keySet()) {
                    if (m1 != m2 && m2.getStartOffset() <= m1.getStartOffset() && m1.getEndOffset() <= m2.getEndOffset()) {
                        nested = true;
                        break;
                    }
                }
                if (!nested) {
                    markers.add(m1);
                }
            }
            for (RangeMarker marker : markers) {
                final String value = rangeToText.get(marker);
                document.replaceString(marker.getStartOffset(), marker.getEndOffset(), value);
            }
        }
    }.execute();
    final TemplateImpl template = new TemplateImpl(TemplateListPanel.ABBREVIATION, document.getText(), TemplateSettings.USER_GROUP_NAME);
    template.setToReformat(true);
    OffsetKey startKey = OffsetKey.create("pivot");
    OffsetsInFile offsets = new OffsetsInFile(file);
    offsets.getOffsets().addOffset(startKey, startOffset);
    OffsetsInFile copy = TemplateManagerImpl.copyWithDummyIdentifier(offsets, editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd(), CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
    Set<TemplateContextType> applicable = TemplateManagerImpl.getApplicableContextTypes(copy.getFile(), copy.getOffsets().getOffset(startKey));
    for (TemplateContextType contextType : TemplateManagerImpl.getAllContextTypes()) {
        template.getTemplateContext().setEnabled(contextType, applicable.contains(contextType));
    }
    final LiveTemplatesConfigurable configurable = new LiveTemplatesConfigurable();
    ShowSettingsUtil.getInstance().editConfigurable(project, configurable, () -> configurable.getTemplateListPanel().addTemplate(template));
}
Also used : WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) OffsetsInFile(com.intellij.codeInsight.completion.OffsetsInFile) Document(com.intellij.openapi.editor.Document) DataContext(com.intellij.openapi.actionSystem.DataContext) TextRange(com.intellij.openapi.util.TextRange) RangeMarker(com.intellij.openapi.editor.RangeMarker) PsiElementFilter(com.intellij.psi.util.PsiElementFilter) Project(com.intellij.openapi.project.Project) OffsetKey(com.intellij.codeInsight.completion.OffsetKey) Editor(com.intellij.openapi.editor.Editor) HashMap(com.intellij.util.containers.HashMap) TemplateContextType(com.intellij.codeInsight.template.TemplateContextType)

Aggregations

OffsetKey (com.intellij.codeInsight.completion.OffsetKey)1 OffsetsInFile (com.intellij.codeInsight.completion.OffsetsInFile)1 TemplateContextType (com.intellij.codeInsight.template.TemplateContextType)1 DataContext (com.intellij.openapi.actionSystem.DataContext)1 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)1 Document (com.intellij.openapi.editor.Document)1 Editor (com.intellij.openapi.editor.Editor)1 RangeMarker (com.intellij.openapi.editor.RangeMarker)1 Project (com.intellij.openapi.project.Project)1 TextRange (com.intellij.openapi.util.TextRange)1 PsiElementFilter (com.intellij.psi.util.PsiElementFilter)1 HashMap (com.intellij.util.containers.HashMap)1