diff options
author | Jeff Johnston | 2013-07-17 23:00:15 +0000 |
---|---|---|
committer | Camilo Bernal | 2013-07-19 20:45:43 +0000 |
commit | d7bf84493f7aca3cff06b91675f245fc5a8a936f (patch) | |
tree | 5ef634e8c5a65a27dc3870313f519ef1b7695c43 /systemtap | |
parent | 7e271a1b8e03430e3f7c122d5583747c4fd16377 (diff) | |
download | org.eclipse.linuxtools-d7bf84493f7aca3cff06b91675f245fc5a8a936f.tar.gz org.eclipse.linuxtools-d7bf84493f7aca3cff06b91675f245fc5a8a936f.tar.xz org.eclipse.linuxtools-d7bf84493f7aca3cff06b91675f245fc5a8a936f.zip |
Add indent correction support to SystemTap editor.
- Add IndentHandler code to handle new indent command
- Add STP_STRING partition type to base partition scanner
- Fix SystemTap SimpleEditor to set key bindings to SystemTap context
- Fix SystemTap auto indent test to support STP_STRING partition
- Fix indenter to recognize assignments of strings that don't have
optional semi-colon as being complete
Change-Id: I490d4d8a6ab153ca7eb6d3b790e1341916f6293a
Reviewed-on: https://git.eclipse.org/r/14671
Tested-by: Hudson CI
Reviewed-by: Camilo Bernal <cabernal@redhat.com>
IP-Clean: Camilo Bernal <cabernal@redhat.com>
Tested-by: Camilo Bernal <cabernal@redhat.com>
Diffstat (limited to 'systemtap')
11 files changed, 591 insertions, 31 deletions
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.editor/src/org/eclipse/linuxtools/systemtap/ui/editor/SimpleEditor.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.editor/src/org/eclipse/linuxtools/systemtap/ui/editor/SimpleEditor.java index 16eecc2789..56094dac2a 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.editor/src/org/eclipse/linuxtools/systemtap/ui/editor/SimpleEditor.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.editor/src/org/eclipse/linuxtools/systemtap/ui/editor/SimpleEditor.java @@ -37,7 +37,7 @@ public class SimpleEditor extends TextEditor { public SimpleEditor() { super(); // make sure we inherit all the text editing commands (delete line etc). - setKeyBindingScopes(new String[] { "org.eclipse.ui.textEditorScope" }); //$NON-NLS-1$ + setKeyBindingScopes(new String[] { "org.eclipse.linuxtools.systemtap.ui.ide.context" }); //$NON-NLS-1$ internal_init(); } diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/editors/stp/STPFormattingTest.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/editors/stp/STPFormattingTest.java index 116db08670..c737211e82 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/editors/stp/STPFormattingTest.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/editors/stp/STPFormattingTest.java @@ -89,6 +89,7 @@ public class STPFormattingTest extends SystemtapTest{ tester.setAutoEditStrategy(IDocument.DEFAULT_CONTENT_TYPE, s); tester.setAutoEditStrategy(STPPartitionScanner.STP_COMMENT, s); tester.setAutoEditStrategy(STPPartitionScanner.STP_CONDITIONAL, s); + tester.setAutoEditStrategy(STPPartitionScanner.STP_STRING, s); return tester; } diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.properties b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.properties index d010b427f0..699b520fd1 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.properties +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.properties @@ -80,7 +80,10 @@ command.runChart.desc=Run the Script w/Chart command.toggleComment.name=Toggle Comment command.toggleComment.desc=Toggle Single Line SystemTap Comment command.toggleComment.mne=Tog&gle Comment +command.indent.name=Correct Indentation +command.indent.desc=Correct Indentation of SystemTap File Lines +command.indent.mne=Correct &Indentation editor.context.name=SystemTap Editor editor.context.desc=Editor for SystemTap Scripts -editor.category.source.name=Source
\ No newline at end of file +editor.category.source.name=Source diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.xml b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.xml index 85779eb11b..d6d391e9d1 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.xml +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/plugin.xml @@ -75,6 +75,16 @@ style="push"> </command> </menuContribution> + <menuContribution + allPopups="false" + locationURI="popup:#TextEditorContext?after=additions"> + <command + commandId="org.eclipse.linuxtools.systemtap.ui.ide.indent" + label="%command.indent.name" + mnemonic="%command.indent.mne" + style="push"> + </command> + </menuContribution> </extension> <extension @@ -162,8 +172,6 @@ description="%command.stop.desc" categoryId="org.eclipse.linuxtools.systemtap.ui.ide.category.run" id="org.eclipse.linuxtools.systemtap.ui.consolelog.commands.StopScript"/> - - <command name="%command.insertProbe.name" description="%command.insertProbe.desc" @@ -173,8 +181,7 @@ name="%command.insertFunction.name" description="%command.insertFunction.desc" categoryId="org.eclipse.linuxtools.systemtap.ui.ide.category.popup" - id="org.eclipse.linuxtools.systemtap.ui.ide.commands.functionaction"/> - + id="org.eclipse.linuxtools.systemtap.ui.ide.commands.functionaction"/> <category name="%category.file.name" description="%category.file.desc" @@ -187,23 +194,30 @@ name="%category.popup.name" description="%category.popup.desc" id="org.eclipse.linuxtools.systemtap.ui.ide.category.popup"/> - <command - defaultHandler="org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.RunScriptHandler" - description="%action.run.desc" - id="org.eclipse.linuxtools.systemtap.ui.ide.RunScriptCommand" - name="%action.run.name"> - </command> - <command - categoryId="org.eclipse.linuxtools.systemtap.ui.ide.category.source" - defaultHandler="org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.ToggleCommentHandler" - description="%command.toggleComment.desc" - id="org.eclipse.linuxtools.systemtap.ui.ide.toggleComment" - name="%command.toggleComment.name"> - </command> - <category - id="org.eclipse.linuxtools.systemtap.ui.ide.category.source" - name="%editor.category.source.name"> - </category> + <command + defaultHandler="org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.RunScriptHandler" + description="%action.run.desc" + id="org.eclipse.linuxtools.systemtap.ui.ide.RunScriptCommand" + name="%action.run.name"> + </command> + <category + id="org.eclipse.linuxtools.systemtap.ui.ide.category.source" + name="%editor.category.source.name"> + </category> + <command + categoryId="org.eclipse.linuxtools.systemtap.ui.ide.category.source" + defaultHandler="org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.ToggleCommentHandler" + description="%command.toggleComment.desc" + id="org.eclipse.linuxtools.systemtap.ui.ide.toggleComment" + name="%command.toggleComment.name"> + </command> + <command + categoryId="org.eclipse.linuxtools.systemtap.ui.ide.category.source" + defaultHandler="org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.IndentHandler" + description="%command.indent.desc" + id="org.eclipse.linuxtools.systemtap.ui.ide.indent" + name="%command.indent.name"> + </command> </extension> <extension point="org.eclipse.ui.actionSets"> @@ -366,6 +380,12 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M1+/"> </key> + <key + commandId="org.eclipse.linuxtools.systemtap.ui.ide.indent" + contextId="org.eclipse.linuxtools.systemtap.ui.ide.context" + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" + sequence="M1+I"> + </key> </extension> <extension point="org.eclipse.ui.contexts"> diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/IDEPlugin.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/IDEPlugin.java index d9e856013b..27692efc23 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/IDEPlugin.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/IDEPlugin.java @@ -50,6 +50,10 @@ public class IDEPlugin extends AbstractUIPlugin { plugin = this; } + public static String getPluginId() { + return PLUGIN_ID; + } + /** * Called by the Eclipse Workbench at plugin activation time. Starts the plugin lifecycle. */ diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/actions/IndentHandler.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/actions/IndentHandler.java new file mode 100644 index 0000000000..99fd8c1da5 --- /dev/null +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/actions/IndentHandler.java @@ -0,0 +1,505 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010, 2013 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) + * Red Hat Inc. - modified for use in SystemTap + *******************************************************************************/ +package org.eclipse.linuxtools.internal.systemtap.ui.ide.actions; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.IRewriteTarget; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.IDEPlugin; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.IndentUtil; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPDefaultCodeFormatterConstants; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPEditor; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPHeuristicScanner; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPIndenter; +import org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPPartitionScanner; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Indents a line or range of lines in a C document to its correct position. No + * complete AST must be present, the indentation is computed using heuristics. + * The algorithm used is fast for single lines, but does not store any + * information and therefore not so efficient for large line ranges. + * + * @see org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPHeuristicScanner + * @see org.eclipse.linuxtools.internal.systemtap.ui.ide.editors.stp.STPIndenter + */ +public class IndentHandler extends AbstractHandler { + /** The caret offset after an indent operation. */ + private int fCaretOffset; + + private class STPRunnable implements Runnable { + private ITextEditor editor; + + public STPRunnable(ITextEditor editor) { + this.editor = editor; + } + + public ITextEditor getTextEditor() { + return editor; + } + + @Override + public void run() { + // TODO Auto-generated method stub + + } + } + + /** + * Whether this is the action invoked by TAB. When <code>true</code>, + * indentation behaves differently to accommodate normal TAB operation. + */ + private final boolean fIsTabAction = false; + + @Override + public Object execute(ExecutionEvent event) { // Update has been called by + // the framework + if (!isEnabled()) + return null; + + ITextEditor editor = (ITextEditor) HandlerUtil.getActiveEditor(event); + if (editor == null || !editor.isEditable()) { + return null; + } + + ITextSelection selection = getSelection(editor); + final IDocument document = getDocument(editor); + + if (document != null) { + final int offset = selection.getOffset(); + final int length = selection.getLength(); + final Position end = new Position(offset + length); + final int firstLine, nLines; + fCaretOffset = -1; + + try { + firstLine = document.getLineOfOffset(offset); + // check for marginal (zero-length) lines + int minusOne = length == 0 ? 0 : 1; + nLines = document.getLineOfOffset(offset + length - minusOne) + - firstLine + 1; + document.addPosition(end); + } catch (BadLocationException e) { + // will only happen on concurrent modification + IDEPlugin.log(new Status(IStatus.ERROR, + IDEPlugin.getPluginId(), IStatus.OK, "", e)); //$NON-NLS-1$ + return null; + } + + Runnable runnable = new STPRunnable(editor) { + @Override + public void run() { + IRewriteTarget target = (IRewriteTarget) getTextEditor() + .getAdapter(IRewriteTarget.class); + if (target != null) + target.beginCompoundChange(); + + try { + STPHeuristicScanner scanner = new STPHeuristicScanner( + document); + STPIndenter indenter = new STPIndenter(document, + scanner, getProject(getTextEditor())); + final boolean multiLine = nLines > 1; + boolean hasChanged = false; + for (int i = 0; i < nLines; i++) { + hasChanged |= indentLine(document, getTextEditor(), + firstLine + i, offset, indenter, scanner, + multiLine); + } + + // update caret position: move to new position when + // indenting just one line + // keep selection when indenting multiple + int newOffset, newLength; + if (!fIsTabAction && multiLine) { + newOffset = offset; + newLength = end.getOffset() - offset; + } else { + newOffset = fCaretOffset; + newLength = 0; + } + + // always reset the selection if anything was replaced + // but not when we had a single line non-tab invocation + if (newOffset != -1 + && (hasChanged || newOffset != offset || newLength != length)) + selectAndReveal(getTextEditor(), newOffset, + newLength); + + } catch (BadLocationException e) { + // will only happen on concurrent modification + IDEPlugin.log(new Status(IStatus.ERROR, IDEPlugin + .getPluginId(), IStatus.OK, + "ConcurrentModification in IndentAction", e)); //$NON-NLS-1$ + } finally { + document.removePosition(end); + if (target != null) + target.endCompoundChange(); + } + } + }; + + if (nLines > 50) { + Display display = editor.getEditorSite().getWorkbenchWindow() + .getShell().getDisplay(); + BusyIndicator.showWhile(display, runnable); + } else { + runnable.run(); + } + } + + return null; + } + + /** + * Selects the given range on the editor. + * + * @param newOffset + * the selection offset + * @param newLength + * the selection range + */ + private void selectAndReveal(ITextEditor editor, int newOffset, + int newLength) { + Assert.isTrue(newOffset >= 0); + Assert.isTrue(newLength >= 0); + if (editor instanceof STPEditor) { + ISourceViewer viewer = ((STPEditor) editor).getMySourceViewer(); + if (viewer != null) + viewer.setSelectedRange(newOffset, newLength); + } else { + // this is too intrusive, but will never get called anyway + editor.selectAndReveal(newOffset, newLength); + } + } + + /** + * Indents a single line using the heuristic scanner. Multiline comments are + * indented as specified by the <code>CCommentAutoIndentStrategy</code>. + * + * @param document + * the document + * @param line + * the line to be indented + * @param caret + * the caret position + * @param indenter + * the indenter + * @param scanner + * the heuristic scanner + * @param multiLine + * <code>true</code> if more than one line is being indented + * @return <code>true</code> if <code>document</code> was modified, + * <code>false</code> otherwise + * @throws BadLocationException + * if the document got changed concurrently + */ + private boolean indentLine(IDocument document, ITextEditor editor, + int line, int caret, STPIndenter indenter, + STPHeuristicScanner scanner, boolean multiLine) + throws BadLocationException { + IRegion currentLine = document.getLineInformation(line); + int offset = currentLine.getOffset(); + int wsStart = offset; // where we start searching for non-WS; after the + // "//" in single line comments + + String indent = null; + if (offset < document.getLength()) { + ITypedRegion partition = TextUtilities.getPartition(document, + STPPartitionScanner.STP_PARTITIONING, offset, true); + ITypedRegion startingPartition = TextUtilities.getPartition( + document, STPPartitionScanner.STP_PARTITIONING, offset, + false); + String type = partition.getType(); + if (type.equals(STPPartitionScanner.STP_MULTILINE_COMMENT)) { + indent = computeCommentIndent(document, line, scanner, + startingPartition); + } else if (startingPartition.getType().equals( + STPPartitionScanner.STP_CONDITIONAL)) { + indent = computePreprocessorIndent(document, line, + startingPartition); + } else if (startingPartition.getType().equals( + STPPartitionScanner.STP_STRING) + && offset > startingPartition.getOffset()) { + // don't indent inside (raw-)string + return false; + } else if (!fIsTabAction + && startingPartition.getOffset() == offset + && startingPartition.getType().equals( + STPPartitionScanner.STP_COMMENT)) { + // line comment starting at position 0 -> indent inside + if (indentInsideLineComments()) { + int max = document.getLength() - offset; + int slashes = 2; + while (slashes < max - 1 + && document.get(offset + slashes, 2).equals("//")) //$NON-NLS-1$ + slashes += 2; + + wsStart = offset + slashes; + + StringBuilder computed = indenter + .computeIndentation(offset); + if (computed == null) + computed = new StringBuilder(0); + int tabSize = getTabSize(); + while (slashes > 0 && computed.length() > 0) { + char c = computed.charAt(0); + if (c == '\t') { + if (slashes > tabSize) + slashes -= tabSize; + else + break; + } else if (c == ' ') { + slashes--; + } else { + break; + } + + computed.deleteCharAt(0); + } + + indent = document.get(offset, wsStart - offset) + computed; + } + } + } + + // standard C code indentation + if (indent == null) { + StringBuilder computed = indenter.computeIndentation(offset); + if (computed != null) + indent = computed.toString(); + else + indent = ""; //$NON-NLS-1$ + } + + // change document: + // get current white space + int lineLength = currentLine.getLength(); + int end = scanner.findNonWhitespaceForwardInAnyPartition(wsStart, + offset + lineLength); + if (end == STPHeuristicScanner.NOT_FOUND) { + // an empty line + end = offset + lineLength; + if (multiLine && !indentEmptyLines()) + indent = ""; //$NON-NLS-1$ + } + int length = end - offset; + String currentIndent = document.get(offset, length); + + // set the caret offset so it can be used when setting the selection + if (caret >= offset && caret <= end) + fCaretOffset = offset + indent.length(); + else + fCaretOffset = -1; + + // only change the document if it is a real change + if (!indent.equals(currentIndent)) { + document.replace(offset, length, indent); + return true; + } + return false; + } + + /** + * Computes and returns the indentation for a block comment line. + * + * @param document + * the document + * @param line + * the line in document + * @param scanner + * the scanner + * @param partition + * the comment partition + * @return the indent, or <code>null</code> if not computable + * @throws BadLocationException + */ + private String computeCommentIndent(IDocument document, int line, + STPHeuristicScanner scanner, ITypedRegion partition) + throws BadLocationException { + return IndentUtil.computeCommentIndent(document, line, scanner, + partition); + } + + /** + * Computes and returns the indentation for a preprocessor line. + * + * @param document + * the document + * @param line + * the line in document + * @param partition + * the comment partition + * @return the indent, or <code>null</code> if not computable + * @throws BadLocationException + */ + private String computePreprocessorIndent(IDocument document, int line, + ITypedRegion partition) throws BadLocationException { + return IndentUtil.computePreprocessorIndent(document, line, partition); + } + + /** + * Returns the tab size used by the editor, which is deduced from the + * formatter preferences. + * + * @return the tab size as defined in the current formatter preferences + */ + private int getTabSize() { + return getCoreFormatterOption( + STPDefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4); + } + + /** + * Returns <code>true</code> if empty lines should be indented, + * <code>false</code> otherwise. + * + * @return <code>true</code> if empty lines should be indented, + * <code>false</code> otherwise + */ + private boolean indentEmptyLines() { + return STPDefaultCodeFormatterConstants.TRUE + .equals(getCoreFormatterOption(STPDefaultCodeFormatterConstants.FORMATTER_INDENT_EMPTY_LINES)); + } + + /** + * Returns <code>true</code> if line comments at column 0 should be indented + * inside, <code>false</code> otherwise. + * + * @return <code>true</code> if line comments at column 0 should be indented + * inside, <code>false</code> otherwise. + */ + private boolean indentInsideLineComments() { + return STPDefaultCodeFormatterConstants.TRUE + .equals(getCoreFormatterOption(STPDefaultCodeFormatterConstants.FORMATTER_INDENT_INSIDE_LINE_COMMENTS)); + } + + /** + * Returns the possibly project-specific core preference defined under + * <code>key</code>. + * + * @param key + * the key of the preference + * @return the value of the preference + */ + private String getCoreFormatterOption(String key) { + return "false"; //$NON-NLS-1$ + } + + /** + * Returns the possibly project-specific core preference defined under + * <code>key</code>, or <code>def</code> if the value is not a integer. + * + * @param key + * the key of the preference + * @param def + * the default value + * @return the value of the preference + */ + private int getCoreFormatterOption(String key, int def) { + try { + return Integer.parseInt(getCoreFormatterOption(key)); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * Returns the <code>IProject</code> of the current editor input, or + * <code>null</code> if it cannot be found. + * + * @return the <code>IProject</code> of the current editor input, or + * <code>null</code> if it cannot be found + */ + private IProject getProject(ITextEditor editor) { + if (editor == null) + return null; + + IEditorInput input = editor.getEditorInput(); + if (input instanceof IFileEditorInput) + return ((IFileEditorInput) input).getFile().getProject(); + return null; + } + + /** + * Returns the editor's selection provider. + * + * @return the editor's selection provider or <code>null</code> + */ + private ISelectionProvider getSelectionProvider(ITextEditor editor) { + if (editor != null) { + return editor.getSelectionProvider(); + } + return null; + } + + /* + * @see org.eclipse.ui.texteditor.IUpdate#update() + */ + + /** + * Returns the document currently displayed in the editor, or + * <code>null</code> if none can be obtained. + * + * @return the current document or <code>null</code> + */ + private IDocument getDocument(ITextEditor editor) { + if (editor != null) { + IDocumentProvider provider = editor.getDocumentProvider(); + IEditorInput input = editor.getEditorInput(); + if (provider != null && input != null) + return provider.getDocument(input); + + } + return null; + } + + /** + * Returns the selection on the editor or an invalid selection if none can + * be obtained. Returns never <code>null</code>. + * + * @return the current selection, never <code>null</code> + */ + private ITextSelection getSelection(ITextEditor editor) { + ISelectionProvider provider = getSelectionProvider(editor); + if (provider != null) { + ISelection selection = provider.getSelection(); + if (selection instanceof ITextSelection) + return (ITextSelection) selection; + } + + // null object + return TextSelection.emptySelection(); + } +} diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/IndentUtil.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/IndentUtil.java index 6631619f29..a3739caab1 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/IndentUtil.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/IndentUtil.java @@ -436,7 +436,7 @@ public final class IndentUtil { ITypedRegion partition= TextUtilities.getPartition(document, STPPartitionScanner.STP_PARTITIONING, offset, true); ITypedRegion startingPartition= TextUtilities.getPartition(document, STPPartitionScanner.STP_PARTITIONING, offset, false); String type= partition.getType(); - if (type.equals(STPPartitionScanner.STP_COMMENT)) { + if (type.equals(STPPartitionScanner.STP_MULTILINE_COMMENT)) { indent= computeCommentIndent(document, line, scanner, startingPartition); } else if (startingPartition.getType().equals(STPPartitionScanner.STP_CONDITIONAL)) { indent= computePreprocessorIndent(document, line, startingPartition); diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPAutoEditStrategy.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPAutoEditStrategy.java index 0f46486c9d..a5bb1acc52 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPAutoEditStrategy.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPAutoEditStrategy.java @@ -114,8 +114,11 @@ public class STPAutoEditStrategy extends return false; try { ITypedRegion partition= TextUtilities.getPartition(d, fPartitioning, c.offset, false); + String partitionType = partition.getType(); if (c.offset > 0 && - STPPartitionScanner.STP_COMMENT.equals(partition.getType())) { + (STPPartitionScanner.STP_COMMENT.equals(partitionType) + || STPPartitionScanner.STP_MULTILINE_COMMENT.equals(partitionType) + || STPPartitionScanner.STP_STRING.equals(partitionType))) { return true; } IRegion lineInfo = d.getLineInformationOfOffset(c.offset); diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPIndenter.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPIndenter.java index b65a9e53ec..47ae6044ba 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPIndenter.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPIndenter.java @@ -24,8 +24,11 @@ import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; import org.eclipse.linuxtools.internal.systemtap.ui.ide.IDEPlugin; /** @@ -1041,10 +1044,25 @@ public final class STPIndenter { return NOT_FOUND; case STPSymbols.TokenEQUAL: - // indent assignments + // indent assignments, but don't do so if there is a String + // after the assignment because SystemTap doesn't require + // semi-colons to end lines and so this should be treated as + // a complete assignment. + pos = fPosition; + while (pos < offset) { + try { + ITypedRegion partition = ((IDocumentExtension3)fDocument).getPartition(STPPartitionScanner.STP_PARTITIONING, pos, danglingElse); + if (STPPartitionScanner.STP_STRING.equals(partition.getType())) + return skipToStatementStart(danglingElse, false); + pos = partition.getOffset() + partition.getLength(); + } catch (BadLocationException e) { + break; + } catch (BadPartitioningException e) { + break; + } + } fIndent= fPrefs.prefAssignmentIndent; return fPosition; - case STPSymbols.TokenCOLON: pos= fPosition; if (looksLikeCaseStatement()) { diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPPartitionScanner.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPPartitionScanner.java index 8138f67edc..b937d0f59c 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPPartitionScanner.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPPartitionScanner.java @@ -19,17 +19,20 @@ import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.IWordDetector; import org.eclipse.jface.text.rules.MultiLineRule; import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.SingleLineRule; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.rules.WordRule; public class STPPartitionScanner extends RuleBasedPartitionScanner { public final static String STP_PARTITIONING = "__stp_partitioning"; //$NON-NLS-1$ + public final static String STP_STRING = "__stp_string"; //$NON-NLS-1$ public final static String STP_COMMENT = "__stp_comment"; //$NON-NLS-1$ public final static String STP_CONDITIONAL = "__stp_conditional"; //$NON-NLS-1$ + public final static String STP_MULTILINE_COMMENT = "__stp_multiline_comment"; //$NON-NLS-1$ public static String[] STP_PARTITION_TYPES = { IDocument.DEFAULT_CONTENT_TYPE, - STP_COMMENT, STP_CONDITIONAL}; + STP_COMMENT, STP_MULTILINE_COMMENT, STP_STRING, STP_CONDITIONAL}; /** * Detect empty comments @@ -73,16 +76,19 @@ public class STPPartitionScanner extends RuleBasedPartitionScanner { public STPPartitionScanner() { IToken stpComment = new Token(STP_COMMENT); + IToken stpMultilineComment = new Token(STP_MULTILINE_COMMENT); IToken stpConditional = new Token(STP_CONDITIONAL); + IToken stpString = new Token(STP_STRING); // Add special case word rule. EmptyCommentRule emptyCommentRule= new EmptyCommentRule(stpComment); setPredicateRules(new IPredicateRule[] { new EndOfLineRule("//", stpComment), //$NON-NLS-1$ - new MultiLineRule("/*", "*/", stpComment), //$NON-NLS-1$//$NON-NLS-2$ + new MultiLineRule("/*", "*/", stpMultilineComment), //$NON-NLS-1$//$NON-NLS-2$ new EndOfLineRule("#", stpComment), //$NON-NLS-1$ - emptyCommentRule, + emptyCommentRule, + new SingleLineRule("\"", "\"", stpString, '\\', false, true), //$NON-NLS-1$ //$NON-NLS-2$ new EndOfLineRule("#if", stpConditional), //$NON-NLS-1$ new EndOfLineRule("#else", stpConditional), //$NON-NLS-1$ new EndOfLineRule("#endif", stpConditional), //$NON-NLS-1$ diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPProbeScanner.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPProbeScanner.java index 2a6b7a45e2..fcd4358843 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPProbeScanner.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/editors/stp/STPProbeScanner.java @@ -47,7 +47,7 @@ public class STPProbeScanner extends RuleBasedPartitionScanner { new EndOfLineRule("#else", stpConditional), //$NON-NLS-1$ new EndOfLineRule("#endif", stpConditional), //$NON-NLS-1$ new EndOfLineRule("#define", stpConditional), //$NON-NLS-1$ - new SingleLineRule("\"", "\"", stpString, '\\'), //$NON-NLS-1$ //$NON-NLS-2$ + new SingleLineRule("\"", "\"", stpString, '\\', false, true), //$NON-NLS-1$ //$NON-NLS-2$ new SingleLineRule("'", "'", stpString, '\\'), //$NON-NLS-1$ //$NON-NLS-2$ new MultiLineRule("probe", "}", stpProbe), //$NON-NLS-1$ //$NON-NLS-2$ }); |