diff options
author | Milos Kleint | 2011-01-21 16:25:45 +0000 |
---|---|---|
committer | Milos Kleint | 2011-01-21 17:01:31 +0000 |
commit | 525ec3f15a8ac37fb56dfa505a89bb976d560985 (patch) | |
tree | 17373023f71cd953aadcab2521404737fba5ce98 /org.eclipse.m2e.editor.xml | |
parent | 8a3b872c4ac00c637ebc51c10e614376bba6a70f (diff) | |
download | m2e-core-525ec3f15a8ac37fb56dfa505a89bb976d560985.tar.gz m2e-core-525ec3f15a8ac37fb56dfa505a89bb976d560985.tar.xz m2e-core-525ec3f15a8ac37fb56dfa505a89bb976d560985.zip |
rewrite InsertArtifactProposal not to manually insert strings into document.
Diffstat (limited to 'org.eclipse.m2e.editor.xml')
2 files changed, 193 insertions, 171 deletions
diff --git a/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/InsertArtifactProposal.java b/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/InsertArtifactProposal.java index 146228d4..82f39f0d 100644 --- a/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/InsertArtifactProposal.java +++ b/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/InsertArtifactProposal.java @@ -11,6 +11,15 @@ package org.eclipse.m2e.editor.xml; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.elementAtOffset; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.findChild; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.format; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.getChild; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.insertAt; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.performOnDOMDocument; +import static org.eclipse.m2e.editor.xml.internal.PomEdits.setText; + +import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -19,11 +28,12 @@ import org.apache.maven.model.DependencyManagement; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginManagement; import org.apache.maven.project.MavenProject; +import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.contentassist.ICompletionProposal; @@ -35,7 +45,6 @@ import org.eclipse.jface.window.Window; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML; import org.eclipse.m2e.core.core.MavenLogger; import org.eclipse.m2e.core.embedder.ArtifactKey; @@ -43,6 +52,8 @@ import org.eclipse.m2e.core.index.IIndex; import org.eclipse.m2e.core.index.IndexedArtifactFile; import org.eclipse.m2e.core.ui.dialogs.MavenRepositorySearchDialog; import org.eclipse.m2e.editor.xml.internal.Messages; +import org.eclipse.m2e.editor.xml.internal.PomEdits.Operation; +import org.eclipse.m2e.editor.xml.internal.PomEdits.OperationTuple; import org.eclipse.m2e.editor.xml.internal.XmlUtils; public class InsertArtifactProposal implements ICompletionProposal, ICompletionProposalExtension4, ICompletionProposalExtension5 { @@ -63,7 +74,7 @@ public class InsertArtifactProposal implements ICompletionProposal, ICompletionP public void apply(IDocument document) { MavenProject prj = XmlUtils.extractMavenProject(sourceViewer); - Set<ArtifactKey> managedKeys = new HashSet<ArtifactKey>(); + final Set<ArtifactKey> managedKeys = new HashSet<ArtifactKey>(); Set<ArtifactKey> usedKeys = new HashSet<ArtifactKey>(); if (config.getType() == SearchType.PLUGIN) { //only populate the lists when in plugin search.. @@ -105,144 +116,133 @@ public class InsertArtifactProposal implements ICompletionProposal, ICompletionP dialog.setQuery(config.getInitiaSearchString()); } if(dialog.open() == Window.OK) { - String lineDelim = document.getLegalLineDelimiters()[0];//do we care? or just append \n always? - IndexedArtifactFile af = (IndexedArtifactFile) dialog.getFirstResult(); + final IndexedArtifactFile af = (IndexedArtifactFile) dialog.getFirstResult(); int offset = region.getOffset(); if(af != null) { if (config.getType() == SearchType.PARENT) { try { - StringBuffer buffer = new StringBuffer(); - buffer.append("<parent>").append(lineDelim); //$NON-NLS-1$ - buffer.append("<groupId>").append(af.group).append("</groupId>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<artifactId>").append(af.artifact).append("</artifactId>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<version>").append(af.version).append("</version>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - String relativePath = PomContentAssistProcessor.findRelativePath(sourceViewer, af.group, af.artifact, af.version); - if (relativePath != null) { - buffer.append("<relativePath>").append(relativePath).append("</relativePath>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - } - buffer.append("</parent>").append(lineDelim); //$NON-NLS-1$ - generatedLength = buffer.toString().length(); - document.replace(offset, region.getLength(), buffer.toString()); - - Region resRegion = format(document, generatedOffset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch(BadLocationException e) { + final int fOffset = offset; + performOnDOMDocument(new OperationTuple(document, new Operation() { + public void process(Document doc) { + Element parent = insertAt(doc.createElement("parent"), fOffset); + setText(getChild(parent, "groupId"), af.group); + setText(getChild(parent, "artifactId"), af.artifact); + setText(getChild(parent, "version"), af.version); + String relativePath = PomContentAssistProcessor.findRelativePath(sourceViewer, af.group, af.artifact, af.version); + if (relativePath != null) { + setText(getChild(parent, "relativePath"), relativePath); + } + format(parent); + generatedOffset = ((IndexedRegion)parent).getStartOffset(); + generatedLength = ((IndexedRegion)parent).getEndOffset() - generatedOffset; + } + })); + } catch(IOException e) { + MavenLogger.log("Failed inserting parent element", e); //$NON-NLS-1$ + } catch(CoreException e) { MavenLogger.log("Failed inserting parent element", e); //$NON-NLS-1$ } } // plugin type - if (config.getType() == SearchType.PLUGIN) { - Node current = config.getCurrentNode(); - if ("project".equals(current.getNodeName())) { //$NON-NLS-1$ - //in project section go with build/plugins. - Element build = XmlUtils.findChild((Element)current, "build"); //$NON-NLS-1$ - if (build == null) { - try { - StringBuffer buffer = new StringBuffer(); - generateBuild(buffer, lineDelim, af, skipVersion(current, af, managedKeys, config.getType())); - generatedLength = buffer.toString().length(); - document.replace(offset, 0, buffer.toString()); - - Region resRegion = format(document, generatedOffset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch (BadLocationException e) { - MavenLogger.log("Failed inserting build element", e); //$NON-NLS-1$ - } - return; - } else { - current = build; - IndexedRegion reg = (IndexedRegion)current; - //we need to update the offset to where we found the existing build element.. - offset = reg.getEndOffset() - "</build>".length(); //$NON-NLS-1$ - } - } - if ("build".equals(current.getNodeName()) || "pluginManagement".equals(current.getNodeName())) { //$NON-NLS-1$ //$NON-NLS-2$ - Element plugins = XmlUtils.findChild((Element)current, "plugins"); //$NON-NLS-1$ - if (plugins == null) { - //we need to create it. - try { - StringBuffer buffer = new StringBuffer(); - generateArtifacts(config.getType(), buffer, lineDelim, af, skipVersion(current, af, managedKeys, config.getType())); - generatedLength = buffer.toString().length(); - document.replace(offset, 0, buffer.toString()); - - Region resRegion = format(document, offset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch (BadLocationException e) { - MavenLogger.log("Failed inserting plugins element", e); //$NON-NLS-1$ + if(config.getType() == SearchType.PLUGIN) { + try { + final int fOffset = offset; + performOnDOMDocument(new OperationTuple(document, new Operation() { + public void process(Document doc) { + Element currentNode = elementAtOffset(doc, fOffset); + if (currentNode == null) { + return; + } + String currentName = currentNode.getNodeName(); + Element plugin = null; + Element toFormat = null; + if("project".equals(currentName)) { //$NON-NLS-1$ + Element build = findChild(currentNode, "build"); + if(build == null) { + build = insertAt(doc.createElement("build"), fOffset); + toFormat = build; + } + Element plugins = getChild(build, "plugins"); + plugin = doc.createElement("plugin"); + plugins.appendChild(plugin); + } + if("build".equals(currentName) || "pluginManagement".equals(currentName)) { //$NON-NLS-1$ //$NON-NLS-2$ + Element plugins = findChild(currentNode, "plugins"); + if(plugins == null) { + plugins = insertAt(doc.createElement("plugins"), fOffset); + toFormat = plugins; + } + plugin = doc.createElement("plugin"); + plugins.appendChild(plugin); + } + if("plugins".equals(currentName)) { + plugin = insertAt(doc.createElement("plugin"), fOffset); + } + if (toFormat == null) { + toFormat = plugin; + } + setText(getChild(plugin, "groupId"), af.group); + setText(getChild(plugin, "artifactId"), af.artifact); + if (!skipVersion(plugin.getParentNode(), af, managedKeys, config.getType())) { + setText(getChild(plugin, "version"), af.version); + } + format(toFormat); + generatedOffset = ((IndexedRegion)toFormat).getStartOffset(); + generatedLength = ((IndexedRegion)toFormat).getEndOffset() - generatedOffset; } - return; - } else { - current = plugins; - IndexedRegion reg = (IndexedRegion)current; - //we need to update the offset to where we found the existing plugins element.. - offset = reg.getEndOffset() - "</plugins>".length(); //$NON-NLS-1$ - } - } - if ("plugins".equals(current.getNodeName())) { //$NON-NLS-1$ - //simple, just add the plugin here.. - //TODO we might want to look if the plugin is already defined in this section or not.. - try { - StringBuffer buffer = new StringBuffer(); - generateArtifact(config.getType(), buffer, lineDelim, af, skipVersion(current, af, managedKeys, config.getType())); - generatedLength = buffer.toString().length(); - document.replace(offset, 0, buffer.toString()); - Region resRegion = format(document, offset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch (BadLocationException e) { - MavenLogger.log("Failed inserting plugin element", e); //$NON-NLS-1$ - } + })); + } catch(IOException e) { + MavenLogger.log("Failed inserting plugin element", e); //$NON-NLS-1$ + } catch(CoreException e) { + MavenLogger.log("Failed inserting plugin element", e); //$NON-NLS-1$ } } // dependency type if (config.getType() == SearchType.DEPENDENCY) { - Node current = config.getCurrentNode(); - if ("project".equals(current.getNodeName()) || "dependencyManagement".equals(current.getNodeName()) || "profile".equals(current.getNodeName())) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - //in project section go with dependencies section. - Element deps = XmlUtils.findChild((Element)current, "dependencies"); //$NON-NLS-1$ - if (deps == null) { - try { - StringBuffer buffer = new StringBuffer(); - generateArtifacts(config.getType(), buffer, lineDelim, af, skipVersion(current, af, managedKeys, config.getType())); - generatedLength = buffer.toString().length(); - document.replace(offset, 0, buffer.toString()); - - Region resRegion = format(document, generatedOffset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch (BadLocationException e) { - MavenLogger.log("Failed inserting dependencies element", e); //$NON-NLS-1$ + try { + final int fOffset = offset; + performOnDOMDocument(new OperationTuple(document, new Operation() { + public void process(Document doc) { + Element currentNode = elementAtOffset(doc, fOffset); + if (currentNode == null) { + return; + } + String currentName = currentNode.getNodeName(); + Element dependency = null; + Element toFormat = null; + if("project".equals(currentName) || "dependencyManagement".equals(currentName) || "profile".equals(currentName)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Element deps = findChild(currentNode, "dependencies"); + if(deps == null) { + deps = insertAt(doc.createElement("dependencies"), fOffset); + toFormat = deps; + } + dependency = doc.createElement("dependency"); + deps.appendChild(dependency); + } + if("dependencies".equals(currentName)) { + dependency = insertAt(doc.createElement("dependency"), fOffset); + } + if (toFormat == null) { + toFormat = dependency; + } + setText(getChild(dependency, "groupId"), af.group); + setText(getChild(dependency, "artifactId"), af.artifact); + if (!skipVersion(dependency.getParentNode(), af, managedKeys, config.getType())) { + setText(getChild(dependency, "version"), af.version); + } + format(toFormat); + generatedOffset = ((IndexedRegion)toFormat).getStartOffset(); + generatedLength = ((IndexedRegion)toFormat).getEndOffset() - generatedOffset; } - return; - } else { - current = deps; - IndexedRegion reg = (IndexedRegion)current; - //we need to update the offset to where we found the existing dependencies element.. - offset = reg.getEndOffset() - "</dependencies>".length(); //$NON-NLS-1$ - } - } - if ("dependencies".equals(current.getNodeName())) { //$NON-NLS-1$ - //simple, just add the dependency here.. - //TODO we might want to look if the dependency is already defined in this section or not.. - try { - StringBuffer buffer = new StringBuffer(); - generateArtifact(config.getType(), buffer, lineDelim, af, skipVersion(current, af, managedKeys, config.getType())); - generatedLength = buffer.toString().length(); - document.replace(offset, 0, buffer.toString()); - Region resRegion = format(document, offset, generatedLength); - generatedOffset = resRegion.getOffset(); - generatedLength = resRegion.getLength(); - } catch (BadLocationException e) { - MavenLogger.log("Failed inserting dependency element", e); //$NON-NLS-1$ - } - } + })); + } catch(IOException e) { + MavenLogger.log("Failed inserting dependency element", e); //$NON-NLS-1$ + } catch(CoreException e) { + MavenLogger.log("Failed inserting dependency element", e); //$NON-NLS-1$ + } } } } @@ -271,52 +271,6 @@ public class InsertArtifactProposal implements ICompletionProposal, ICompletionP return managedList.contains(key); } - private void generateArtifact(SearchType type, StringBuffer buffer, String lineDelim, IndexedArtifactFile af, boolean skipVersion) { - assert type == SearchType.PLUGIN || type == SearchType.DEPENDENCY; - String rootElement = type == SearchType.PLUGIN ? "plugin" : "dependency"; //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<" + rootElement + ">").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<groupId>").append(af.group).append("</groupId>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<artifactId>").append(af.artifact).append("</artifactId>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - //for managed plugins (if version matches only?), don't add the version element - if (!skipVersion) { - buffer.append("<version>").append(af.version).append("</version>").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - } - buffer.append("</" + rootElement + ">").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - } - - private void generateArtifacts(SearchType type, StringBuffer buffer, String lineDelim, IndexedArtifactFile af, boolean skipVersion) { - assert type == SearchType.PLUGIN || type == SearchType.DEPENDENCY; - String rootElement = type == SearchType.PLUGIN ? "plugins" : "dependencies"; //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append("<" + rootElement + ">").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - generateArtifact(type, buffer, lineDelim, af, skipVersion); - buffer.append("</" + rootElement + ">").append(lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - } - - private void generateBuild(StringBuffer buffer, String lineDelim, IndexedArtifactFile af, boolean skipVersion) { - buffer.append("<build>").append(lineDelim); //$NON-NLS-1$ - generateArtifacts(SearchType.PLUGIN, buffer, lineDelim, af, skipVersion); - buffer.append("</build>").append(lineDelim); //$NON-NLS-1$ - } - - /** - * take the document and format the region specified by the supplied formatter. - * operates on whole line (determined by the region specified) - * returns the new region encompassing the original region after formatting - */ - public static Region format(IDocument document, int offset, int length) throws BadLocationException { - int startLine = document.getLineOfOffset(offset); - int endLine = document.getLineOfOffset(offset + length - 1); // -1 to make sure to be before the end of line char - int startLineOffset = document.getLineOffset(startLine); - try { - new FormatProcessorXML().formatDocument(document, offset, length); - } catch(Exception e) { - MavenLogger.log("Failed to format generated code", e); - } -// formatter.format(document, new Region(startLineOffset, (document.getLineOffset(endLine) + document.getLineLength(endLine)) - startLineOffset)); - startLineOffset = document.getLineOffset(startLine); //should be same, just being paranoid - return new Region (startLineOffset, (document.getLineOffset(endLine) + document.getLineLength(endLine)) - startLineOffset); - } - public Point getSelection(IDocument document) { return new Point(generatedOffset, generatedLength); } diff --git a/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/internal/PomEdits.java b/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/internal/PomEdits.java index e9e27f7b..5e5dfa10 100644 --- a/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/internal/PomEdits.java +++ b/org.eclipse.m2e.editor.xml/src/main/java/org/eclipse/m2e/editor/xml/internal/PomEdits.java @@ -24,9 +24,17 @@ import org.w3c.dom.Text; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.DocumentRewriteSession; +import org.eclipse.jface.text.DocumentRewriteSessionType; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension4; import org.eclipse.wst.sse.core.StructuredModelManager; +import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; +import org.eclipse.wst.sse.core.internal.text.rules.IStructuredRegion; import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML; @@ -260,6 +268,54 @@ public class PomEdits { } } + public static Element insertAt(Element newElement, int offset) { + Document doc = newElement.getOwnerDocument(); + if (doc instanceof IDOMDocument) { + IDOMDocument domDoc = (IDOMDocument) doc; + IndexedRegion ir = domDoc.getModel().getIndexedRegion(offset); + Node parent = ((Node)ir).getParentNode(); + if (ir instanceof Text) { + Text txt = (Text)ir; + String data = txt.getData(); + int dataSplitIndex = offset - ir.getStartOffset(); + String beforeText = data.substring(0, dataSplitIndex); + String afterText = data.substring(dataSplitIndex); + Text after = doc.createTextNode(afterText); + Text before = doc.createTextNode(beforeText); + parent.replaceChild(after, txt); + parent.insertBefore(newElement, after); + parent.insertBefore(before, newElement); + } else { + parent.appendChild(newElement); + } + } else { + throw new IllegalArgumentException(); + } + return newElement; + } + + /** + * finds the element at offset, if other type of node at offset, will return it's parent element (if any) + * @param doc + * @param offset + * @return + */ + public static Element elementAtOffset(Document doc, int offset) { + if (doc instanceof IDOMDocument) { + IDOMDocument domDoc = (IDOMDocument) doc; + IndexedRegion ir = domDoc.getModel().getIndexedRegion(offset); + if (ir instanceof Element) { + return (Element) ir; + } else { + Node parent = ((Node)ir).getParentNode(); + if (parent instanceof Element) { + return (Element) parent; + } + } + } + return null; + } + /** * formats the node (and content). please make sure to only format the node you have created.. * @param newNode @@ -291,17 +347,29 @@ public class PomEdits { domModel = tuple.getFile() != null ? (IDOMModel) StructuredModelManager.getModelManager().getModelForEdit(tuple.getFile()) : (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForEdit(tuple.getDocument()); //existing shall be ok here.. - domModel.aboutToChangeModel(); + //let the model know we make changes + domModel.aboutToChangeModel(); IStructuredTextUndoManager undo = domModel.getStructuredDocument().getUndoManager(); + DocumentRewriteSession session = null; + //let the document know we make changes + if (domModel.getStructuredDocument() instanceof IDocumentExtension4) { + IDocumentExtension4 ext4 = (IDocumentExtension4)domModel.getStructuredDocument(); + session = ext4.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED_SMALL); + } undo.beginRecording(domModel); try { tuple.getOperation().process(domModel.getDocument()); } finally { undo.endRecording(domModel); + if (session != null && domModel.getStructuredDocument() instanceof IDocumentExtension4) { + IDocumentExtension4 ext4 = (IDocumentExtension4)domModel.getStructuredDocument(); + ext4.stopRewriteSession(session); + } domModel.changedModel(); } } finally { if(domModel != null) { + //for ducuments saving shall only happen when the model is not held elsewhere (eg. in opened view) //for files, save always if(tuple.getFile() != null || domModel.getReferenceCountForEdit() == 1) { |