public PostprocessReformattingAspect( Project project, PsiManager psiManager, TreeAspect treeAspect) { myProject = project; myPsiManager = psiManager; myTreeAspect = treeAspect; PomManager.getModel(psiManager.getProject()) .registerAspect( PostprocessReformattingAspect.class, this, Collections.singleton((PomModelAspect) treeAspect)); ApplicationListener applicationListener = new ApplicationAdapter() { public void writeActionStarted(final Object action) { final CommandProcessor processor = CommandProcessor.getInstance(); if (processor != null) { final Project project = processor.getCurrentCommandProject(); if (project == myProject) { myPostponedCounter++; } } } public void writeActionFinished(final Object action) { final CommandProcessor processor = CommandProcessor.getInstance(); if (processor != null) { final Project project = processor.getCurrentCommandProject(); if (project == myProject) { decrementPostponedCounter(); } } } }; ApplicationManager.getApplication().addApplicationListener(applicationListener, this); }
public String[] knownNamespaces() { final PsiElement parentElement = getParent(); BidirectionalMap<String, String> map = initNamespaceMaps(parentElement); Set<String> known = Collections.emptySet(); if (map != null) { known = new HashSet<String>(map.values()); } if (parentElement instanceof XmlTag) { if (known.isEmpty()) return ((XmlTag) parentElement).knownNamespaces(); ContainerUtil.addAll(known, ((XmlTag) parentElement).knownNamespaces()); } else { XmlExtension xmlExtension = XmlExtension.getExtensionByElement(this); if (xmlExtension != null) { final XmlFile xmlFile = xmlExtension.getContainingFile(this); if (xmlFile != null) { final XmlTag rootTag = xmlFile.getRootTag(); if (rootTag != null && rootTag != this) { if (known.isEmpty()) return rootTag.knownNamespaces(); ContainerUtil.addAll(known, rootTag.knownNamespaces()); } } } } return ArrayUtil.toStringArray(known); }
@NotNull private Map<String, CachedValue<XmlNSDescriptor>> computeNsDescriptorMap() { Map<String, CachedValue<XmlNSDescriptor>> map = null; // XSD aware attributes processing final String noNamespaceDeclaration = getAttributeValue("noNamespaceSchemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI); final String schemaLocationDeclaration = getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI); if (noNamespaceDeclaration != null) { map = initializeSchema(XmlUtil.EMPTY_URI, null, noNamespaceDeclaration, map); } if (schemaLocationDeclaration != null) { final StringTokenizer tokenizer = new StringTokenizer(schemaLocationDeclaration); while (tokenizer.hasMoreTokens()) { final String uri = tokenizer.nextToken(); if (tokenizer.hasMoreTokens()) { map = initializeSchema(uri, null, tokenizer.nextToken(), map); } } } // namespace attributes processing (XSD declaration via ExternalResourceManager) if (hasNamespaceDeclarations()) { for (final XmlAttribute attribute : getAttributes()) { if (attribute.isNamespaceDeclaration()) { String ns = attribute.getValue(); if (ns == null) ns = XmlUtil.EMPTY_URI; ns = getRealNs(ns); if (map == null || !map.containsKey(ns)) { map = initializeSchema(ns, getNSVersion(ns, this), getNsLocation(ns), map); } } } } return map == null ? Collections.<String, CachedValue<XmlNSDescriptor>>emptyMap() : map; }
private List<PostponedAction> normalizeAndReorderPostponedActions( final TreeSet<PostprocessFormattingTask> rangesToProcess, Document document) { final List<PostprocessFormattingTask> freeFormatingActions = new ArrayList<PostprocessFormattingTask>(); final List<ReindentTask> indentActions = new ArrayList<ReindentTask>(); PostprocessFormattingTask accumulatedTask = null; Iterator<PostprocessFormattingTask> iterator = rangesToProcess.iterator(); while (iterator.hasNext()) { final PostprocessFormattingTask currentTask = iterator.next(); if (accumulatedTask == null) { accumulatedTask = currentTask; iterator.remove(); } else if (accumulatedTask.getStartOffset() > currentTask.getEndOffset() || accumulatedTask.getStartOffset() == currentTask.getEndOffset() && !canStickActionsTogether(accumulatedTask, currentTask)) { // action can be pushed if (accumulatedTask instanceof ReindentTask) { indentActions.add((ReindentTask) accumulatedTask); } else { freeFormatingActions.add(accumulatedTask); } accumulatedTask = currentTask; iterator.remove(); } else if (accumulatedTask instanceof ReformatTask && currentTask instanceof ReindentTask) { // split accumulated reformat range into two if (accumulatedTask.getStartOffset() < currentTask.getStartOffset()) { final RangeMarker endOfRange = document.createRangeMarker( accumulatedTask.getStartOffset(), currentTask.getStartOffset()); // add heading reformat part rangesToProcess.add(new ReformatTask(endOfRange)); // and manage heading whitespace because formatter does not edit it in previous action iterator = rangesToProcess.iterator(); //noinspection StatementWithEmptyBody while (iterator.next().getRange() != currentTask.getRange()) ; } final RangeMarker rangeToProcess = document.createRangeMarker(currentTask.getEndOffset(), accumulatedTask.getEndOffset()); freeFormatingActions.add(new ReformatWithHeadingWhitespaceTask(rangeToProcess)); accumulatedTask = currentTask; iterator.remove(); } else { if (!(accumulatedTask instanceof ReindentTask)) { iterator.remove(); boolean withLeadingWhitespace = accumulatedTask instanceof ReformatWithHeadingWhitespaceTask; if (accumulatedTask instanceof ReformatTask && currentTask instanceof ReformatWithHeadingWhitespaceTask && accumulatedTask.getStartOffset() == currentTask.getStartOffset()) { withLeadingWhitespace = true; } else if (accumulatedTask instanceof ReformatWithHeadingWhitespaceTask && currentTask instanceof ReformatTask && accumulatedTask.getStartOffset() < currentTask.getStartOffset()) { withLeadingWhitespace = false; } int newStart = Math.min(accumulatedTask.getStartOffset(), currentTask.getStartOffset()); int newEnd = Math.max(accumulatedTask.getEndOffset(), currentTask.getEndOffset()); RangeMarker rangeMarker; if (accumulatedTask.getStartOffset() == newStart && accumulatedTask.getEndOffset() == newEnd) { rangeMarker = accumulatedTask.getRange(); } else if (currentTask.getStartOffset() == newStart && currentTask.getEndOffset() == newEnd) { rangeMarker = currentTask.getRange(); } else { rangeMarker = document.createRangeMarker(newStart, newEnd); } if (withLeadingWhitespace) { accumulatedTask = new ReformatWithHeadingWhitespaceTask(rangeMarker); } else { accumulatedTask = new ReformatTask(rangeMarker); } } else if (currentTask instanceof ReindentTask) { iterator.remove(); } // TODO[ik]: need to be fixed to correctly process indent inside indent } } if (accumulatedTask != null) { if (accumulatedTask instanceof ReindentTask) { indentActions.add((ReindentTask) accumulatedTask); } else { freeFormatingActions.add(accumulatedTask); } } final List<PostponedAction> result = new ArrayList<PostponedAction>(); Collections.reverse(freeFormatingActions); Collections.reverse(indentActions); if (!freeFormatingActions.isEmpty()) { FormatTextRanges ranges = new FormatTextRanges(); for (PostprocessFormattingTask action : freeFormatingActions) { TextRange range = TextRange.create(action); ranges.add(range, action instanceof ReformatWithHeadingWhitespaceTask); } result.add(new ReformatRangesAction(ranges)); } if (!indentActions.isEmpty()) { ReindentRangesAction reindentRangesAction = new ReindentRangesAction(); for (ReindentTask action : indentActions) { reindentRangesAction.add(action.getRange(), action.getOldIndent()); } result.add(reindentRangesAction); } return result; }
private List<Pair<StubBasedPsiElementBase, CompositeElement>> calcStubAstBindings( final ASTNode root, final Document cachedDocument) { final StubTree stubTree = derefStub(); if (stubTree == null) { return Collections.emptyList(); } final Iterator<StubElement<?>> stubs = stubTree.getPlainList().iterator(); stubs.next(); // Skip file stub; final List<Pair<StubBasedPsiElementBase, CompositeElement>> result = ContainerUtil.newArrayList(); final StubBuilder builder = ((IStubFileElementType) getContentElementType()).getBuilder(); LazyParseableElement.setSuppressEagerPsiCreation(true); try { ((TreeElement) root) .acceptTree( new RecursiveTreeElementWalkingVisitor() { @Override protected void visitNode(TreeElement node) { CompositeElement parent = node.getTreeParent(); if (parent != null && builder.skipChildProcessingWhenBuildingStubs(parent, node)) { return; } IElementType type = node.getElementType(); if (type instanceof IStubElementType && ((IStubElementType) type).shouldCreateStub(node)) { if (!stubs.hasNext()) { reportStubAstMismatch( "Stub list is less than AST, last AST element: " + node.getElementType() + " " + node, stubTree, cachedDocument); } final StubElement stub = stubs.next(); if (stub.getStubType() != node.getElementType()) { reportStubAstMismatch( "Stub and PSI element type mismatch in " + getName() + ": stub " + stub + ", AST " + node.getElementType() + "; " + node, stubTree, cachedDocument); } PsiElement psi = stub.getPsi(); assert psi != null : "Stub " + stub + " (" + stub.getClass() + ") has returned null PSI"; result.add(Pair.create((StubBasedPsiElementBase) psi, (CompositeElement) node)); } super.visitNode(node); } }); } finally { LazyParseableElement.setSuppressEagerPsiCreation(false); } if (stubs.hasNext()) { reportStubAstMismatch( "Stub list in " + getName() + " has more elements than PSI", stubTree, cachedDocument); } return result; }