You can subscribe to this list here.
| 2005 |
Jan
|
Feb
|
Mar
(41) |
Apr
(9) |
May
|
Jun
|
Jul
(39) |
Aug
(38) |
Sep
(135) |
Oct
(220) |
Nov
(75) |
Dec
(74) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2006 |
Jan
(44) |
Feb
(160) |
Mar
(49) |
Apr
(69) |
May
(40) |
Jun
(52) |
Jul
(47) |
Aug
(51) |
Sep
(19) |
Oct
(22) |
Nov
(36) |
Dec
(76) |
| 2007 |
Jan
(154) |
Feb
(165) |
Mar
(186) |
Apr
(143) |
May
(175) |
Jun
(133) |
Jul
(203) |
Aug
(177) |
Sep
(136) |
Oct
|
Nov
|
Dec
|
|
From: <caw...@us...> - 2007-05-03 16:00:10
|
Revision: 2422
http://svn.sourceforge.net/rubyeclipse/?rev=2422&view=rev
Author: cawilliams
Date: 2007-05-03 09:00:08 -0700 (Thu, 03 May 2007)
Log Message:
-----------
make test unit test case wizard actually show up in New > File menu.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.testunit/plugin.xml
Modified: trunk/org.rubypeople.rdt.testunit/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.testunit/plugin.xml 2007-05-03 13:45:21 UTC (rev 2421)
+++ trunk/org.rubypeople.rdt.testunit/plugin.xml 2007-05-03 16:00:08 UTC (rev 2422)
@@ -23,6 +23,8 @@
<perspectiveExtension
targetID="org.rubypeople.rdt.ui.PerspectiveRuby">
<viewShortcut id="org.rubypeople.rdt.testunit.views.TestUnitView"/>
+ <newWizardShortcut id="org.rubypeople.rdt.testunit.wizards.RubyNewTestCaseWizard">
+ </newWizardShortcut>
<view
relative="org.eclipse.ui.views.ContentOutline"
relationship="stack"
@@ -141,10 +143,15 @@
<extension
point="org.eclipse.ui.newWizards">
+ <category
+ name="%WizardCategory.name"
+ parentCategory="org.rubypeople.rdt.ui"
+ id="org.rubypeople.rdt.testunit">
+ </category>
<wizard
name="%NewWizardRubyTestCase.name"
icon="$nl$/icons/full/etool16/new_testcase.gif"
- category="org.rubypeople.rdt.ui"
+ category="org.rubypeople.rdt.testunit"
class="org.rubypeople.rdt.internal.testunit.wizards.NewTestCaseCreationWizard"
preferredPerspectives="org.rubypeople.rdt.ui.PerspectiveRuby"
id="org.rubypeople.rdt.testunit.wizards.RubyNewTestCaseWizard">
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-03 13:45:23
|
Revision: 2421
http://svn.sourceforge.net/rubyeclipse/?rev=2421&view=rev
Author: cawilliams
Date: 2007-05-03 06:45:21 -0700 (Thu, 03 May 2007)
Log Message:
-----------
clean up the hack I had in before for rdebug-ide to work without using cmd.exe on windows. I was inserting the debugger arguments and filename in the wrong places in the command line (that only worked for simple command lines), and rdebug-ide would try to parse out options for the file we were debugging!
The upshot is that now we handle more complex command lines like those that happen under the hood of RadRails when invoking a webserver under debug mode.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RDebugVMDebugger.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMDebugger.java
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RDebugVMDebugger.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RDebugVMDebugger.java 2007-05-02 19:04:01 UTC (rev 2420)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RDebugVMDebugger.java 2007-05-03 13:45:21 UTC (rev 2421)
@@ -2,16 +2,11 @@
import java.io.File;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.debug.core.ILaunch;
import org.rubypeople.rdt.internal.debug.core.RubyDebuggerProxy;
import org.rubypeople.rdt.internal.debug.core.model.RubyDebugTarget;
-import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants;
import org.rubypeople.rdt.launching.IVMInstall;
import org.rubypeople.rdt.launching.VMRunnerConfiguration;
@@ -24,16 +19,27 @@
public RDebugVMDebugger(IVMInstall vmInstance) {
super(vmInstance);
}
-
+
@Override
protected List<String> constructProgramString(VMRunnerConfiguration config) throws CoreException {
- List<String> string = super.constructProgramString(config);
- string.add(findRDebugExecutable(fVMInstance.getInstallLocation()));
- return string;
+ String[] args = config.getProgramArguments();
+ List<String> argList = new ArrayList<String>();
+ argList.add(StandardVMDebugger.END_OF_OPTIONS_DELIMITER);
+ for (int i = 0; i < args.length; i++) {
+ argList.add(args[i]);
+ }
+ config.setProgramArguments(argList.toArray(new String[argList.size()]));
+ return super.constructProgramString(config);
}
-
+
+ @Override
protected List<String> debugSpecificVMArgs(RubyDebugTarget debugTarget) {
+ return new ArrayList<String>();
+ }
+
+ protected List<String> debugArgs(RubyDebugTarget debugTarget) {
List<String> arguments = new ArrayList<String>();
+ arguments.add(findRDebugExecutable(fVMInstance.getInstallLocation()));
arguments.add(PORT_SWITCH);
arguments.add(Integer.toString(debugTarget.getPort()));
if (isDebuggerVerbose()) {
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMDebugger.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMDebugger.java 2007-05-02 19:04:01 UTC (rev 2420)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMDebugger.java 2007-05-03 13:45:21 UTC (rev 2421)
@@ -3,6 +3,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
@@ -64,8 +65,7 @@
RubyDebugTarget debugTarget = new RubyDebugTarget(launch, port);
List<String> arguments = constructProgramString(config);
-// arguments.add(program);
-
+
// VM args are the first thing after the ruby program so that users can
// specify
// options like '-client' & '-server' which are required to be the first
@@ -75,14 +75,15 @@
String[] cp = config.getLoadPath();
if (cp.length > 0) {
- arguments.addAll(convertLoadPath(cp));
+ arguments.addAll(convertLoadPath(cp)); // TODO If our working directory is equal to loadpath, don't add loadpath
}
-
- arguments.addAll(debugSpecificVMArgs(debugTarget));
-
+ arguments.addAll(debugSpecificVMArgs(debugTarget));
+
arguments.add(StandardVMRunner.END_OF_OPTIONS_DELIMITER);
+
+ arguments.addAll(debugArgs(debugTarget));
- arguments.add(config.getFileToLaunch());
+ arguments.add(config.getFileToLaunch());
addArguments(config.getProgramArguments(), arguments);
String[] cmdLine = new String[arguments.size()];
arguments.toArray(cmdLine);
@@ -140,6 +141,10 @@
// }
}
+ protected Collection<String> debugArgs(RubyDebugTarget debugTarget) {
+ return new ArrayList<String>();
+ }
+
protected RubyDebuggerProxy getDebugProxy(RubyDebugTarget debugTarget) {
return new RubyDebuggerProxy(debugTarget, false /* isRubyDebug*/);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 19:04:03
|
Revision: 2420
http://svn.sourceforge.net/rubyeclipse/?rev=2420&view=rev
Author: cawilliams
Date: 2007-05-02 12:04:01 -0700 (Wed, 02 May 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/Flags.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/Flags.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/Flags.java 2007-05-02 19:02:35 UTC (rev 2419)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/Flags.java 2007-05-02 19:04:01 UTC (rev 2420)
@@ -55,5 +55,8 @@
public static boolean isStatic(int flags) {
return (flags & AccStatic) != 0;
}
+ public static boolean isModule(int flags) {
+ return (flags & AccModule) != 0;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 19:02:36
|
Revision: 2419
http://svn.sourceforge.net/rubyeclipse/?rev=2419&view=rev
Author: cawilliams
Date: 2007-05-02 12:02:35 -0700 (Wed, 02 May 2007)
Log Message:
-----------
handles types that are enclosed
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/matching/TypeDeclarationPattern.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionComponent.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java 2007-05-02 17:40:58 UTC (rev 2418)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java 2007-05-02 19:02:35 UTC (rev 2419)
@@ -1,5 +1,7 @@
package org.rubypeople.rdt.internal.core.search.indexing;
+import java.util.Stack;
+
import org.rubypeople.rdt.core.Flags;
import org.rubypeople.rdt.core.compiler.CategorizedProblem;
import org.rubypeople.rdt.internal.compiler.ISourceElementRequestor;
@@ -7,9 +9,11 @@
public class SourceIndexerRequestor implements ISourceElementRequestor {
private SourceIndexer indexer;
+ private Stack<String> typeStack;
public SourceIndexerRequestor(SourceIndexer sourceIndexer) {
this.indexer = sourceIndexer;
+ typeStack = new Stack<String>();
}
public void acceptConstructorReference(String name, int argCount, int offset) {
@@ -78,9 +82,19 @@
if (type.superclass != null) {
superclass = type.superclass.toCharArray();
}
- indexer.addClassDeclaration(type.isModule ? Flags.AccModule : 0, packName, type.name.toCharArray(), null, superclass, mod, type.secondary);
+ indexer.addClassDeclaration(type.isModule ? Flags.AccModule : 0, packName, type.name.toCharArray(), getEnclosingTypeNames(), superclass, mod, type.secondary);
+ typeStack.push(type.name);
}
+ private char[][] getEnclosingTypeNames() {
+ char[][] names = new char[typeStack.size()][];
+ int i = 0;
+ for (String name : typeStack) {
+ names[i++] = name.toCharArray();
+ }
+ return names;
+ }
+
public void exitConstructor(int endOffset) {
// TODO Auto-generated method stub
@@ -102,8 +116,7 @@
}
public void exitType(int endOffset) {
- // TODO Auto-generated method stub
-
+ typeStack.pop();
}
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/matching/TypeDeclarationPattern.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/matching/TypeDeclarationPattern.java 2007-05-02 17:40:58 UTC (rev 2418)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/matching/TypeDeclarationPattern.java 2007-05-02 19:02:35 UTC (rev 2419)
@@ -95,7 +95,7 @@
for (int i = 0, length = enclosingTypeNames.length; i < length;) {
enclosingNamesLength += enclosingTypeNames[i].length;
if (++i < length)
- enclosingNamesLength++; // for the '.' separator
+ enclosingNamesLength += 2; // for the "::" separator
}
}
@@ -119,8 +119,10 @@
int itsLength = enclosingName.length;
System.arraycopy(enclosingName, 0, result, pos, itsLength);
pos += itsLength;
- if (++i < length)
- result[pos++] = '.';
+ if (++i < length) {
+ result[pos++] = ':';
+ result[pos++] = ':';
+ }
}
}
result[pos++] = SEPARATOR;
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java 2007-05-02 17:40:58 UTC (rev 2418)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java 2007-05-02 19:02:35 UTC (rev 2419)
@@ -158,14 +158,14 @@
/**
* Gets the type qualified name: Includes enclosing type names, but
- * not package name. Identifiers are separated by dots.
+ * not package name. Identifiers are separated by "::".
*/
public String getTypeQualifiedName() {
if (fEnclosingNames != null && fEnclosingNames.length > 0) {
StringBuffer buf= new StringBuffer();
for (int i= 0; i < fEnclosingNames.length; i++) {
buf.append(fEnclosingNames[i]);
- buf.append('.');
+ buf.append("::");
}
buf.append(fName);
return buf.toString();
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionComponent.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionComponent.java 2007-05-02 17:40:58 UTC (rev 2418)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionComponent.java 2007-05-02 19:02:35 UTC (rev 2419)
@@ -11,7 +11,6 @@
package org.rubypeople.rdt.internal.ui.dialogs;
import java.io.IOException;
-import java.io.StringReader;
import java.io.StringWriter;
import org.eclipse.jface.action.Action;
@@ -20,8 +19,6 @@
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.util.IPropertyChangeListener;
-import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
@@ -51,9 +48,6 @@
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
-import org.eclipse.ui.IMemento;
-import org.eclipse.ui.IWorkingSet;
-import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.actions.WorkingSetFilterActionGroup;
import org.rubypeople.rdt.core.search.IRubySearchScope;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 17:41:00
|
Revision: 2418
http://svn.sourceforge.net/rubyeclipse/?rev=2418&view=rev
Author: cawilliams
Date: 2007-05-02 10:40:58 -0700 (Wed, 02 May 2007)
Log Message:
-----------
add missing message
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.properties
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.properties 2007-05-02 13:35:00 UTC (rev 2417)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.properties 2007-05-02 17:40:58 UTC (rev 2418)
@@ -21,5 +21,4 @@
ToggleComment_error_title=Toggle Comment
ToggleComment_error_message=An error occurred while toggling comments.
-CompletionProcessor_ContextInfo_display_pattern=
-CompletionProcessor_ContextInfo_value_pattern=
\ No newline at end of file
+EditorUtility_concatModifierStrings= {0} + {1}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 13:35:02
|
Revision: 2417
http://svn.sourceforge.net/rubyeclipse/?rev=2417&view=rev
Author: cawilliams
Date: 2007-05-02 06:35:00 -0700 (Wed, 02 May 2007)
Log Message:
-----------
make the source hover do syntax coloring and use the editor's font
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/SourceViewerInformationControl.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/SourceViewerInformationControl.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/SourceViewerInformationControl.java 2007-05-02 13:17:38 UTC (rev 2416)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/SourceViewerInformationControl.java 2007-05-02 13:35:00 UTC (rev 2417)
@@ -11,6 +11,7 @@
package org.rubypeople.rdt.internal.ui.text.ruby.hover;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
@@ -37,6 +38,7 @@
import org.eclipse.swt.widgets.Shell;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer;
+import org.rubypeople.rdt.internal.ui.text.IRubyPartitions;
import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration;
/**
@@ -131,7 +133,7 @@
// Source viewer
IPreferenceStore store= RubyPlugin.getDefault().getCombinedPreferenceStore();
fViewer= new RubySourceViewer(composite, null, null, false, style, store);
- fViewer.configure(new SimpleRubySourceViewerConfiguration(RubyPlugin.getDefault().getRubyTextTools().getColorManager(), store, null, null, false));
+ fViewer.configure(new SimpleRubySourceViewerConfiguration(RubyPlugin.getDefault().getRubyTextTools().getColorManager(), store, null, IRubyPartitions.RUBY_PARTITIONING, false));
fViewer.setEditable(false);
fText= fViewer.getTextWidget();
@@ -140,6 +142,8 @@
fText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
fText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ initializeFont();
+
fText.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
@@ -229,6 +233,17 @@
public SourceViewerInformationControl(Shell parent, String statusFieldText) {
this(parent, SWT.NONE, statusFieldText);
}
+
+ /**
+ * Initialize the font to the Ruby editor font.
+ *
+ * @since 1.0
+ */
+ private void initializeFont() {
+ Font font= JFaceResources.getFont("org.rubypeople.rdt.ui.editors.textfont"); //$NON-NLS-1$
+ StyledText styledText= getViewer().getTextWidget();
+ styledText.setFont(font);
+ }
/*
* @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
@@ -250,7 +265,7 @@
}
IDocument doc= new Document(content);
- RubyPlugin.getDefault().getRubyTextTools().setupRubyDocumentPartitioner(doc);
+ RubyPlugin.getDefault().getRubyTextTools().setupRubyDocumentPartitioner(doc, IRubyPartitions.RUBY_PARTITIONING);
fViewer.setInput(doc);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 13:17:42
|
Revision: 2416
http://svn.sourceforge.net/rubyeclipse/?rev=2416&view=rev
Author: cawilliams
Date: 2007-05-02 06:17:38 -0700 (Wed, 02 May 2007)
Log Message:
-----------
some core work to support new hovers
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyElement.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/formatter/IndentManipulation.java
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/formatter/IndentManipulation.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/formatter/IndentManipulation.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/formatter/IndentManipulation.java 2007-05-02 13:17:38 UTC (rev 2416)
@@ -0,0 +1,427 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.core.formatter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.rubypeople.rdt.internal.compiler.parser.ScannerHelper;
+
+/**
+ * Helper class to provide String manipulation functions dealing with indentations.
+ *
+ * @since 1.0
+ */
+public final class IndentManipulation {
+
+ public static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ private IndentManipulation() {
+ // don't instantiate
+ }
+
+ /**
+ * Returns <code>true</code> if the given character is an indentation character. Indentation character are all whitespace characters
+ * except the line delimiter characters.
+ *
+ * @param ch the given character
+ * @return Returns <code>true</code> if this the character is a indent character, <code>false</code> otherwise
+ */
+ public static boolean isIndentChar(char ch) {
+ return ScannerHelper.isWhitespace(ch) && !isLineDelimiterChar(ch);
+ }
+
+ /**
+ * Returns <code>true</code> if the given character is a line delimiter character.
+ *
+ * @param ch the given character
+ * @return Returns <code>true</code> if this the character is a line delimiter character, <code>false</code> otherwise
+ */
+ public static boolean isLineDelimiterChar(char ch) {
+ return ch == '\n' || ch == '\r';
+ }
+
+ /**
+ * Returns the indentation of the given line in indentation units. Odd spaces are
+ * not counted. This method only analyzes the content of <code>line</code> up to the first
+ * non-whitespace character.
+ *
+ * @param line the string to measure the indent of
+ * @param tabWidth the width of one tab character in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the number of indentation units that line is indented by
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>indentWidth</code> is lower or equals to zero</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * <li>the given <code>line</code> is null</li>
+ * </ul>
+ */
+ public static int measureIndentUnits(CharSequence line, int tabWidth, int indentWidth) {
+ if (indentWidth <= 0 || tabWidth < 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int visualLength= measureIndentInSpaces(line, tabWidth);
+ return visualLength / indentWidth;
+ }
+
+ /**
+ * Returns the indentation of the given line in space equivalents.
+ *
+ * <p>Tab characters are counted using the given <code>tabWidth</code> and every other indent
+ * character as one. This method analyzes the content of <code>line</code> up to the first
+ * non-whitespace character.</p>
+ *
+ * @param line the string to measure the indent of
+ * @param tabWidth the width of one tab in space equivalents
+ * @return the measured indent width in space equivalents
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>line</code> is null</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * </ul>
+ */
+ public static int measureIndentInSpaces(CharSequence line, int tabWidth) {
+ if (tabWidth < 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int length= 0;
+ int max= line.length();
+ for (int i= 0; i < max; i++) {
+ char ch= line.charAt(i);
+ if (ch == '\t') {
+ int reminder= length % tabWidth;
+ length += tabWidth - reminder;
+ } else if (isIndentChar(ch)) {
+ length++;
+ } else {
+ return length;
+ }
+ }
+ return length;
+ }
+
+ /**
+ * Returns the leading indentation string of the given line. Note that the returned string
+ * need not be equal to the leading whitespace as odd spaces are not considered part of the
+ * indentation.
+ *
+ * @param line the line to scan
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the indent part of <code>line</code>, but no odd spaces
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>indentWidth</code> is lower or equals to zero</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * <li>the given <code>line</code> is null</li>
+ * </ul>
+ */
+ public static String extractIndentString(String line, int tabWidth, int indentWidth) {
+ if (tabWidth < 0 || indentWidth <= 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int size= line.length();
+ int end= 0;
+
+ int spaceEquivs= 0;
+ int characters= 0;
+ for (int i= 0; i < size; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= spaceEquivs % tabWidth;
+ spaceEquivs += tabWidth - remainder;
+ characters++;
+ } else if (isIndentChar(c)) {
+ spaceEquivs++;
+ characters++;
+ } else {
+ break;
+ }
+ if (spaceEquivs >= indentWidth) {
+ end += characters;
+ characters= 0;
+ spaceEquivs= spaceEquivs % indentWidth;
+ }
+ }
+ if (end == 0) {
+ return EMPTY_STRING;
+ } else if (end == size) {
+ return line;
+ } else {
+ return line.substring(0, end);
+ }
+ }
+
+
+ /**
+ * Removes the given number of indentation units from a given line. If the line
+ * has less than the given indent, all the available indentation is removed.
+ * If <code>indentsToRemove <= 0</code> the line is returned.
+ *
+ * @param line the line to trim
+ * @param tabWidth the width of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the trimmed string
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>indentWidth</code> is lower or equals to zero</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * <li>the given <code>line</code> is null</li>
+ * </ul>
+ */
+ public static String trimIndent(String line, int indentUnitsToRemove, int tabWidth, int indentWidth) {
+ if (tabWidth < 0 || indentWidth <= 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (indentUnitsToRemove <= 0)
+ return line;
+
+ final int spaceEquivalentsToRemove= indentUnitsToRemove * indentWidth;
+
+ int start= 0;
+ int spaceEquivalents= 0;
+ int size= line.length();
+ String prefix= null;
+ for (int i= 0; i < size; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= spaceEquivalents % tabWidth;
+ spaceEquivalents += tabWidth - remainder;
+ } else if (isIndentChar(c)) {
+ spaceEquivalents++;
+ } else {
+ // Assert.isTrue(false, "Line does not have requested number of indents");
+ start= i;
+ break;
+ }
+ if (spaceEquivalents == spaceEquivalentsToRemove) {
+ start= i + 1;
+ break;
+ }
+ if (spaceEquivalents > spaceEquivalentsToRemove) {
+ // can happen if tabSize > indentSize, e.g tabsize==8, indent==4, indentsToRemove==1, line prefixed with one tab
+ // this implements the third option
+ start= i + 1; // remove the tab
+ // and add the missing spaces
+ char[] missing= new char[spaceEquivalents - spaceEquivalentsToRemove];
+ Arrays.fill(missing, ' ');
+ prefix= new String(missing);
+ break;
+ }
+ }
+ String trimmed;
+ if (start == size)
+ trimmed= EMPTY_STRING;
+ else
+ trimmed= line.substring(start);
+
+ if (prefix == null)
+ return trimmed;
+ return prefix + trimmed;
+ }
+
+ /**
+ * Change the indent of a, possible multiple line, code string. The given number of indent units is removed,
+ * and a new indent string is added.
+ * <p>The first line of the code will not be changed (It is considered to have no indent as it might start in
+ * the middle of a line).</p>
+ *
+ * @param code the code to change the indent of
+ * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @param newIndentString the new indent string to be added to all lines (except the first)
+ * @param lineDelim the new line delimiter to be used. The returned code will contain only this line delimiter.
+ * @return the newly indent code, containing only the given line delimiters.
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>indentWidth</code> is lower or equals to zero</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * <li>the given <code>code</code> is null</li>
+ * <li>the given <code>indentUnitsToRemove</code> is lower than zero</li>
+ * <li>the given <code>newIndentString</code> is null</li>
+ * <li>the given <code>lineDelim</code> is null</li>
+ * </ul>
+ */
+ public static String changeIndent(String code, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString, String lineDelim) {
+ if (tabWidth < 0 || indentWidth <= 0 || code == null || indentUnitsToRemove < 0 || newIndentString == null || lineDelim == null) {
+ throw new IllegalArgumentException();
+ }
+
+ try {
+ ILineTracker tracker= new DefaultLineTracker();
+ tracker.set(code);
+ int nLines= tracker.getNumberOfLines();
+ if (nLines == 1) {
+ return code;
+ }
+
+ StringBuffer buf= new StringBuffer();
+
+ for (int i= 0; i < nLines; i++) {
+ IRegion region= tracker.getLineInformation(i);
+ int start= region.getOffset();
+ int end= start + region.getLength();
+ String line= code.substring(start, end);
+
+ if (i == 0) { // no indent for first line (contained in the formatted string)
+ buf.append(line);
+ } else { // no new line after last line
+ buf.append(lineDelim);
+ buf.append(newIndentString);
+ buf.append(trimIndent(line, indentUnitsToRemove, tabWidth, indentWidth));
+ }
+ }
+ return buf.toString();
+ } catch (BadLocationException e) {
+ // can not happen
+ return code;
+ }
+ }
+
+ /**
+ * Returns the text edits retrieved after changing the indentation of a, possible multi-line, code string.
+ *
+ * <p>The given number of indent units is removed, and a new indent string is added.</p>
+ * <p>The first line of the code will not be changed (It is considered to have no indent as it might start in
+ * the middle of a line).</p>
+ *
+ * @param source The code to change the indent of
+ * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @param newIndentString the new indent string to be added to all lines (except the first)
+ * @return returns the resulting text edits
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the given <code>indentWidth</code> is lower or equals to zero</li>
+ * <li>the given <code>tabWidth</code> is lower than zero</li>
+ * <li>the given <code>source</code> is null</li>
+ * <li>the given <code>indentUnitsToRemove</code> is lower than zero</li>
+ * <li>the given <code>newIndentString</code> is null</li>
+ * </ul>
+ */
+ public static ReplaceEdit[] getChangeIndentEdits(String source, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString) {
+ if (tabWidth < 0 || indentWidth <= 0 || source == null || indentUnitsToRemove < 0 || newIndentString == null) {
+ throw new IllegalArgumentException();
+ }
+
+ ArrayList result= new ArrayList();
+ try {
+ ILineTracker tracker= new DefaultLineTracker();
+ tracker.set(source);
+ int nLines= tracker.getNumberOfLines();
+ if (nLines == 1)
+ return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
+ for (int i= 1; i < nLines; i++) {
+ IRegion region= tracker.getLineInformation(i);
+ int offset= region.getOffset();
+ String line= source.substring(offset, offset + region.getLength());
+ int length= indexOfIndent(line, indentUnitsToRemove, tabWidth, indentWidth);
+ if (length >= 0) {
+ result.add(new ReplaceEdit(offset, length, newIndentString));
+ } else {
+ length= measureIndentUnits(line, tabWidth, indentWidth);
+ result.add(new ReplaceEdit(offset, length, "")); //$NON-NLS-1$
+ }
+ }
+ } catch (BadLocationException cannotHappen) {
+ // can not happen
+ }
+ return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
+ }
+
+ /*
+ * Returns the index where the indent of the given size ends.
+ * Returns <code>-1<code> if the line isn't prefixed with an indent of
+ * the given number of indents.
+ */
+ private static int indexOfIndent(CharSequence line, int numberOfIndentUnits, int tabWidth, int indentWidth) {
+
+ int spaceEquivalents= numberOfIndentUnits * indentWidth;
+
+ int size= line.length();
+ int result= -1;
+ int blanks= 0;
+ for (int i= 0; i < size && blanks < spaceEquivalents; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= blanks % tabWidth;
+ blanks += tabWidth - remainder;
+ } else if (isIndentChar(c)) {
+ blanks++;
+ } else {
+ break;
+ }
+ result= i;
+ }
+ if (blanks < spaceEquivalents)
+ return -1;
+ return result + 1;
+ }
+
+ /**
+ * Returns the tab width as configured in the given map.
+ * <p>Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to get the most current project options.</p>
+ *
+ * @param options the map to get the formatter settings from.
+ *
+ * @return the tab width
+ * @exception IllegalArgumentException if the given <code>options</code> is null
+ */
+ public static int getTabWidth(Map options) {
+ if (options == null) {
+ throw new IllegalArgumentException();
+ }
+ return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4);
+ }
+
+ /**
+ * Returns the tab width as configured in the given map.
+ * <p>Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to get the most current project options.</p>
+ *
+ * @param options the map to get the formatter settings from
+ *
+ * @return the indent width
+ * @exception IllegalArgumentException if the given <code>options</code> is null
+ */
+ public static int getIndentWidth(Map options) {
+ if (options == null) {
+ throw new IllegalArgumentException();
+ }
+ int tabWidth=getTabWidth(options);
+ boolean isMixedMode= DefaultCodeFormatterConstants.MIXED.equals(options.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR));
+ if (isMixedMode) {
+ return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabWidth);
+ }
+ return tabWidth;
+ }
+
+ private static int getIntValue(Map options, String key, int def) {
+ try {
+ return Integer.parseInt((String) options.get(key));
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ }
+}
+
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-05-02 13:17:08 UTC (rev 2415)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-05-02 13:17:38 UTC (rev 2416)
@@ -16,9 +16,9 @@
import org.jruby.ast.ClassVarDeclNode;
import org.jruby.ast.ClassVarNode;
import org.jruby.ast.Colon2Node;
+import org.jruby.ast.ConstDeclNode;
import org.jruby.ast.ConstNode;
import org.jruby.ast.DefnNode;
-import org.jruby.ast.DefsNode;
import org.jruby.ast.FCallNode;
import org.jruby.ast.InstAsgnNode;
import org.jruby.ast.InstVarNode;
@@ -54,7 +54,6 @@
import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator;
import org.rubypeople.rdt.internal.ti.util.INodeAcceptor;
import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator;
-import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator;
public class SelectionEngine {
@@ -117,6 +116,11 @@
.getChildren(), IRubyElement.CLASS_VAR, getName(selected));
return possible.toArray(new IRubyElement[possible.size()]);
}
+ // We're already on the declaration, just return it
+ if ((selected instanceof DefnNode) || (selected instanceof ConstDeclNode)) {
+ IRubyElement element = ((RubyScript)script).getElementAt(start);
+ return new IRubyElement[] {element};
+ }
if (isMethodCall(selected)) {
String methodName = getName(selected);
Set<IRubyElement> possible = new HashSet<IRubyElement>();
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java 2007-05-02 13:17:08 UTC (rev 2415)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java 2007-05-02 13:17:38 UTC (rev 2416)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.internal.compiler.parser;
+
public class ScannerHelper {
public final static int MAX_OBVIOUS = 128;
public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];
@@ -115,4 +116,16 @@
}
return Character.isJavaIdentifierStart(c);
}
+
+ /**
+ * Include also non JLS whitespaces.
+ *
+ * return true if Character.isWhitespace(c) would return true
+ */
+ public static boolean isWhitespace(char c) {
+ if (c < MAX_OBVIOUS) {
+ return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_SPACE) != 0;
+ }
+ return Character.isWhitespace(c);
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyElement.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyElement.java 2007-05-02 13:17:08 UTC (rev 2415)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyElement.java 2007-05-02 13:17:38 UTC (rev 2416)
@@ -477,10 +477,33 @@
}
this.toStringChildren(tab, buffer, info);
}
+ /**
+ * Debugging purposes
+ */
+ public String toStringWithAncestors(boolean showResolvedInfo) {
+ StringBuffer buffer = new StringBuffer();
+ this.toStringInfo(0, buffer, NO_INFO, showResolvedInfo);
+ this.toStringAncestors(buffer);
+ return buffer.toString();
+ }
/**
* Debugging purposes
+ *
+ * @param showResolvedInfo
+ * TODO
*/
+ protected void toStringInfo(int tab, StringBuffer buffer, Object info,
+ boolean showResolvedInfo) {
+ buffer.append(this.tabString(tab));
+ toStringName(buffer);
+ if (info == null) {
+ buffer.append(" (not open)"); //$NON-NLS-1$
+ }
+ }
+ /**
+ * Debugging purposes
+ */
public String toStringWithAncestors() {
StringBuffer buffer = new StringBuffer();
this.toStringInfo(0, buffer, NO_INFO);
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java 2007-05-02 13:17:08 UTC (rev 2415)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java 2007-05-02 13:17:38 UTC (rev 2416)
@@ -37,6 +37,7 @@
import org.rubypeople.rdt.core.RubyConventions;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.RubyElement;
/**
* @author Chris
@@ -1000,4 +1001,21 @@
return new String(result);
}
+ /**
+ * Sorts an array of Ruby elements based on their toStringWithAncestors(),
+ * returning a new array with the sorted items.
+ * The original array is left untouched.
+ */
+ public static IRubyElement[] sortCopy(IRubyElement[] elements) {
+ int len = elements.length;
+ IRubyElement[] copy = new IRubyElement[len];
+ System.arraycopy(elements, 0, copy, 0, len);
+ sort(copy, new Comparer() {
+ public int compare(Object a, Object b) {
+ return ((RubyElement) a).toStringWithAncestors().compareTo(((RubyElement) b).toStringWithAncestors());
+ }
+ });
+ return copy;
+ }
+
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-02 13:17:11
|
Revision: 2415
http://svn.sourceforge.net/rubyeclipse/?rev=2415&view=rev
Author: cawilliams
Date: 2007-05-02 06:17:08 -0700 (Wed, 02 May 2007)
Log Message:
-----------
Rip out the old hover extension point and replace it with one based on JDT - this allows us to more easily modify the popup, and override nly the methods we choose.
Also hook up the new extension point to the editor, and add a bunch of new hovers.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/plugin.xml
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/EditorUtility.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/WorkingCopyManager.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/AbstractRubyEditorTextHover.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RiDocHoverProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyHoverMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/RubySourceViewerConfiguration.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/text/ruby/hover/IRubyEditorTextHover.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/RubydocHoverStyleSheet.css
trunk/org.rubypeople.rdt.ui/schema/rubyEditorTextHovers.exsd
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/BestMatchHover.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/ProblemHover.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverDescriptor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverProxy.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubySourceHover.java
Removed Paths:
-------------
trunk/org.rubypeople.rdt.ui/schema/textHoverProvider.exsd
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyCodeTextHover.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/extensions/ITextHoverProvider.java
Added: trunk/org.rubypeople.rdt.ui/RubydocHoverStyleSheet.css
===================================================================
--- trunk/org.rubypeople.rdt.ui/RubydocHoverStyleSheet.css (rev 0)
+++ trunk/org.rubypeople.rdt.ui/RubydocHoverStyleSheet.css 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,30 @@
+/* Font definitions */
+body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: sans-serif; font-size: 9pt }
+pre { font-family: monospace; font-size: 9pt }
+
+/* Margins */
+body { overflow: auto; margin-top: 0; margin-bottom: 4; margin-left: 3; margin-right: 0 }
+h1 { margin-top: 5; margin-bottom: 1 }
+h2 { margin-top: 25; margin-bottom: 3 }
+h3 { margin-top: 20; margin-bottom: 3 }
+h4 { margin-top: 20; margin-bottom: 3 }
+h5 { margin-top: 0; margin-bottom: 0 }
+p { margin-top: 10px; margin-bottom: 10px }
+pre { margin-left: 6 }
+ul { margin-top: 0; margin-bottom: 10 }
+li { margin-top: 0; margin-bottom: 0 }
+li p { margin-top: 0; margin-bottom: 0 }
+ol { margin-top: 0; margin-bottom: 10 }
+dl { margin-top: 0; margin-bottom: 10 }
+dt { margin-top: 0; margin-bottom: 0; font-weight: bold }
+dd { margin-top: 0; margin-bottom: 0 }
+
+/* Styles and colors */
+a:link { color: #0000FF }
+a:hover { color: #000080 }
+a:visited { text-decoration: underline }
+h4 { font-style: italic }
+strong { font-weight: bold }
+em { font-style: italic }
+var { font-style: italic }
+th { font-weight: bold }
Modified: trunk/org.rubypeople.rdt.ui/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.ui/plugin.xml 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/plugin.xml 2007-05-02 13:17:08 UTC (rev 2415)
@@ -8,6 +8,7 @@
<extension-point id="editorPopupExtender" name="%editorPopupExtender" schema="schema/org.rubypeople.rdt.ui.editorPopupExtender.exsd"/>
<extension-point id="rubyTemplateProvider" name="Ruby template provider" schema="schema/rubyTemplateProvider.exsd"/>
<extension-point id="quickFixProcessors" name="%quickFixProcessorExtensionPoint" schema="schema/quickFixProcessors.exsd"/>
+ <extension-point id="rubyEditorTextHovers" name="%rubyEditorTextHover" schema="schema/rubyEditorTextHovers.exsd"/>
<extension
point="org.eclipse.ui.preferencePages">
@@ -921,12 +922,38 @@
id="org.rubypeople.rdt.ui.search.RubySearchResultPage"
searchResultClass="org.rubypeople.rdt.internal.ui.search.RubySearchResult"/>
</extension>
-
- <extension
- point="org.rubypeople.rdt.ui.textHoverProvider">
- <textHoverProvider class="org.rubypeople.rdt.internal.ui.text.ruby.hover.RiDocHoverProvider" />
+
+ <extension point="org.rubypeople.rdt.ui.rubyEditorTextHovers">
+ <hover
+ label="%sequentialHover"
+ description="%sequentialHoverDescription"
+ class="org.rubypeople.rdt.internal.ui.text.ruby.hover.BestMatchHover"
+ id="org.rubypeople.rdt.ui.BestMatchHover">
+ </hover>
+ <hover
+ label="%problemHover"
+ description="%problemHoverDescription"
+ class="org.rubypeople.rdt.internal.ui.text.ruby.hover.ProblemHover"
+ id="org.rubypeople.rdt.ui.ProblemHover">
+ </hover>
+ <hover
+ id="org.rubypeople.rdt.ui.RiDocHover"
+ class="org.rubypeople.rdt.internal.ui.text.ruby.hover.RiDocHoverProvider"
+ label="%rdocHover"/>
+ <hover
+ label="%sourceHover"
+ description="%sourceHoverDescription"
+ class="org.rubypeople.rdt.internal.ui.text.ruby.hover.RubySourceHover"
+ id="org.rubypeople.rdt.ui.RubySourceHover">
+ </hover>
+ <hover
+ label="%annotationHover"
+ description="%annotationHoverDescription"
+ class="org.rubypeople.rdt.internal.ui.text.ruby.hover.AnnotationHover"
+ id="org.rubypeople.rdt.ui.AnnotationHover">
+ </hover>
</extension>
-
+
<extension
point="org.eclipse.ui.popupMenus">
<viewerContribution
Added: trunk/org.rubypeople.rdt.ui/schema/rubyEditorTextHovers.exsd
===================================================================
--- trunk/org.rubypeople.rdt.ui/schema/rubyEditorTextHovers.exsd (rev 0)
+++ trunk/org.rubypeople.rdt.ui/schema/rubyEditorTextHovers.exsd 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,139 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.rubypeople.rdt.ui">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.rubypeople.rdt.ui" id="rubyEditorTextHovers" name="%rubyEditorTextHover"/>
+ </appInfo>
+ <documentation>
+ This extension point is used to plug-in text hovers in a Ruby editor.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <element ref="hover"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ a fully qualified identifier of the target extension point
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="hover">
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ the id, typically the same as the fully qualified class name.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ the fully qualified class name implementing the interface org.rubypeople.rdt.ui.text.ruby.hover.IRubyEditorTextHover
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.rubypeople.rdt.ui.text.ruby.hover.IRubyEditorTextHover"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="label" type="string">
+ <annotation>
+ <documentation>
+ the translatable label for this hover.
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="description" type="string">
+ <annotation>
+ <documentation>
+ the translatable description for this hover.
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="activate" type="boolean" use="default" value="false">
+ <annotation>
+ <documentation>
+ if the attribute is set to "true" it will force this plug-in to be loaded on hover activation.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ RDT 1.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ 2007 Aptana, Inc.
+ </documentation>
+ </annotation>
+
+</schema>
Deleted: trunk/org.rubypeople.rdt.ui/schema/textHoverProvider.exsd
===================================================================
--- trunk/org.rubypeople.rdt.ui/schema/textHoverProvider.exsd 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/schema/textHoverProvider.exsd 2007-05-02 13:17:08 UTC (rev 2415)
@@ -1,120 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.rubypeople.rdt.ui.TextHoverProvider">
-<annotation>
- <appInfo>
- <meta.schema plugin="org.rubypeople.rdt.ui" id="textHoverProvider" name="Text Hover Provider"/>
- </appInfo>
- <documentation>
-
- </documentation>
- </annotation>
-
- <element name="extension">
- <complexType>
- <sequence>
- <element ref="textHoverProvider"/>
- </sequence>
- <attribute name="point" type="string" use="required">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- <attribute name="id" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- <attribute name="name" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- </complexType>
- </element>
-
- <element name="textHoverProvider">
- <complexType>
- <attribute name="class" type="string" use="required">
- <annotation>
- <documentation>
- The class that implements org.rubypeople.rdt.ui.extensions.ITextHoverProvider.
- </documentation>
- <appInfo>
- <meta.attribute kind="java" basedOn="org.rubypeople.rdt.ui.extensions.ITextHoverProvider"/>
- </appInfo>
- </annotation>
- </attribute>
-
- <attribute name="fileExtension" type="string" use="optional">
- <annotation>
- <documentation>
- Use this to restrict the application of this hover to particular file extensions.
- </documentation>
- <appInfo>
- <meta.attribute kind="java" basedOn="org.rubypeople.rdt.ui.extensions.ITextHoverProvider"/>
- </appInfo>
- </annotation>
- </attribute>
-
-
-
- </complexType>
-
- </element>
-
-
-
-
- <annotation>
- <appInfo>
- <meta.section type="since"/>
- </appInfo>
- <documentation>
- [Enter the first release in which this extension point appears.]
- </documentation>
- </annotation>
-
- <annotation>
- <appInfo>
- <meta.section type="examples"/>
- </appInfo>
- <documentation>
- [Enter extension point usage example here.]
- </documentation>
- </annotation>
-
- <annotation>
- <appInfo>
- <meta.section type="apiInfo"/>
- </appInfo>
- <documentation>
- [Enter API information here.]
- </documentation>
- </annotation>
-
- <annotation>
- <appInfo>
- <meta.section type="implementation"/>
- </appInfo>
- <documentation>
- [Enter information about supplied implementation of this extension point.]
- </documentation>
- </annotation>
-
- <annotation>
- <appInfo>
- <meta.section type="copyright"/>
- </appInfo>
- <documentation>
-
- </documentation>
- </annotation>
-
-</schema>
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -1,6 +1,11 @@
package org.rubypeople.rdt.internal.corext.util;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.formatter.IndentManipulation;
public class Strings {
@@ -144,4 +149,127 @@
return result.toString();
}
+ /**
+ * Converts the given string into an array of lines. The lines
+ * don't contain any line delimiter characters.
+ *
+ * @return the string converted into an array of strings. Returns <code>
+ * null</code> if the input string can't be converted in an array of lines.
+ */
+ public static String[] convertIntoLines(String input) {
+ try {
+ ILineTracker tracker= new DefaultLineTracker();
+ tracker.set(input);
+ int size= tracker.getNumberOfLines();
+ String result[]= new String[size];
+ for (int i= 0; i < size; i++) {
+ IRegion region= tracker.getLineInformation(i);
+ int offset= region.getOffset();
+ result[i]= input.substring(offset, offset + region.getLength());
+ }
+ return result;
+ } catch (BadLocationException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Removes the common number of indents from all lines. If a line
+ * only consists out of white space it is ignored.
+
+ * @param project the java project from which to get the formatter
+ * preferences, or <code>null</code> for global preferences
+ * @since 3.1
+ */
+ public static void trimIndentation(String[] lines, IRubyProject project) {
+ trimIndentation(lines, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project), true);
+ }
+
+ /**
+ * Removes the common number of indents from all lines. If a line
+ * only consists out of white space it is ignored. If <code>
+ * considerFirstLine</code> is false the first line will be ignored.
+ * @since 3.1
+ */
+ public static void trimIndentation(String[] lines, int tabWidth, int indentWidth, boolean considerFirstLine) {
+ String[] toDo= new String[lines.length];
+ // find indentation common to all lines
+ int minIndent= Integer.MAX_VALUE; // very large
+ for (int i= considerFirstLine ? 0 : 1; i < lines.length; i++) {
+ String line= lines[i];
+ if (containsOnlyWhitespaces(line))
+ continue;
+ toDo[i]= line;
+ int indent= computeIndentUnits(line, tabWidth, indentWidth);
+ if (indent < minIndent) {
+ minIndent= indent;
+ }
+ }
+
+ if (minIndent > 0) {
+ // remove this indent from all lines
+ for (int i= considerFirstLine ? 0 : 1; i < toDo.length; i++) {
+ String s= toDo[i];
+ if (s != null)
+ lines[i]= trimIndent(s, minIndent, tabWidth, indentWidth);
+ else {
+ String line= lines[i];
+ int indent= computeIndentUnits(line, tabWidth, indentWidth);
+ if (indent > minIndent)
+ lines[i]= trimIndent(line, minIndent, tabWidth, indentWidth);
+ else
+ lines[i]= trimLeadingTabsAndSpaces(line);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the given number of indents from the line. Asserts that the given line
+ * has the requested number of indents. If <code>indentsToRemove <= 0</code>
+ * the line is returned.
+ *
+ * @since 3.1
+ */
+ public static String trimIndent(String line, int indentsToRemove, int tabWidth, int indentWidth) {
+ return IndentManipulation.trimIndent(line, indentsToRemove, tabWidth, indentWidth);
+ }
+
+ /**
+ * Removes leading tabs and spaces from the given string. If the string
+ * doesn't contain any leading tabs or spaces then the string itself is
+ * returned.
+ */
+ public static String trimLeadingTabsAndSpaces(String line) {
+ int size= line.length();
+ int start= size;
+ for (int i= 0; i < size; i++) {
+ char c= line.charAt(i);
+ if (!IndentManipulation.isIndentChar(c)) {
+ start= i;
+ break;
+ }
+ }
+ if (start == 0)
+ return line;
+ else if (start == size)
+ return ""; //$NON-NLS-1$
+ else
+ return line.substring(start);
+ }
+
+ /**
+ * Concatenate the given strings into one strings using the passed line delimiter as a
+ * delimiter. No delimiter is added to the last line.
+ */
+ public static String concatenate(String[] lines, String delimiter) {
+ StringBuffer buffer= new StringBuffer();
+ for (int i= 0; i < lines.length; i++) {
+ if (i > 0)
+ buffer.append(delimiter);
+ buffer.append(lines[i]);
+ }
+ return buffer.toString();
+ }
+
}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -17,6 +17,7 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
@@ -47,6 +48,7 @@
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.ConfigurationElementSorter;
import org.osgi.framework.BundleContext;
import org.rubypeople.rdt.core.IBuffer;
import org.rubypeople.rdt.core.IRubyScript;
@@ -66,8 +68,8 @@
import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants;
import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter;
import org.rubypeople.rdt.internal.ui.text.folding.RubyFoldingStructureProviderRegistry;
+import org.rubypeople.rdt.internal.ui.text.ruby.hover.RubyEditorTextHoverDescriptor;
import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess;
-import org.rubypeople.rdt.ui.IWorkingCopyManager;
import org.rubypeople.rdt.ui.PreferenceConstants;
import org.rubypeople.rdt.ui.text.RubyTextTools;
@@ -80,7 +82,7 @@
protected RubyTextTools textTools;
protected RubyFileMatcher rubyFileMatcher;
- private IWorkingCopyManager fWorkingCopyManager;
+ private WorkingCopyManager fWorkingCopyManager;
private RubyDocumentProvider fDocumentProvider;
protected PropertyResourceBundle pluginProperties;
@@ -106,6 +108,8 @@
private MembersOrderPreferenceCache fMembersOrderPreferenceCache;
private RubyScriptDocumentProvider fExternalRubyDocumentProvider;
+ private RubyEditorTextHoverDescriptor[] fRubyEditorTextHoverDescriptors;
+
/**
* Default instance of the appearance type filters.
* @since 1.0
@@ -414,7 +418,7 @@
/**
* @return
*/
- public IWorkingCopyManager getWorkingCopyManager() {
+ public WorkingCopyManager getWorkingCopyManager() {
if (fWorkingCopyManager == null) {
RubyDocumentProvider provider = getRubyDocumentProvider();
fWorkingCopyManager = new WorkingCopyManager(provider);
@@ -584,4 +588,39 @@
}
return section;
}
+
+ /**
+ * Returns all Ruby editor text hovers contributed to the workbench.
+ *
+ * @return an array of RubyEditorTextHoverDescriptor
+ * @since 1.0
+ */
+ public RubyEditorTextHoverDescriptor[] getRubyEditorTextHoverDescriptors() {
+ if (fRubyEditorTextHoverDescriptors == null) {
+ fRubyEditorTextHoverDescriptors= RubyEditorTextHoverDescriptor.getContributedHovers();
+ ConfigurationElementSorter sorter= new ConfigurationElementSorter() {
+ /*
+ * @see org.eclipse.ui.texteditor.ConfigurationElementSorter#getConfigurationElement(java.lang.Object)
+ */
+ public IConfigurationElement getConfigurationElement(Object object) {
+ return ((RubyEditorTextHoverDescriptor)object).getConfigurationElement();
+ }
+ };
+ sorter.sort(fRubyEditorTextHoverDescriptors);
+
+ // Move Best Match hover to front
+ for (int i= 0; i < fRubyEditorTextHoverDescriptors.length - 1; i++) {
+ if (PreferenceConstants.ID_BESTMATCH_HOVER.equals(fRubyEditorTextHoverDescriptors[i].getId())) {
+ RubyEditorTextHoverDescriptor hoverDescriptor= fRubyEditorTextHoverDescriptors[i];
+ for (int j= i; j > 0; j--)
+ fRubyEditorTextHoverDescriptors[j]= fRubyEditorTextHoverDescriptors[j-1];
+ fRubyEditorTextHoverDescriptors[0]= hoverDescriptor;
+ break;
+ }
+
+ }
+ }
+
+ return fRubyEditorTextHoverDescriptors;
+ }
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/EditorUtility.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/EditorUtility.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/EditorUtility.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -8,10 +8,12 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.SWT;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
@@ -35,6 +37,7 @@
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.ExternalRubyScript;
+import org.rubypeople.rdt.internal.core.util.Messages;
import org.rubypeople.rdt.internal.corext.util.RubyModelUtil;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.ui.PreferenceConstants;
@@ -285,4 +288,68 @@
return null;
}
+ /**
+ * Maps the localized modifier name to a code in the same
+ * manner as #findModifier.
+ *
+ * @param modifierName the modifier name
+ * @return the SWT modifier bit, or <code>0</code> if no match was found
+ * @since 2.1.1
+ */
+ public static int findLocalizedModifier(String modifierName) {
+ if (modifierName == null)
+ return 0;
+
+ if (modifierName.equalsIgnoreCase(Action.findModifierString(SWT.CTRL)))
+ return SWT.CTRL;
+ if (modifierName.equalsIgnoreCase(Action.findModifierString(SWT.SHIFT)))
+ return SWT.SHIFT;
+ if (modifierName.equalsIgnoreCase(Action.findModifierString(SWT.ALT)))
+ return SWT.ALT;
+ if (modifierName.equalsIgnoreCase(Action.findModifierString(SWT.COMMAND)))
+ return SWT.COMMAND;
+
+ return 0;
+ }
+
+ /**
+ * Returns the modifier string for the given SWT modifier
+ * modifier bits.
+ *
+ * @param stateMask the SWT modifier bits
+ * @return the modifier string
+ * @since 2.1.1
+ */
+ public static String getModifierString(int stateMask) {
+ String modifierString= ""; //$NON-NLS-1$
+ if ((stateMask & SWT.CTRL) == SWT.CTRL)
+ modifierString= appendModifierString(modifierString, SWT.CTRL);
+ if ((stateMask & SWT.ALT) == SWT.ALT)
+ modifierString= appendModifierString(modifierString, SWT.ALT);
+ if ((stateMask & SWT.SHIFT) == SWT.SHIFT)
+ modifierString= appendModifierString(modifierString, SWT.SHIFT);
+ if ((stateMask & SWT.COMMAND) == SWT.COMMAND)
+ modifierString= appendModifierString(modifierString, SWT.COMMAND);
+
+ return modifierString;
+ }
+
+ /**
+ * Appends to modifier string of the given SWT modifier bit
+ * to the given modifierString.
+ *
+ * @param modifierString the modifier string
+ * @param modifier an int with SWT modifier bit
+ * @return the concatenated modifier string
+ * @since 2.1.1
+ */
+ private static String appendModifierString(String modifierString, int modifier) {
+ if (modifierString == null)
+ modifierString= ""; //$NON-NLS-1$
+ String newModifierString= Action.findModifierString(modifier);
+ if (modifierString.length() == 0)
+ return newModifierString;
+ return Messages.format(RubyEditorMessages.EditorUtility_concatModifierStrings, new String[] {modifierString, newModifierString});
+ }
+
}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditorMessages.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -35,6 +35,7 @@
public static String ToggleComment_error_message;
public static String CompletionProcessor_ContextInfo_value_pattern;
public static String CompletionProcessor_ContextInfo_display_pattern;
+ public static String EditorUtility_concatModifierStrings;
private static ResourceBundle fgResourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/WorkingCopyManager.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/WorkingCopyManager.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/WorkingCopyManager.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -18,6 +18,7 @@
import org.eclipse.jface.text.Assert;
import org.eclipse.ui.IEditorInput;
import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.internal.corext.util.RubyModelUtil;
import org.rubypeople.rdt.ui.IWorkingCopyManager;
import org.rubypeople.rdt.ui.IWorkingCopyManagerExtension;
@@ -80,10 +81,33 @@
* @see org.eclipse.jdt.ui.IWorkingCopyManager#getWorkingCopy(org.eclipse.ui.IEditorInput)
*/
public IRubyScript getWorkingCopy(IEditorInput input) {
- IRubyScript unit = fMap == null ? null : (IRubyScript) fMap.get(input);
- return unit != null ? unit : fDocumentProvider.getWorkingCopy(input);
+ return getWorkingCopy(input, true);
}
+ /**
+ * Returns the working copy remembered for the compilation unit encoded in the
+ * given editor input.
+ * <p>
+ * Note: This method must not be part of the public {@link IWorkingCopyManager} API.
+ * </p>
+ *
+ * @param input the editor input
+ * @param primaryOnly if <code>true</code> only primary working copies will be returned
+ * @return the working copy of the compilation unit, or <code>null</code> if the
+ * input does not encode an editor input, or if there is no remembered working
+ * copy for this compilation unit
+ * @since 3.2
+ */
+ public IRubyScript getWorkingCopy(IEditorInput input, boolean primaryOnly) {
+ IRubyScript unit= fMap == null ? null : (IRubyScript) fMap.get(input);
+ if (unit == null)
+ unit= fDocumentProvider.getWorkingCopy(input);
+ if (unit != null && (!primaryOnly || RubyModelUtil.isPrimary(unit)))
+ return unit;
+ return null;
+ }
+
+
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IWorkingCopyManagerExtension#setWorkingCopy(org.eclipse.ui.IEditorInput,
* org.eclipse.jdt.core.ICompilationUnit)
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/AbstractRubyEditorTextHover.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/AbstractRubyEditorTextHover.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/AbstractRubyEditorTextHover.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -1,17 +1,22 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
+ * Copyright (c) 2000, 2006 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/cpl-v10.html
- *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.rubypeople.rdt.internal.ui.text.ruby.hover;
-import java.util.List;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
@@ -20,14 +25,18 @@
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.commands.ICommand;
-import org.eclipse.ui.commands.ICommandManager;
-import org.eclipse.ui.commands.IKeySequenceBinding;
-import org.eclipse.ui.keys.KeySequence;
+import org.eclipse.ui.keys.IBindingService;
+import org.osgi.framework.Bundle;
+import org.rubypeople.rdt.core.ICodeAssist;
import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.util.Messages;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.rubyeditor.RubyScriptEditorInput;
+import org.rubypeople.rdt.internal.ui.rubyeditor.WorkingCopyManager;
import org.rubypeople.rdt.internal.ui.text.HTMLTextPresenter;
import org.rubypeople.rdt.internal.ui.text.RubyWordFinder;
import org.rubypeople.rdt.ui.PreferenceConstants;
@@ -36,19 +45,20 @@
/**
* Abstract class for providing hover information for Ruby elements.
- *
- * @since 2.1
+ *
+ * @since 1.0
*/
public abstract class AbstractRubyEditorTextHover implements IRubyEditorTextHover, ITextHoverExtension {
-
+ /**
+ * The style sheet (css).
+ * @since 1.0
+ */
+ private static String fgStyleSheet;
private IEditorPart fEditor;
- private ICommand fCommand;
+ private IBindingService fBindingService;
{
- ICommandManager commandManager= PlatformUI.getWorkbench().getCommandSupport().getCommandManager();
- fCommand= commandManager.getCommand(IRubyEditorActionDefinitionIds.SHOW_RDOC);
- if (!fCommand.isDefined())
- fCommand= null;
+ fBindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
}
/*
@@ -61,25 +71,68 @@
protected IEditorPart getEditor() {
return fEditor;
}
-
+
+ protected ICodeAssist getCodeAssist() {
+ if (fEditor != null) {
+ IEditorInput input= fEditor.getEditorInput();
+ if (input instanceof RubyScriptEditorInput) {
+ RubyScriptEditorInput cfeInput= (RubyScriptEditorInput) input;
+ return cfeInput.getRubyScript();
+ }
+
+ WorkingCopyManager manager= RubyPlugin.getDefault().getWorkingCopyManager();
+ return manager.getWorkingCopy(input, false);
+ }
+
+ return null;
+ }
+
/*
* @see ITextHover#getHoverRegion(ITextViewer, int)
*/
public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
return RubyWordFinder.findWord(textViewer.getDocument(), offset);
}
-
+
/*
* @see ITextHover#getHoverInfo(ITextViewer, IRegion)
*/
- public abstract String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion);
-
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ /*
+ * The region should be a word region an not of length 0.
+ * This check is needed because codeSelect(...) also finds
+ * the Ruby element if the offset is behind the word.
+ */
+ if (hoverRegion.getLength() == 0)
+ return null;
+
+ ICodeAssist resolve= getCodeAssist();
+ if (resolve != null) {
+ try {
+ IRubyElement[] result= resolve.codeSelect(hoverRegion.getOffset(), hoverRegion.getLength());
+ if (result == null)
+ return null;
+
+ int nResults= result.length;
+ if (nResults == 0)
+ return null;
+
+ return getHoverInfo(result);
+
+ } catch (RubyModelException x) {
+ return null;
+ }
+ }
+ return null;
+ }
+
/**
* Provides hover information for the given Ruby elements.
- *
- * @param javaElements the Ruby elements for which to provide hover information
+ *
+ * @param rubyElements the Ruby elements for which to provide hover information
* @return the hover information string
- * @since 2.1
+ * @since 1.0
*/
protected String getHoverInfo(IRubyElement[] rubyElements) {
return null;
@@ -87,7 +140,7 @@
/*
* @see ITextHoverExtension#getHoverControlCreator()
- * @since 3.0
+ * @since 1.0
*/
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
@@ -96,44 +149,52 @@
}
};
}
-
+
/**
* Returns the tool tip affordance string.
- *
+ *
* @return the affordance string or <code>null</code> if disabled or no key binding is defined
- * @since 3.0
+ * @since 1.0
*/
protected String getTooltipAffordanceString() {
- if (!RubyPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE))
+ if (fBindingService == null || !RubyPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE))
return null;
-
- KeySequence[] sequences= getKeySequences();
- if (sequences == null)
+
+ String keySequence= fBindingService.getBestActiveBindingFormattedFor(IRubyEditorActionDefinitionIds.SHOW_RDOC);
+ if (keySequence == null)
return null;
- String keySequence= sequences[0].format();
- return RubyHoverMessages.getFormattedString(RubyHoverMessages.RubyTextHover_makeStickyHint, keySequence);
+ return Messages.format(RubyHoverMessages.RubyTextHover_makeStickyHint, keySequence == null ? "" : keySequence); //$NON-NLS-1$
}
/**
- * Returns the array of valid key sequence bindings for the
- * show tool tip description command.
- *
- * @return the array with the {@link KeySequence}s
- *
- * @since 3.0
+ * Returns the style sheet.
+ *
+ * @since 1.0
*/
- private KeySequence[] getKeySequences() {
- if (fCommand != null) {
- List list= fCommand.getKeySequenceBindings();
- if (!list.isEmpty()) {
- KeySequence[] keySequences= new KeySequence[list.size()];
- for (int i= 0; i < keySequences.length; i++) {
- keySequences[i]= ((IKeySequenceBinding) list.get(i)).getKeySequence();
+ protected static String getStyleSheet() {
+ if (fgStyleSheet == null) {
+ Bundle bundle= Platform.getBundle(RubyPlugin.getPluginId());
+ URL styleSheetURL= bundle.getEntry("/RubydocHoverStyleSheet.css"); //$NON-NLS-1$
+ if (styleSheetURL != null) {
+ try {
+ styleSheetURL= FileLocator.toFileURL(styleSheetURL);
+ BufferedReader reader= new BufferedReader(new InputStreamReader(styleSheetURL.openStream()));
+ StringBuffer buffer= new StringBuffer(200);
+ String line= reader.readLine();
+ while (line != null) {
+ buffer.append(line);
+ buffer.append('\n');
+ line= reader.readLine();
+ }
+ fgStyleSheet= buffer.toString();
+ } catch (IOException ex) {
+ RubyPlugin.log(ex);
+ fgStyleSheet= ""; //$NON-NLS-1$
}
- return keySequences;
- }
+ }
}
- return null;
+ return fgStyleSheet;
}
+
}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/BestMatchHover.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/BestMatchHover.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/BestMatchHover.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.ui.text.ruby.hover;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextHoverExtension;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProviderExtension2;
+import org.eclipse.ui.IEditorPart;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.ui.PreferenceConstants;
+import org.rubypeople.rdt.ui.text.ruby.hover.IRubyEditorTextHover;
+
+/**
+ * Caution: this implementation is a layer breaker and contains some "shortcuts"
+ */
+public class BestMatchHover extends AbstractRubyEditorTextHover implements ITextHoverExtension, IInformationProviderExtension2 {
+
+ private List fTextHoverSpecifications;
+ private List fInstantiatedTextHovers;
+ private ITextHover fBestHover;
+
+ public BestMatchHover() {
+ installTextHovers();
+ }
+
+ public BestMatchHover(IEditorPart editor) {
+ this();
+ setEditor(editor);
+ }
+
+ /**
+ * Installs all text hovers.
+ */
+ private void installTextHovers() {
+
+ // initialize lists - indicates that the initialization happened
+ fTextHoverSpecifications= new ArrayList(2);
+ fInstantiatedTextHovers= new ArrayList(2);
+
+ // populate list
+ RubyEditorTextHoverDescriptor[] hoverDescs= RubyPlugin.getDefault().getRubyEditorTextHoverDescriptors();
+ for (int i= 0; i < hoverDescs.length; i++) {
+ // ensure that we don't add ourselves to the list
+ if (!PreferenceConstants.ID_BESTMATCH_HOVER.equals(hoverDescs[i].getId()))
+ fTextHoverSpecifications.add(hoverDescs[i]);
+ }
+ }
+
+ private void checkTextHovers() {
+ if (fTextHoverSpecifications.size() == 0)
+ return;
+
+ for (Iterator iterator= new ArrayList(fTextHoverSpecifications).iterator(); iterator.hasNext(); ) {
+ RubyEditorTextHoverDescriptor spec= (RubyEditorTextHoverDescriptor) iterator.next();
+
+ IRubyEditorTextHover hover= spec.createTextHover();
+ if (hover != null) {
+ hover.setEditor(getEditor());
+ addTextHover(hover);
+ fTextHoverSpecifications.remove(spec);
+ }
+ }
+ }
+
+ protected void addTextHover(ITextHover hover) {
+ if (!fInstantiatedTextHovers.contains(hover))
+ fInstantiatedTextHovers.add(hover);
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ checkTextHovers();
+ fBestHover= null;
+
+ if (fInstantiatedTextHovers == null)
+ return null;
+
+ for (Iterator iterator= fInstantiatedTextHovers.iterator(); iterator.hasNext(); ) {
+ ITextHover hover= (ITextHover)iterator.next();
+
+ String s= hover.getHoverInfo(textViewer, hoverRegion);
+ if (s != null && s.trim().length() > 0) {
+ fBestHover= hover;
+ return s;
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
+ * @since 3.0
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ if (fBestHover instanceof ITextHoverExtension)
+ return ((ITextHoverExtension)fBestHover).getHoverControlCreator();
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProviderExtension2#getInformationPresenterControlCreator()
+ * @since 3.0
+ */
+ public IInformationControlCreator getInformationPresenterControlCreator() {
+ if (fBestHover instanceof IInformationProviderExtension2)
+ return ((IInformationProviderExtension2)fBestHover).getInformationPresenterControlCreator();
+
+ return null;
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/ProblemHover.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/ProblemHover.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/ProblemHover.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.ui.text.ruby.hover;
+
+/**
+ * This annotation hover shows the description of the
+ * selected ruby annotation.
+ *
+ * @since 1.0
+ */
+public class ProblemHover extends AbstractAnnotationHover {
+
+ public ProblemHover() {
+ super(false);
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RiDocHoverProvider.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RiDocHoverProvider.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RiDocHoverProvider.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -10,16 +10,14 @@
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.ui.IEditorInput;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
-import org.rubypeople.rdt.launching.IVMInstall;
import org.rubypeople.rdt.launching.RubyRuntime;
-import org.rubypeople.rdt.ui.extensions.ITextHoverProvider;
-
-public class RiDocHoverProvider implements ITextHoverProvider {
- public String getHoverInfo(IEditorInput input, ITextViewer textViewer, IRegion hoverRegion){
- File ri = RubyRuntime.getRI();
+public class RiDocHoverProvider extends AbstractRubyEditorTextHover {
+
+ @Override
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+ File ri = RubyRuntime.getRI();
if (ri == null || !ri.exists() || !ri.isFile()) return null;
List<String> args = new ArrayList<String>();
@@ -64,8 +62,7 @@
RubyPlugin.log(e);
}
}
- }
-
+ }
return null;
}
}
Deleted: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyCodeTextHover.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyCodeTextHover.java 2007-05-01 18:09:19 UTC (rev 2414)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyCodeTextHover.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -1,82 +0,0 @@
-package org.rubypeople.rdt.internal.ui.text.ruby.hover;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExtension;
-import org.eclipse.core.runtime.IExtensionPoint;
-import org.eclipse.core.runtime.IExtensionRegistry;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.ITextViewer;
-import org.rubypeople.rdt.internal.ui.RubyPlugin;
-import org.rubypeople.rdt.ui.extensions.ITextHoverProvider;
-
-/**
- * Generic TextHover that uses installed extensions for getting information;
- * when the TextHover is requested then all installed TextHoverProvider
- * extensions will be asked to provide a String to show for the location.
- *
- * @author murphee
- *
- */
-public class RubyCodeTextHover extends AbstractRubyEditorTextHover {
-
- public static final String RDT_UI_NAMESPACE = "org.rubypeople.rdt.ui";
- public static final String RDT_UI_TEXTHOVERPROVIDER = "textHoverProvider";
-
- private List fExtensions;
-
- public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
- List extensions = initExtensions();
- if (extensions.isEmpty())
- return null;
- for (int i = 0; i < extensions.size(); i++) {
- ITextHoverProvider currentProvider = (ITextHoverProvider) extensions.get(i);
- String hoverText = currentProvider.getHoverInfo(getEditor().getEditorInput(), textViewer, hoverRegion);
- if (hoverText != null) {
- return hoverText;
- }
- }
- return null;
- }
-
- private List initExtensions() {
- if (fExtensions == null) {
- fExtensions = new ArrayList();
- IExtensionPoint point = getTextHoverExtensionPoint();
- if (point == null)
- return fExtensions;
- IExtension[] exts = point.getExtensions();
- for (int i = 0; i < exts.length; i++) {
- IConfigurationElement[] elem = exts[i].getConfigurationElements();
- String attrs[] = elem[0].getAttributeNames();
- try {
- Object tempProv = elem[0].createExecutableExtension("class");
- if (tempProv instanceof ITextHoverProvider) {
- ITextHoverProvider prov = (ITextHoverProvider) tempProv;
- fExtensions.add(prov);
- }
- } catch (Exception e) {
- RubyPlugin.log(e);
- }
- }
- }
- return fExtensions;
- }
-
- private IExtensionPoint getTextHoverExtensionPoint() {
- IExtensionRegistry reg = Platform.getExtensionRegistry();
- IExtensionPoint[] points = reg.getExtensionPoints(RDT_UI_NAMESPACE);
- if (points == null)
- return null;
- for (int i = 0; i < points.length; i++) {
- IExtensionPoint currentPoint = points[i];
- if (currentPoint.getUniqueIdentifier().endsWith(RDT_UI_TEXTHOVERPROVIDER)) {
- return currentPoint;
- }
- }
- return null;
- }
-}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverDescriptor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverDescriptor.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverDescriptor.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+
+package org.rubypeople.rdt.internal.ui.text.ruby.hover;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.swt.SWT;
+import org.osgi.framework.Bundle;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.rubyeditor.EditorUtility;
+import org.rubypeople.rdt.ui.PreferenceConstants;
+import org.rubypeople.rdt.ui.text.ruby.hover.IRubyEditorTextHover;
+
+/**
+ * Describes a Ruby editor text hover.
+ *
+ * @since 1.0
+ */
+public class RubyEditorTextHoverDescriptor {
+
+ private static final String RUBY_EDITOR_TEXT_HOVER_EXTENSION_POINT= "org.rubypeople.rdt.ui.rubyEditorTextHovers"; //$NON-NLS-1$
+ private static final String HOVER_TAG= "hover"; //$NON-NLS-1$
+ private static final String ID_ATTRIBUTE= "id"; //$NON-NLS-1$
+ private static final String CLASS_ATTRIBUTE= "class"; //$NON-NLS-1$
+ private static final String LABEL_ATTRIBUTE= "label"; //$NON-NLS-1$
+ private static final String ACTIVATE_PLUG_IN_ATTRIBUTE= "activate"; //$NON-NLS-1$
+ private static final String DESCRIPTION_ATTRIBUTE= "description"; //$NON-NLS-1$
+
+ public static final String NO_MODIFIER= "0"; //$NON-NLS-1$
+ public static final String DISABLED_TAG= "!"; //$NON-NLS-1$
+ public static final String VALUE_SEPARATOR= ";"; //$NON-NLS-1$
+
+ private int fStateMask;
+ private String fModifierString;
+ private boolean fIsEnabled;
+
+ private IConfigurationElement fElement;
+
+
+ /**
+ * Returns all Ruby editor text hovers contributed to the workbench.
+ */
+ public static RubyEditorTextHoverDescriptor[] getContributedHovers() {
+ IExtensionRegistry registry= Platform.getExtensionRegistry();
+ IConfigurationElement[] elements= registry.getConfigurationElementsFor(RUBY_EDITOR_TEXT_HOVER_EXTENSION_POINT);
+ RubyEditorTextHoverDescriptor[] hoverDescs= createDescriptors(elements);
+ initializeFromPreferences(hoverDescs);
+ return hoverDescs;
+ }
+
+ /**
+ * Computes the state mask for the given modifier string.
+ *
+ * @param modifiers the string with the modifiers, separated by '+', '-', ';', ',' or '.'
+ * @return the state mask or -1 if the input is invalid
+ */
+ public static int computeStateMask(String modifiers) {
+ if (modifiers == null)
+ return -1;
+
+ if (modifiers.length() == 0)
+ return SWT.NONE;
+
+ int stateMask= 0;
+ StringTokenizer modifierTokenizer= new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$
+ while (modifierTokenizer.hasMoreTokens()) {
+ int modifier= EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
+ if (modifier == 0 || (stateMask & modifier) == modifier)
+ return -1;
+ stateMask= stateMask | modifier;
+ }
+ return stateMask;
+ }
+
+ /**
+ * Creates a new Ruby Editor text hover descriptor from the given configuration element.
+ */
+ private RubyEditorTextHoverDescriptor(IConfigurationElement element) {
+ Assert.isNotNull(element);
+ fElement= element;
+ }
+
+ /**
+ * Creates the Ruby editor text hover.
+ */
+ public IRubyEditorTextHover createTextHover() {
+ String pluginId = fElement.getContributor().getName();
+ boolean isHoversPlugInActivated= Platform.getBundle(pluginId).getState() == Bundle.ACTIVE;
+ if (isHoversPlugInActivated || canActivatePlugIn()) {
+ try {
+ return (IRubyEditorTextHover)fElement.createExecutableExtension(CLASS_ATTRIBUTE);
+ } catch (CoreException x) {
+ RubyPlugin.log(new Status(IStatus.ERROR, RubyPlugin.getPluginId(), 0, RubyHoverMessages.RubyTextHover_createTextHover, null));
+ }
+ }
+
+ return null;
+ }
+
+ //---- XML Attribute accessors ---------------------------------------------
+
+ /**
+ * Returns the hover's id.
+ */
+ public String getId() {
+ return fElement.getAttribute(ID_ATTRIBUTE);
+ }
+
+ /**
+ * Returns the hover's class name.
+ */
+ public String getHoverClassName() {
+ return fElement.getAttribute(CLASS_ATTRIBUTE);
+ }
+
+ /**
+ * Returns the hover's label.
+ */
+ public String getLabel() {
+ String label= fElement.getAttribute(LABEL_ATTRIBUTE);
+ if (label != null)
+ return label;
+
+ // Return simple class name
+ label= getHoverClassName();
+ int lastDot= label.lastIndexOf('.');
+ if (lastDot >= 0 && lastDot < label.length() - 1)
+ return label.substring(lastDot + 1);
+ else
+ return label;
+ }
+
+ /**
+ * Returns the hover's description.
+ *
+ * @return the hover's description or <code>null</code> if not provided
+ */
+ public String getDescription() {
+ return fElement.getAttribute(DESCRIPTION_ATTRIBUTE);
+ }
+
+
+ public boolean canActivatePlugIn() {
+ return Boolean.valueOf(fElement.getAttribute(ACTIVATE_PLUG_IN_ATTRIBUTE)).booleanValue();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == null || !obj.getClass().equals(this.getClass()) || getId() == null)
+ return false;
+ return getId().equals(((RubyEditorTextHoverDescriptor)obj).getId());
+ }
+
+ public int hashCode() {
+ return getId().hashCode();
+ }
+
+ private static RubyEditorTextHoverDescriptor[] createDescriptors(IConfigurationElement[] elements) {
+ List result= new ArrayList(elements.length);
+ for (int i= 0; i < elements.length; i++) {
+ IConfigurationElement element= elements[i];
+ if (HOVER_TAG.equals(element.getName())) {
+ RubyEditorTextHoverDescriptor desc= new RubyEditorTextHoverDescriptor(element);
+ result.add(desc);
+ }
+ }
+ return (RubyEditorTextHoverDescriptor[])result.toArray(new RubyEditorTextHoverDescriptor[result.size()]);
+ }
+
+ private static void initializeFromPreferences(RubyEditorTextHoverDescriptor[] hovers) {
+ String compiledTextHoverModifiers= RubyPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
+
+ StringTokenizer tokenizer= new StringTokenizer(compiledTextHoverModifiers, VALUE_SEPARATOR);
+ HashMap idToModifier= new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id= tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifier.put(id, tokenizer.nextToken());
+ }
+
+ String compiledTextHoverModifierMasks= RubyPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
+
+ tokenizer= new StringTokenizer(compiledTextHoverModifierMasks, VALUE_SEPARATOR);
+ HashMap idToModifierMask= new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id= tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifierMask.put(id, tokenizer.nextToken());
+ }
+
+ for (int i= 0; i < hovers.length; i++) {
+ String modifierString= (String)idToModifier.get(hovers[i].getId());
+ boolean enabled= true;
+ if (modifierString == null)
+ modifierString= DISABLED_TAG;
+
+ if (modifierString.startsWith(DISABLED_TAG)) {
+ enabled= false;
+ modifierString= modifierString.substring(1);
+ }
+
+ if (modifierString.equals(NO_MODIFIER))
+ modifierString= ""; //$NON-NLS-1$
+
+ hovers[i].fModifierString= modifierString;
+ hovers[i].fIsEnabled= enabled;
+ hovers[i].fStateMask= computeStateMask(modifierString);
+ if (hovers[i].fStateMask == -1) {
+ // Fallback: use stored modifier masks
+ try {
+ hovers[i].fStateMask= Integer.parseInt((String)idToModifierMask.get(hovers[i].getId()));
+ } catch (NumberFormatException ex) {
+ hovers[i].fStateMask= -1;
+ }
+ // Fix modifier string
+ int stateMask= hovers[i].fStateMask;
+ if (stateMask == -1)
+ hovers[i].fModifierString= ""; //$NON-NLS-1$
+ else
+ hovers[i].fModifierString= EditorUtility.getModifierString(stateMask);
+ }
+ }
+ }
+
+ /**
+ * Returns the configured modifier getStateMask for this hover.
+ *
+ * @return the hover modifier stateMask or -1 if no hover is configured
+ */
+ public int getStateMask() {
+ return fStateMask;
+ }
+
+ /**
+ * Returns the modifier String as set in the preference store.
+ *
+ * @return the modifier string
+ */
+ public String getModifierString() {
+ return fModifierString;
+ }
+
+ /**
+ * Returns whether this hover is enabled or not.
+ *
+ * @return <code>true</code> if enabled
+ */
+ public boolean isEnabled() {
+ return fIsEnabled;
+ }
+
+ /**
+ * Returns this hover descriptors configuration element.
+ *
+ * @return the configuration element
+ * @since 3.0
+ */
+ public IConfigurationElement getConfigurationElement() {
+ return fElement;
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverProxy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverProxy.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/hover/RubyEditorTextHoverProxy.java 2007-05-02 13:17:08 UTC (rev 2415)
@@ -0,0 +1,109 @@
+/**************...
[truncated message content] |
|
From: <caw...@us...> - 2007-05-01 18:09:20
|
Revision: 2414
http://svn.sourceforge.net/rubyeclipse/?rev=2414&view=rev
Author: cawilliams
Date: 2007-05-01 11:09:19 -0700 (Tue, 01 May 2007)
Log Message:
-----------
Fix Trac # 4251 - Delete Next Word causes NPE: deleting the last code inside an RHMTL ruby snippet could cause us to try and grab bad locatiosn the dcument and not properly reset our lexerSource object inside the parser which caused NPEs. Now if we get a abd lcoation , just set lexerSource to an empty string to avoid the NPE
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java 2007-05-01 17:38:57 UTC (rev 2413)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java 2007-05-01 18:09:19 UTC (rev 2414)
@@ -297,7 +297,8 @@
lexerSource = new LexerSource("filename", new StringReader(contents));
lexer.setSource(lexerSource);
} catch (BadLocationException e) {
- RubyPlugin.log(e);
+ lexerSource = new LexerSource("filename", new StringReader(""));
+ lexer.setSource(lexerSource);
}
origOffset = offset;
origLength = length;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 17:38:59
|
Revision: 2413
http://svn.sourceforge.net/rubyeclipse/?rev=2413&view=rev
Author: cawilliams
Date: 2007-05-01 10:38:57 -0700 (Tue, 01 May 2007)
Log Message:
-----------
yikes, fix Trac # 4209 - Folder Selection getting appended to paths
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/rubyvms/VMLibraryBlock.java
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/rubyvms/VMLibraryBlock.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/rubyvms/VMLibraryBlock.java 2007-05-01 17:25:29 UTC (rev 2412)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/rubyvms/VMLibraryBlock.java 2007-05-01 17:38:57 UTC (rev 2413)
@@ -316,7 +316,7 @@
lastUsedPath= ""; //$NON-NLS-1$
}
DirectoryDialog dialog= new DirectoryDialog(fLibraryViewer.getControl().getShell(), SWT.MULTI);
- dialog.setText(RubyVMMessages.VMLibraryBlock_10);
+ dialog.setMessage(RubyVMMessages.VMLibraryBlock_10);
dialog.setFilterPath(lastUsedPath);
String res= dialog.open();
if (res == null) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 17:25:30
|
Revision: 2412
http://svn.sourceforge.net/rubyeclipse/?rev=2412&view=rev
Author: cawilliams
Date: 2007-05-01 10:25:29 -0700 (Tue, 01 May 2007)
Log Message:
-----------
add some more messy code to handle resolving a go to declaration on a method call. In this case,
we're adding code to handle some cases of VCallNodes - that is method calls with no receiver or args.
We can now handle cases where this occurs in the scope of a Class or Module (but not at top-level).
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-05-01 17:24:19 UTC (rev 2411)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-05-01 17:25:29 UTC (rev 2412)
@@ -8,18 +8,23 @@
import java.util.Set;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
import org.jruby.ast.ArgumentNode;
import org.jruby.ast.CallNode;
+import org.jruby.ast.ClassNode;
import org.jruby.ast.ClassVarAsgnNode;
import org.jruby.ast.ClassVarDeclNode;
import org.jruby.ast.ClassVarNode;
import org.jruby.ast.Colon2Node;
import org.jruby.ast.ConstNode;
+import org.jruby.ast.DefnNode;
+import org.jruby.ast.DefsNode;
import org.jruby.ast.FCallNode;
import org.jruby.ast.InstAsgnNode;
import org.jruby.ast.InstVarNode;
import org.jruby.ast.LocalAsgnNode;
import org.jruby.ast.LocalVarNode;
+import org.jruby.ast.ModuleNode;
import org.jruby.ast.Node;
import org.jruby.ast.VCallNode;
import org.jruby.ast.types.INameNode;
@@ -31,14 +36,25 @@
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchConstants;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
+import org.rubypeople.rdt.core.search.SearchMatch;
+import org.rubypeople.rdt.core.search.SearchParticipant;
+import org.rubypeople.rdt.core.search.SearchPattern;
import org.rubypeople.rdt.internal.core.RubyScript;
import org.rubypeople.rdt.internal.core.parser.RubyParser;
+import org.rubypeople.rdt.internal.core.search.BasicSearchEngine;
+import org.rubypeople.rdt.internal.core.search.CollectingSearchRequestor;
import org.rubypeople.rdt.internal.core.util.ASTUtil;
import org.rubypeople.rdt.internal.core.util.Util;
import org.rubypeople.rdt.internal.ti.DefaultTypeInferrer;
import org.rubypeople.rdt.internal.ti.ITypeGuess;
import org.rubypeople.rdt.internal.ti.ITypeInferrer;
+import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator;
+import org.rubypeople.rdt.internal.ti.util.INodeAcceptor;
import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator;
+import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator;
public class SelectionEngine {
@@ -102,23 +118,64 @@
return possible.toArray(new IRubyElement[possible.size()]);
}
if (isMethodCall(selected)) {
+ String methodName = getName(selected);
Set<IRubyElement> possible = new HashSet<IRubyElement>();
- ITypeInferrer inferrer = new DefaultTypeInferrer();
- List<ITypeGuess> guesses = inferrer.infer(source, start);
- RubyElementRequestor requestor = new RubyElementRequestor(script);
- String methodName = getName(selected);
- for (ITypeGuess guess : guesses) {
-
- String name = guess.getType();
- IType[] types = requestor.findType(name);
- for (int i = 0; i < types.length; i++) {
- IType type = types[i];
- Collection<IMethod> methods = suggestMethods(type);
- for (IMethod method : methods) {
- if (method.getElementName().equals(methodName))
- possible.add(method);
+ // FIXME If VCallNode we know the method is in the enclosing scope
+ // (usually the type or it's hierarchy)
+ if (selected instanceof VCallNode) {
+ Node enclosingTypeNode = ClosestSpanningNodeLocator.Instance()
+ .findClosestSpanner(root, start, new INodeAcceptor() {
+ public boolean doesAccept(Node node) {
+ return (node instanceof ClassNode || node instanceof ModuleNode);
+ }
+ });
+ if (enclosingTypeNode == null) {
+ // TODO Handle case we're in top-level - we need to find the method some other way!
+ RubyCore.log("Was unable to grab the enclosing type for our VCallNode. Maybe we're in top-level?");
+ return new IRubyElement[0];
+ }
+ String typeName = ASTUtil.getNameReflectively(enclosingTypeNode);
+ IRubySearchScope scope = SearchEngine.createRubySearchScope(new IRubyElement[] { script });
+ CollectingSearchRequestor requestor = new CollectingSearchRequestor();
+ SearchPattern pattern = SearchPattern.createPattern(
+ IRubyElement.TYPE, typeName,
+ IRubySearchConstants.DECLARATIONS,
+ SearchPattern.R_EXACT_MATCH);
+ SearchParticipant[] participants = { BasicSearchEngine.getDefaultSearchParticipant() };
+ try {
+ new BasicSearchEngine().search(pattern, participants, scope, requestor, null);
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ List<SearchMatch> matches = requestor.getResults();
+ if (matches == null || matches.isEmpty()) return new IRubyElement[0];
+ SearchMatch match = matches.get(0);
+ IType type = (IType) match.getElement();
+ Collection<IMethod> methods = suggestMethods(type);
+ for (IMethod method : methods) {
+ if (method.getElementName().equals(methodName))
+ possible.add(method);
+ }
+ } else {
+
+ ITypeInferrer inferrer = new DefaultTypeInferrer();
+ List<ITypeGuess> guesses = inferrer.infer(source, start);
+ RubyElementRequestor requestor = new RubyElementRequestor(
+ script);
+ for (ITypeGuess guess : guesses) {
+ String name = guess.getType();
+ IType[] types = requestor.findType(name);
+ for (int i = 0; i < types.length; i++) {
+ IType type = types[i];
+ Collection<IMethod> methods = suggestMethods(type);
+ for (IMethod method : methods) {
+ if (method.getElementName().equals(methodName))
+ possible.add(method);
+ }
}
}
+
}
return possible.toArray(new IRubyElement[possible.size()]);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 17:24:20
|
Revision: 2411
http://svn.sourceforge.net/rubyeclipse/?rev=2411&view=rev
Author: cawilliams
Date: 2007-05-01 10:24:19 -0700 (Tue, 01 May 2007)
Log Message:
-----------
handle grabbing name from ClassNode or ModuleNode
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/ASTUtil.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/ASTUtil.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/ASTUtil.java 2007-05-01 16:11:29 UTC (rev 2410)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/ASTUtil.java 2007-05-01 17:24:19 UTC (rev 2411)
@@ -8,6 +8,7 @@
import org.jruby.ast.ArgsNode;
import org.jruby.ast.ArgumentNode;
import org.jruby.ast.AttrAssignNode;
+import org.jruby.ast.ClassNode;
import org.jruby.ast.ClassVarAsgnNode;
import org.jruby.ast.Colon2Node;
import org.jruby.ast.ConstNode;
@@ -19,6 +20,7 @@
import org.jruby.ast.InstAsgnNode;
import org.jruby.ast.ListNode;
import org.jruby.ast.LocalAsgnNode;
+import org.jruby.ast.ModuleNode;
import org.jruby.ast.NilNode;
import org.jruby.ast.Node;
import org.jruby.ast.SelfNode;
@@ -147,6 +149,14 @@
* @return name or null
*/
public static String getNameReflectively(Node node) {
+ if (node instanceof ClassNode) {
+ ClassNode classNode = (ClassNode) node;
+ return getNameReflectively(classNode.getCPath());
+ }
+ if (node instanceof ModuleNode) {
+ ModuleNode moduleNode = (ModuleNode) node;
+ return getNameReflectively(moduleNode.getCPath());
+ }
if (node instanceof INameNode) {
return ((INameNode)node).getName();
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 16:11:31
|
Revision: 2410
http://svn.sourceforge.net/rubyeclipse/?rev=2410&view=rev
Author: cawilliams
Date: 2007-05-01 09:11:29 -0700 (Tue, 01 May 2007)
Log Message:
-----------
add some missing messages
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties 2007-05-01 16:06:07 UTC (rev 2409)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties 2007-05-01 16:11:29 UTC (rev 2410)
@@ -21,8 +21,6 @@
OpenTypeAction_dialogTitle=Open Type
OpenTypeAction_dialogMessage=&Select a type to open (? = any character, * = any String, SE = StandardError):
-TypeSelectionDialog2_title_format={0} - {1}
-
TypeSelectionComponent_label= &Matching types:
TypeSelectionComponent_menu=Menu
TypeSelectionComponent_fully_qualify_duplicates_label=Show &Container for Duplicates
@@ -41,6 +39,8 @@
TypeInfoViewer_syncJob_label=Synchronizing search tables
TypeInfoViewer_syncJob_taskName=Refreshing indices...
+TypeInfoLabelProvider_default_package=(root source folder)
+
#########################################
# RubyProjectLibraryPage
#########################################
@@ -74,6 +74,13 @@
StatusBarUpdater_num_elements_selected={0} items selected
+TypeSelectionDialog2_title_format={0} - {1}
+
+TypeSelectionDialog_progress_consistency=Initializing search indices...
+TypeSelectionDialog_error3Message=Unexpected exception. See log for details.
+TypeSelectionDialog_error3Title=Exception
+TypeSelectionDialog_error_type_doesnot_exist=Type {0} does not exist.
+
#########################################
# Ruby Search Page
#########################################
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 16:06:09
|
Revision: 2409
http://svn.sourceforge.net/rubyeclipse/?rev=2409&view=rev
Author: cawilliams
Date: 2007-05-01 09:06:07 -0700 (Tue, 01 May 2007)
Log Message:
-----------
add hacky hook into class creation so we can inject in imports,
fix test case wizard to import test/unit,
fix test case wizard to actually open the generated file after completing.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/internal/testunit/wizards/NewTestCaseCreationWizard.java
trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java
Modified: trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/internal/testunit/wizards/NewTestCaseCreationWizard.java
===================================================================
--- trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/internal/testunit/wizards/NewTestCaseCreationWizard.java 2007-05-01 15:30:23 UTC (rev 2408)
+++ trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/internal/testunit/wizards/NewTestCaseCreationWizard.java 2007-05-01 16:06:07 UTC (rev 2409)
@@ -1,252 +1,69 @@
package org.rubypeople.rdt.internal.testunit.wizards;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-
-import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.IWorkspaceRunnable;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.wizard.Wizard;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.INewWizard;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchWizard;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.ide.IDE;
-import org.rubypeople.rdt.core.RubyCore;
-import org.rubypeople.rdt.core.formatter.Indents;
-import org.rubypeople.rdt.internal.testunit.ui.TestunitPlugin;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
-import org.rubypeople.rdt.internal.ui.actions.WorkbenchRunnableAdapter;
-import org.rubypeople.rdt.internal.ui.util.ExceptionHandler;
-import org.rubypeople.rdt.internal.ui.wizards.NewWizardMessages;
+import org.rubypeople.rdt.internal.ui.wizards.NewElementWizard;
import org.rubypeople.rdt.testunit.wizards.RubyNewTestCaseWizardPage;
-public class NewTestCaseCreationWizard extends Wizard implements INewWizard {
-
- private static final String RUBY_FILE_EXTENSION = ".rb";
- private RubyNewTestCaseWizardPage page;
- private IStructuredSelection selection;
-
- /**
- * Constructor for SampleNewWizard.
- */
- public NewTestCaseCreationWizard() {
- super();
- setWindowTitle(WizardMessages.Wizard_title_new_testcase);
- setDefaultPageImageDescriptor(RubyPluginImages.DESC_WIZBAN_NEWCLASS);
- setNeedsProgressMonitor(true);
- }
-
- /**
- * Adding the page to the wizard.
- */
-
- public void addPages() {
- page = new RubyNewTestCaseWizardPage(selection);
- page.init(selection);
- addPage(page);
- }
-
- /**
- * This method is called when 'Finish' button is pressed in the wizard. We
- * will create an operation and run it using wizard as execution context.
- */
- public boolean performFinish() {
- IWorkspaceRunnable op= new IWorkspaceRunnable() {
- public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
- try {
- finishPage(monitor);
- } catch (InterruptedException e) {
- throw new OperationCanceledException(e.getMessage());
- }
- }
- };
- try {
- ISchedulingRule rule= null;
- Job job= Platform.getJobManager().currentJob();
- if (job != null)
- rule= job.getRule();
- IRunnableWithProgress runnable= null;
- if (rule != null)
- runnable= new WorkbenchRunnableAdapter(op, rule, true);
- else
- runnable= new WorkbenchRunnableAdapter(op, getSchedulingRule());
- getContainer().run(canRunForked(), true, runnable);
- } catch (InvocationTargetException e) {
- handleFinishException(getShell(), e);
- return false;
- } catch (InterruptedException e) {
- return false;
- }
- return true;
- }
-
- protected boolean canRunForked() {
- return true;
+public class NewTestCaseCreationWizard extends NewElementWizard {
+
+ private RubyNewTestCaseWizardPage fPage;
+
+ public NewTestCaseCreationWizard(RubyNewTestCaseWizardPage page) {
+ setDefaultPageImageDescriptor(RubyPluginImages.DESC_WIZBAN_NEWCLASS);
+ setDialogSettings(RubyPlugin.getDefault().getDialogSettings());
+ setWindowTitle(WizardMessages.Wizard_title_new_testcase);
+
+ fPage= page;
}
- /**
- * Returns the scheduling rule for creating the element.
- */
- protected ISchedulingRule getSchedulingRule() {
- return ResourcesPlugin.getWorkspace().getRoot(); // look all by default
+ public NewTestCaseCreationWizard() {
+ this(null);
}
-
- protected void handleFinishException(Shell shell, InvocationTargetException e) {
- String title= NewWizardMessages.NewElementWizard_op_error_title;
- String message= NewWizardMessages.NewElementWizard_op_error_message;
- ExceptionHandler.handle(e, shell, title, message);
- }
-
+
/*
- * (non-Javadoc)
- *
+ * @see Wizard#createPages
+ */
+ public void addPages() {
+ super.addPages();
+ if (fPage == null) {
+ fPage= new RubyNewTestCaseWizardPage();
+ fPage.init(getSelection());
+ }
+ addPage(fPage);
+ }
+
+ /* (non-Rubydoc)
* @see org.eclipse.jdt.internal.ui.wizards.NewElementWizard#finishPage(org.eclipse.core.runtime.IProgressMonitor)
*/
protected void finishPage(IProgressMonitor monitor) throws InterruptedException, CoreException {
- page.createType(monitor); // use the full progress monitor
+ fPage.createType(monitor); // use the full progress monitor
}
-
- /**
- * The worker method. It will find the container, create the file if missing
- * or just replace its contents, and open the editor on the newly created
- * file.
- * @param superclassName
- */
-
- private void doFinish(String containerName, String className, String superclassName, IProgressMonitor monitor)
- throws CoreException {
- // create a sample file
- monitor.beginTask("Creating " + className, 2);
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- IResource resource = root.findMember(new Path(containerName));
- if (!resource.exists() || !(resource instanceof IContainer)) {
- throwCoreException("Container \"" + containerName + "\" does not exist.");
- }
- IContainer container = (IContainer) resource;
- String fileName = classNameToFileName(className) + RUBY_FILE_EXTENSION;
-
- final IFile file = container.getFile(new Path(fileName));
- try {
- InputStream stream = openContentStream(className, superclassName);
- if (file.exists()) {
- file.setContents(stream, true, true, monitor);
- } else {
- file.create(stream, true, monitor);
- }
- stream.close();
- } catch (IOException e) {
- }
- monitor.worked(1);
- monitor.setTaskName("Opening file for editing...");
- getShell().getDisplay().asyncExec(new Runnable() {
-
- public void run() {
- IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
- .getActivePage();
- try {
- IDE.openEditor(page, file, true);
- } catch (PartInitException e) {
- }
- }
- });
- monitor.worked(1);
- }
-
- /**
- * Convert a Constant Class Name (in camels) to a file name (all lowercase,
- * uppercase characters get downcased and have underscores put in front,
- * except first character.)
- *
- * @param className
- * @return
- */
- private String classNameToFileName(String className) {
- className = stripNamespace(className);
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < className.length(); i++) {
- char c = className.charAt(i);
- if (Character.isUpperCase(c)) {
- if (i != 0) buffer.append('_');
- buffer.append(Character.toLowerCase(c));
- } else {
- buffer.append(c);
- }
- }
- return buffer.toString();
- }
-
- private String stripNamespace(String className) {
- if (className == null || className.length() == 0) return className;
- if (className.lastIndexOf("::") != -1) {
- return className.substring(className.lastIndexOf("::") + 2);
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.wizard.IWizard#performFinish()
+ */
+ public boolean performFinish() {
+ boolean res= super.performFinish();
+ if (res) {
+ IResource resource= fPage.getModifiedResource();
+ if (resource != null) {
+ selectAndReveal(resource);
+ openResource((IFile) resource);
+ }
}
- return className;
+ return res;
}
- /**
- * We will initialize file contents with a sample text.
- *
- * @param className
- * The Filename chosen by the user
- * @param superclassName
- */
-
- private InputStream openContentStream(String className, String superclassName) {
- StringBuffer contents = new StringBuffer();
- String endLine = System.getProperty("line.separator");
- if (endLine == null) endLine = "\n";
- contents.append("require 'test/unit'");
- contents.append(endLine);
-
- contents.append("class ");
- contents.append(className);
- contents.append(" < ");
- contents.append(superclassName);
- contents.append(endLine);
-
- contents.append(Indents.createIndentString(1, RubyCore.getOptions()));
- contents.append(endLine);
-
- contents.append(Indents.createIndentString(1, RubyCore.getOptions()));
- contents.append(endLine);
-
- contents.append("end");
- contents.append(endLine);
- return new ByteArrayInputStream(contents.toString().getBytes());
- }
-
- private void throwCoreException(String message) throws CoreException {
- IStatus status = new Status(IStatus.ERROR, TestunitPlugin.PLUGIN_ID, IStatus.OK, message, null);
- throw new CoreException(status);
- }
-
- /**
- * We will accept the selection in the workbench to see if we can initialize
- * from it.
- *
- * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
- */
- public void init(IWorkbench workbench, IStructuredSelection selection) {
- this.selection = selection;
- }
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.wizards.NewElementWizard#getCreatedElement()
+ */
+ public IRubyElement getCreatedElement() {
+ return fPage.getCreatedType();
+ }
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java
===================================================================
--- trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java 2007-05-01 15:30:23 UTC (rev 2408)
+++ trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java 2007-05-01 16:06:07 UTC (rev 2409)
@@ -1,12 +1,14 @@
package org.rubypeople.rdt.testunit.wizards;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
@@ -66,11 +68,11 @@
private IType fClassUnderTest;
/**
- * Constructor for SampleNewWizardPage.
+ * Constructor for RubyNewTestCaseWizardPage.
*
* @param pageName
*/
- public RubyNewTestCaseWizardPage(ISelection selection) {
+ public RubyNewTestCaseWizardPage() {
super(true, PAGE_NAME);
setTitle(WizardMessages.NewTestCaseWizardPage_title);
@@ -133,7 +135,7 @@
*/
protected void createTypeMembers(IType type, IProgressMonitor monitor) throws CoreException {
String lineDelimiter= StubUtility.getLineDelimiterUsed(type.getRubyProject());
-
+
if (fMethodStubsButtons.isSelected(IDX_CONSTRUCTOR)) {
createConstructor(type, lineDelimiter);
}
@@ -151,6 +153,13 @@
}
}
+ @Override
+ protected List<String> addImports() {
+ List<String> imports = new ArrayList<String>();
+ imports.add("test/unit");
+ // TODO Add import for class under test?
+ return imports;
+ }
private void createConstructor(IType type, String lineDelimiter) throws CoreException {
StringBuffer content = new StringBuffer("def initialize");
@@ -363,45 +372,30 @@
return fClassUnderTestText;
}
- /**
- * Initialized the page with the current selection
- * @param selection The selection
+ /**
+ * The wizard owning this page is responsible for calling this method with the
+ * current selection. The selection is used to initialize the fields of the wizard
+ * page.
+ *
+ * @param selection used to initialize the fields
*/
public void init(IStructuredSelection selection) {
- IRubyElement element= getInitialRubyElement(selection);
-
- initContainerPage(element);
- // TODO Uncomment to set up type page
-// initTypePage(element);
- // put default class to test
-// if (element != null) {
-// IType classToTest= null;
- // evaluate the enclosing type
-// IType typeInCompUnit= (IType) element.getAncestor(IRubyElement.TYPE);
-// if (typeInCompUnit != null) {
-// if (typeInCompUnit.getRubyScript() != null) {
-// classToTest= typeInCompUnit;
-// }
-// } else {
-// IRubyScript cu= (IRubyScript) element.getAncestor(IRubyElement.SCRIPT);
-// if (cu != null)
-// classToTest= cu.findPrimaryType();
+ IRubyElement jelem= getInitialRubyElement(selection);
+ initContainerPage(jelem);
+ initTypePage(jelem);
+ doStatusUpdate();
+
+// boolean createConstructors= false;
+// boolean createUnimplemented= true;
+// IDialogSettings dialogSettings= getDialogSettings();
+// if (dialogSettings != null) {
+// IDialogSettings section= dialogSettings.getSection(PAGE_NAME);
+// if (section != null) {
+// createConstructors= section.getBoolean(SETTINGS_CREATECONSTR);
// }
- // TODO uncomment to set class under test
-// if (classToTest != null) {
-// try {
-// if (!TestSearchEngine.isTestImplementor(classToTest)) {
-// setClassUnderTest(classToTest.getFullyQualifiedName('.'));
-// }
-// } catch (RubyModelException e) {
-// TestunitPlugin.log(e);
-// }
-// }
// }
-
- restoreWidgetValues();
-
- updateStatus(getStatusList());
+//
+// setMethodStubSelection(createConstructors, true);
}
/**
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java 2007-05-01 15:30:23 UTC (rev 2408)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java 2007-05-01 16:06:07 UTC (rev 2409)
@@ -685,7 +685,17 @@
}
private String constructSimpleTypeStub(String lineDelimiter) {
- StringBuffer buf= new StringBuffer("class "); //$NON-NLS-1$
+ StringBuffer buf= new StringBuffer(); //$NON-NLS-1$
+ List<String> imports = addImports();
+ if (imports != null) {
+ for (String string : imports) {
+ buf.append("require \"");
+ buf.append(string);
+ buf.append('"');
+ buf.append(lineDelimiter);
+ }
+ }
+ buf.append("class "); //$NON-NLS-1$
buf.append(getTypeName());
String superclass = getSuperClass();
if (superclass != null && superclass.trim().length() > 0 && !superclass.trim().equals("Object") ) {
@@ -697,6 +707,11 @@
return buf.toString();
}
+ protected List<String> addImports() {
+ // This is an ugly hack since we don't have an Iportsmanager or ImportRewrite yet.
+ return null;
+ }
+
/**
* Opens a selection dialog that allows to select the super interfaces. The selected interfaces are
* directly added to the wizard page using {@link #addSuperModule(String)}.
@@ -772,10 +787,10 @@
}
/**
- * Returns the resource handle that corresponds to the compilation unit to was or
+ * Returns the resource handle that corresponds to the ruby script that was or
* will be created or modified.
* @return A resource or null if the page contains illegal values.
- * @since 3.0
+ * @since 1.0
*/
public IResource getModifiedResource() {
ISourceFolder pack= getSourceFolder();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 15:30:33
|
Revision: 2408
http://svn.sourceforge.net/rubyeclipse/?rev=2408&view=rev
Author: cawilliams
Date: 2007-05-01 08:30:23 -0700 (Tue, 01 May 2007)
Log Message:
-----------
change our wizards to use new type selection dialogs,
remove unused RubyModuleSelectionDialog,
fix class stub creation to take superclass into account,
make test case creation use proper line delimeters so Eclipse doesn't complain.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java
trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java
trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/dialogfields/ListDialogField.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyClassSelectionDialog.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/SuperModuleSelectionDialog.java
Removed Paths:
-------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyModuleSelectionDialog.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.core.search;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.core.WorkingCopyOwner;
import org.rubypeople.rdt.internal.core.search.BasicSearchEngine;
@@ -95,4 +96,8 @@
this.basicEngine.searchAllTypeNames(packageName, typeName, matchRule, searchFor, scope, nameRequestor, waitingPolicy, progressMonitor);
}
+ public static IRubySearchScope createRubySearchScope(IRubyElement[] elements) {
+ return BasicSearchEngine.createRubySearchScope(elements);
+ }
+
}
Modified: trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java
===================================================================
--- trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.testunit/src/org/rubypeople/rdt/testunit/wizards/RubyNewTestCaseWizardPage.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -26,13 +26,17 @@
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyConventions;
import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchConstants;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
+import org.rubypeople.rdt.internal.corext.codemanipulation.StubUtility;
import org.rubypeople.rdt.internal.corext.util.Messages;
import org.rubypeople.rdt.internal.testunit.util.LayoutUtil;
import org.rubypeople.rdt.internal.testunit.util.TestUnitStatus;
import org.rubypeople.rdt.internal.testunit.wizards.MethodStubsSelectionButtonGroup;
import org.rubypeople.rdt.internal.testunit.wizards.WizardMessages;
+import org.rubypeople.rdt.internal.ui.dialogs.TypeSelectionDialog2;
import org.rubypeople.rdt.ui.wizards.NewTypeWizardPage;
-import org.rubypeople.rdt.ui.wizards.RubyClassSelectionDialog;
public class RubyNewTestCaseWizardPage extends NewTypeWizardPage {
@@ -127,47 +131,58 @@
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#createTypeMembers(org.eclipse.jdt.core.IType, org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager, org.eclipse.core.runtime.IProgressMonitor)
*/
- protected void createTypeMembers(IType type, IProgressMonitor monitor) throws CoreException {
+ protected void createTypeMembers(IType type, IProgressMonitor monitor) throws CoreException {
+ String lineDelimiter= StubUtility.getLineDelimiterUsed(type.getRubyProject());
+
if (fMethodStubsButtons.isSelected(IDX_CONSTRUCTOR)) {
- createConstructor(type);
+ createConstructor(type, lineDelimiter);
}
if (fMethodStubsButtons.isSelected(IDX_SETUP)) {
- createSetUp(type);
+ createSetUp(type, lineDelimiter);
}
if (fMethodStubsButtons.isSelected(IDX_TEARDOWN)) {
- createTearDown(type);
+ createTearDown(type, lineDelimiter);
}
if (fClassUnderTest != null) {
- createTestMethodStubs(type);
+ createTestMethodStubs(type, lineDelimiter);
}
}
- private void createConstructor(IType type) throws CoreException {
- StringBuffer content = new StringBuffer("def initialize\n");
- content.append(" super\n");
- content.append("end\n");
+ private void createConstructor(IType type, String lineDelimiter) throws CoreException {
+ StringBuffer content = new StringBuffer("def initialize");
+ content.append(lineDelimiter);
+ content.append(" super");
+ content.append(lineDelimiter);
+ content.append("end");
+ content.append(lineDelimiter);
type.createMethod(content.toString(), null, true, null);
}
- private void createSetUp(IType type) throws CoreException {
- StringBuffer content = new StringBuffer("def setup\n");
- content.append(" super\n");
- content.append("end\n");
+ private void createSetUp(IType type, String lineDelimiter) throws CoreException {
+ StringBuffer content = new StringBuffer("def setup");
+ content.append(lineDelimiter);
+ content.append(" super");
+ content.append(lineDelimiter);
+ content.append("end");
+ content.append(lineDelimiter);
type.createMethod(content.toString(), null, true, null);
}
- private void createTearDown(IType type) throws CoreException {
- StringBuffer content = new StringBuffer("def teardown\n");
- content.append(" super\n");
- content.append("end\n");
+ private void createTearDown(IType type, String lineDelimiter) throws CoreException {
+ StringBuffer content = new StringBuffer("def teardown");
+ content.append(lineDelimiter);
+ content.append(" super");
+ content.append(lineDelimiter);
+ content.append("end");
+ content.append(lineDelimiter);
type.createMethod(content.toString(), null, true, null);
}
- private void createTestMethodStubs(IType type) throws CoreException {
+ private void createTestMethodStubs(IType type, String lineDelimiter) throws CoreException {
// StringBuffer content = new StringBuffer("def setup");
// content.append(" super\n");
// content.append("end\n");
@@ -238,21 +253,21 @@
private IType chooseClassToTestType() {
ISourceFolderRoot root= getSourceFolderRoot();
- if (root == null)
+ if (root == null) {
return null;
+ }
+
+ IRubyElement[] elements= new IRubyElement[] { root.getRubyProject() };
+ IRubySearchScope scope= SearchEngine.createRubySearchScope(elements);
-// IRubyElement[] elements= new IRubyElement[] { root.getRubyProject() };
+ TypeSelectionDialog2 dialog= new TypeSelectionDialog2(getShell(), false,
+ getWizard().getContainer(), scope, IRubySearchConstants.CLASS);
+ dialog.setTitle(WizardMessages.NewTestCaseWizardPage_class_to_test_dialog_title);
+ dialog.setMessage(WizardMessages.NewTestCaseWizardPage_class_to_test_dialog_message);
-
- RubyClassSelectionDialog dialog = new RubyClassSelectionDialog(getShell());
- dialog.setTitle(WizardMessages.NewTestCaseWizardPage_class_to_test_dialog_title);
- dialog.setMessage(WizardMessages.NewTestCaseWizardPage_class_to_test_dialog_message);
- if (dialog.open() == Window.OK) {
- Object[] resultArray= dialog.getResult();
- if (resultArray != null && resultArray.length > 0)
- return (IType) resultArray[0];
- }
-
+ if (dialog.open() == Window.OK) {
+ return (IType) dialog.getFirstResult();
+ }
return null;
}
Modified: trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
===================================================================
--- trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-05-01 15:30:23 UTC (rev 2408)
@@ -8,6 +8,7 @@
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.rubypeople.rdt.internal.corext,
+ org.rubypeople.rdt.internal.corext.codemanipulation,
org.rubypeople.rdt.internal.corext.util,
org.rubypeople.rdt.internal.ui,
org.rubypeople.rdt.internal.ui.actions,
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -27,6 +27,7 @@
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
@@ -566,5 +567,21 @@
if (fTypeFilter == null)
fTypeFilter= new TypeFilter();
return fTypeFilter;
+ }
+
+ /**
+ * Returns a section in the Ruby plugin's dialog settings. If the section doesn't exist yet, it is created.
+ *
+ * @param name the name of the section
+ * @return the section of the given name
+ * @since 1.0
+ */
+ public IDialogSettings getDialogSettingsSection(String name) {
+ IDialogSettings dialogSettings= getDialogSettings();
+ IDialogSettings section= dialogSettings.getSection(name);
+ if (section == null) {
+ section= dialogSettings.addNewSection(name);
+ }
+ return section;
}
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -363,6 +363,11 @@
public static String RubyCapabilityConfigurationPage_description;
public static String RubyCapabilityConfigurationPage_op_desc_java;
public static String LoadPathDetector_operation_description;
+ public static String NewTypeWizardPage_SuperClassDialog_message;
+ public static String NewTypeWizardPage_SuperClassDialog_title;
+ public static String SuperModuleSelectionDialog_addButton_label;
+ public static String SuperModuleSelectionDialog_interfaceadded_info;
+ public static String SuperModuleSelectionDialog_interfacealreadyadded_info;
static {
NLS.initializeMessages(BUNDLE_NAME, NewWizardMessages.class);
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.properties 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/NewWizardMessages.properties 2007-05-01 15:30:23 UTC (rev 2408)
@@ -49,6 +49,9 @@
NewTypeWizardPage_error_EnterTypeName=Type name is empty.
+NewTypeWizardPage_SuperClassDialog_title=Superclass Selection
+NewTypeWizardPage_SuperClassDialog_message=&Choose a type:
+
NewTypeWizardPage_package_button=Bro&wse...
NewTypeWizardPage_package_label=Folder:
NewTypeWizardPage_ChoosePackageDialog_title=Package Selection
@@ -57,6 +60,12 @@
NewTypeWizardPage_error_InvalidPackageName=Package name is not valid. {0}
NewTypeWizardPage_warning_DiscouragedPackageName=This package name is discouraged. {0}
+# ------- SuperModuleSelectionDialog -----
+
+SuperModuleSelectionDialog_addButton_label=&Add
+SuperModuleSelectionDialog_interfaceadded_info=''{0}'' added.
+SuperModuleSelectionDialog_interfacealreadyadded_info=''{0}'' already in list.
+
# ------- NewClassWizardPage -------
NewClassCreationWizard_title=New Ruby Class
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/SuperModuleSelectionDialog.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/SuperModuleSelectionDialog.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/SuperModuleSelectionDialog.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.ui.wizards;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.search.IRubySearchConstants;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
+import org.rubypeople.rdt.internal.corext.util.Messages;
+import org.rubypeople.rdt.internal.corext.util.TypeInfo;
+import org.rubypeople.rdt.internal.ui.IRubyHelpContextIds;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.dialogs.StatusInfo;
+import org.rubypeople.rdt.internal.ui.dialogs.TypeSelectionDialog2;
+import org.rubypeople.rdt.ui.wizards.NewTypeWizardPage;
+
+public class SuperModuleSelectionDialog extends TypeSelectionDialog2 {
+
+ private static final int ADD_ID= IDialogConstants.CLIENT_ID + 1;
+
+ private NewTypeWizardPage fTypeWizardPage;
+ private List fOldContent;
+
+ public SuperModuleSelectionDialog(Shell parent, IRunnableContext context, NewTypeWizardPage page, IRubyProject p) {
+ super(parent, true, context, createSearchScope(p), IRubySearchConstants.MODULE);
+ fTypeWizardPage= page;
+ // to restore the content of the dialog field if the dialog is canceled
+ fOldContent= fTypeWizardPage.getSuperModules();
+ setStatusLineAboveButtons(true);
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, ADD_ID, NewWizardMessages.SuperModuleSelectionDialog_addButton_label, true);
+ super.createButtonsForButtonBar(parent);
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
+ */
+ protected IDialogSettings getDialogBoundsSettings() {
+ return RubyPlugin.getDefault().getDialogSettingsSection("DialogBounds_SuperModuleSelectionDialog"); //$NON-NLS-1$
+ }
+
+ protected void updateButtonsEnableState(IStatus status) {
+ super.updateButtonsEnableState(status);
+ Button addButton = getButton(ADD_ID);
+ if (addButton != null && !addButton.isDisposed())
+ addButton.setEnabled(!status.matches(IStatus.ERROR));
+ }
+
+ protected void handleShellCloseEvent() {
+ super.handleShellCloseEvent();
+ // Handle the closing of the shell by selecting the close icon
+ fTypeWizardPage.setSuperModules(fOldContent, true);
+ }
+
+ protected void cancelPressed() {
+ fTypeWizardPage.setSuperModules(fOldContent, true);
+ super.cancelPressed();
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == ADD_ID){
+ addSelectedInterface();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected void okPressed() {
+ addSelectedInterface();
+ super.okPressed();
+ }
+
+ private void addSelectedInterface() {
+ TypeInfo[] selection= getSelectedTypes();
+ if (selection == null)
+ return;
+ for (int i= 0; i < selection.length; i++) {
+ TypeInfo type= selection[i];
+ String qualifiedName= type.getFullyQualifiedName();
+ String message;
+ if (fTypeWizardPage.addSuperModule(qualifiedName)) {
+ message= Messages.format(NewWizardMessages.SuperModuleSelectionDialog_interfaceadded_info, qualifiedName);
+ } else {
+ message= Messages.format(NewWizardMessages.SuperModuleSelectionDialog_interfacealreadyadded_info, qualifiedName);
+ }
+ updateStatus(new StatusInfo(IStatus.INFO, message));
+ }
+ }
+
+ private static IRubySearchScope createSearchScope(IRubyProject p) {
+ return SearchEngine.createRubySearchScope(new IRubyProject[] { p });
+ }
+
+ protected void handleDefaultSelected(TypeInfo[] selection) {
+ if (selection.length > 0)
+ buttonPressed(ADD_ID);
+ }
+
+ protected void handleWidgetSelected(TypeInfo[] selection) {
+ super.handleWidgetSelected(selection);
+ getButton(ADD_ID).setEnabled(selection.length > 0);
+ }
+
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IRubyHelpContextIds.SUPER_INTERFACE_SELECTION_DIALOG);
+ }
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/dialogfields/ListDialogField.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/dialogfields/ListDialogField.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/wizards/dialogfields/ListDialogField.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -604,16 +604,16 @@
/**
* Adds an element at the end of the list.
*/
- public void addElement(Object element) {
- addElement(element, fElements.size());
+ public boolean addElement(Object element) {
+ return addElement(element, fElements.size());
}
/**
* Adds an element at a position.
*/
- public void addElement(Object element, int index) {
+ public boolean addElement(Object element, int index) {
if (fElements.contains(element)) {
- return;
+ return false;
}
fElements.add(index, element);
if (isOkToUse(fTableControl)) {
@@ -622,6 +622,7 @@
}
dialogFieldChanged();
+ return true;
}
/**
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/NewTypeWizardPage.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.ui.wizards;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IResource;
@@ -31,6 +32,9 @@
import org.rubypeople.rdt.core.RubyConventions;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.core.formatter.CodeFormatter;
+import org.rubypeople.rdt.core.search.IRubySearchConstants;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
import org.rubypeople.rdt.internal.core.RubyProject;
import org.rubypeople.rdt.internal.corext.codemanipulation.StubUtility;
import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil;
@@ -39,7 +43,9 @@
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
import org.rubypeople.rdt.internal.ui.dialogs.StatusInfo;
+import org.rubypeople.rdt.internal.ui.dialogs.TypeSelectionDialog2;
import org.rubypeople.rdt.internal.ui.wizards.NewWizardMessages;
+import org.rubypeople.rdt.internal.ui.wizards.SuperModuleSelectionDialog;
import org.rubypeople.rdt.internal.ui.wizards.dialogfields.DialogField;
import org.rubypeople.rdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.rubypeople.rdt.internal.ui.wizards.dialogfields.IListAdapter;
@@ -110,13 +116,13 @@
private StringButtonStatusDialogField fPackageDialogField;
private StringButtonDialogField fSuperClassDialogField;
- private ListDialogField fSuperInterfacesDialogField;
+ private ListDialogField fSuperModulesDialogField;
private IType fCreatedType;
protected IStatus fTypeNameStatus;
protected IStatus fSuperClassStatus;
- protected IStatus fSuperInterfacesStatus;
+ protected IStatus fSuperModulesStatus;
private int fTypeKind;
private ISourceFolder fCurrSourceFolder;
@@ -182,15 +188,15 @@
/* 1 */ null,
NewWizardMessages.NewTypeWizardPage_interfaces_remove
};
- fSuperInterfacesDialogField= new ListDialogField(adapter, addButtons, new InterfacesListLabelProvider());
- fSuperInterfacesDialogField.setDialogFieldListener(adapter);
- fSuperInterfacesDialogField.setTableColumns(new ListDialogField.ColumnsDescription(1, false));
- fSuperInterfacesDialogField.setLabelText(getSuperInterfacesLabel());
- fSuperInterfacesDialogField.setRemoveButtonIndex(2);
+ fSuperModulesDialogField= new ListDialogField(adapter, addButtons, new InterfacesListLabelProvider());
+ fSuperModulesDialogField.setDialogFieldListener(adapter);
+ fSuperModulesDialogField.setTableColumns(new ListDialogField.ColumnsDescription(1, false));
+ fSuperModulesDialogField.setLabelText(getSuperModulesLabel());
+ fSuperModulesDialogField.setRemoveButtonIndex(2);
fTypeNameStatus= new StatusInfo();
fSuperClassStatus= new StatusInfo();
- fSuperInterfacesStatus= new StatusInfo();
+ fSuperModulesStatus= new StatusInfo();
}
/**
@@ -316,7 +322,7 @@
* @return the label that is used for the super interfaces input field.
* @since 3.2
*/
- protected String getSuperInterfacesLabel() {
+ protected String getSuperModulesLabel() {
if (fTypeKind != INTERFACE_TYPE)
return NewWizardMessages.NewTypeWizardPage_interfaces_class_label;
return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label;
@@ -472,12 +478,12 @@
}
private void typePageCustomButtonPressed(DialogField field, int index) {
- if (field == fSuperInterfacesDialogField) {
- chooseSuperInterfaces();
- List interfaces= fSuperInterfacesDialogField.getElements();
+ if (field == fSuperModulesDialogField) {
+ chooseSuperModules();
+ List interfaces= fSuperModulesDialogField.getElements();
if (!interfaces.isEmpty()) {
Object element= interfaces.get(interfaces.size() - 1);
- fSuperInterfacesDialogField.editElement(element);
+ fSuperModulesDialogField.editElement(element);
}
}
}
@@ -681,6 +687,11 @@
private String constructSimpleTypeStub(String lineDelimiter) {
StringBuffer buf= new StringBuffer("class "); //$NON-NLS-1$
buf.append(getTypeName());
+ String superclass = getSuperClass();
+ if (superclass != null && superclass.trim().length() > 0 && !superclass.trim().equals("Object") ) {
+ buf.append(" < ");
+ buf.append(superclass.trim());
+ }
buf.append(lineDelimiter);
buf.append("end"); //$NON-NLS-1$
return buf.toString();
@@ -688,27 +699,73 @@
/**
* Opens a selection dialog that allows to select the super interfaces. The selected interfaces are
- * directly added to the wizard page using {@link #addSuperInterface(String)}.
+ * directly added to the wizard page using {@link #addSuperModule(String)}.
*
* <p>
* Clients can override this method if they want to offer a different dialog.
* </p>
*
- * @since 3.2
+ * @since 1.0
*/
- protected void chooseSuperInterfaces() {
+ protected void chooseSuperModules() {
ISourceFolderRoot root= getSourceFolderRoot();
if (root == null) {
return;
}
- RubyModuleSelectionDialog dialog = new RubyModuleSelectionDialog(getShell());
- dialog.setTitle(getInterfaceDialogTitle());
+ IRubyProject project= root.getRubyProject();
+ SuperModuleSelectionDialog dialog= new SuperModuleSelectionDialog(getShell(), getWizard().getContainer(), this, project);
+ dialog.setTitle(getModuleDialogTitle());
dialog.setMessage(NewWizardMessages.NewTypeWizardPage_InterfacesDialog_message);
- dialog.open();
+ dialog.open();
}
- private String getInterfaceDialogTitle() {
+ /**
+ * Sets the super interfaces.
+ *
+ * @param interfacesNames a list of super interface. The method requires that
+ * the list's elements are of type <code>String</code>
+ * @param canBeModified if <code>true</code> the super interface field is
+ * editable; otherwise it is read-only.
+ */
+ public void setSuperModules(List interfacesNames, boolean canBeModified) {
+ ArrayList interfaces= new ArrayList(interfacesNames.size());
+ for (Iterator iter= interfacesNames.iterator(); iter.hasNext();) {
+ interfaces.add(new InterfaceWrapper((String) iter.next()));
+ }
+ fSuperModulesDialogField.setElements(interfaces);
+ fSuperModulesDialogField.setEnabled(canBeModified);
+ }
+
+ /**
+ * Returns the chosen super interfaces.
+ *
+ * @return a list of chosen super interfaces. The list's elements
+ * are of type <code>String</code>
+ */
+ public List getSuperModules() {
+ List interfaces= fSuperModulesDialogField.getElements();
+ ArrayList result= new ArrayList(interfaces.size());
+ for (Iterator iter= interfaces.iterator(); iter.hasNext();) {
+ InterfaceWrapper wrapper= (InterfaceWrapper) iter.next();
+ result.add(wrapper.interfaceName);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a super interface to the end of the list and selects it if it is not in the list yet.
+ *
+ * @param superInterface the fully qualified type name of the interface.
+ * @return returns <code>true</code>if the interfaces has been added, <code>false</code>
+ * if the interface already is in the list.
+ * @since 1.0
+ */
+ public boolean addSuperModule(String superInterface) {
+ return fSuperModulesDialogField.addElement(new InterfaceWrapper(superInterface));
+ }
+
+ private String getModuleDialogTitle() {
if (fTypeKind == INTERFACE_TYPE)
return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_interface_title;
return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_class_title;
@@ -741,8 +798,8 @@
} else if (field == fSuperClassDialogField) {
fSuperClassStatus= superClassChanged();
fieldName= SUPER;
- } else if (field == fSuperInterfacesDialogField) {
- fSuperInterfacesStatus= superInterfacesChanged();
+ } else if (field == fSuperModulesDialogField) {
+ fSuperModulesStatus= superInterfacesChanged();
fieldName= INTERFACES;
} else {
fieldName= METHODS;
@@ -820,7 +877,7 @@
fContainerStatus,
fTypeNameStatus,
fSuperClassStatus,
- fSuperInterfacesStatus
+ fSuperModulesStatus
};
// the mode severe status will be displayed and the OK button enabled/disabled.
@@ -932,10 +989,10 @@
StatusInfo status= new StatusInfo();
ISourceFolderRoot root= getSourceFolderRoot();
- fSuperInterfacesDialogField.enableButton(0, root != null);
+ fSuperModulesDialogField.enableButton(0, root != null);
if (root != null) {
- List elements= fSuperInterfacesDialogField.getElements();
+ List elements= fSuperModulesDialogField.getElements();
int nElements= elements.size();
for (int i= 0; i < nElements; i++) {
// TODO Check to make sure each interface exists and is valid
@@ -961,15 +1018,23 @@
* different dialog.
* </p>
*
- * @since 3.2
+ * @since 0.9
*/
protected IType chooseSuperClass() {
ISourceFolderRoot root= getSourceFolderRoot();
if (root == null) {
return null;
- }
+ }
- RubyClassSelectionDialog dialog = new RubyClassSelectionDialog(getShell());
+ IRubyElement[] elements= new IRubyElement[] { root.getRubyProject() };
+ IRubySearchScope scope= SearchEngine.createRubySearchScope(elements);
+
+ TypeSelectionDialog2 dialog= new TypeSelectionDialog2(getShell(), false,
+ getWizard().getContainer(), scope, IRubySearchConstants.CLASS);
+ dialog.setTitle(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_title);
+ dialog.setMessage(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_message);
+ dialog.setFilter(getSuperClass());
+
if (dialog.open() == Window.OK) {
return (IType) dialog.getFirstResult();
}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyClassSelectionDialog.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyClassSelectionDialog.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyClassSelectionDialog.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -6,9 +6,16 @@
import org.eclipse.swt.widgets.Shell;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.internal.ui.dialogs.TypeSelectionDialog2;
+/**
+ *
+ * @author Chris Williams
+ * @deprecated Please use {@link TypeSelectionDialog2}
+ */
public class RubyClassSelectionDialog extends RubyTypeSelectionDialog {
-
+// XXX Remve all references to this and remove it and its parent!
+
public RubyClassSelectionDialog(Shell parent) {
super(parent);
}
Deleted: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyModuleSelectionDialog.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyModuleSelectionDialog.java 2007-05-01 14:54:54 UTC (rev 2407)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/wizards/RubyModuleSelectionDialog.java 2007-05-01 15:30:23 UTC (rev 2408)
@@ -1,28 +0,0 @@
-package org.rubypeople.rdt.ui.wizards;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.swt.widgets.Shell;
-import org.rubypeople.rdt.core.IRubyElement;
-import org.rubypeople.rdt.core.IType;
-
-public class RubyModuleSelectionDialog extends RubyTypeSelectionDialog {
-
- public RubyModuleSelectionDialog(Shell parent) {
- super(parent);
- }
-
- protected Object[] getElements() {
- Object[] types = super.getElements();
- List classes = new ArrayList();
- for (int i = 0; i < types.length; i++) {
- IType type = (IType) types[i];
- if (type.isModule()) classes.add(types[i]);
- }
- IRubyElement[] elements = new IRubyElement[classes.size()];
- System.arraycopy(classes.toArray(), 0, elements, 0, elements.length);
- return elements;
- }
-
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 14:54:58
|
Revision: 2407
http://svn.sourceforge.net/rubyeclipse/?rev=2407&view=rev
Author: cawilliams
Date: 2007-05-01 07:54:54 -0700 (Tue, 01 May 2007)
Log Message:
-----------
add the underlying code for us to enable the new type selection dialog. Also fix an error in the way I was generating index keys for type delcratiosn which caused us to never get any matches (I was storing the folder hierarchy in the place for type name and vice versa)
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyScript.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchConstants.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchScope.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchPattern.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/NamedMember.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScript.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/BasicSearchEngine.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/RubySearchScope.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/TypeNameRequestor.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyScript.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyScript.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IRubyScript.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -375,4 +375,6 @@
IRubyElement getElementAt(int position) throws RubyModelException;
IType findPrimaryType();
+
+ IType[] getAllTypes() throws RubyModelException;
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IType.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -176,4 +176,16 @@
public ISourceFolder getSourceFolder();
+ public String getTypeQualifiedName(String string);
+
+ /**
+ * Returns the immediate member types declared by this type.
+ * The results are listed in the order in which they appear in the source or class file.
+ *
+ * @exception RubyModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the immediate member types declared by this type
+ */
+ IType[] getTypes() throws RubyModelException;
+
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchConstants.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchConstants.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchConstants.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -50,4 +50,39 @@
* @since 2.0
*/
int WRITE_ACCESSES = 5;
+
+/* Nature of searched element */
+
+ /**
+ * The searched element is a type, which may include classes and modules.
+ */
+ int TYPE= 0;
+
+ /**
+ * The searched element is a method.
+ */
+ int METHOD= 1;
+
+ /**
+ * The searched element is a constructor.
+ */
+ int CONSTRUCTOR= 3;
+
+ /**
+ * The searched element is a field.
+ */
+ int FIELD= 4;
+
+ /**
+ * The searched element is a class.
+ * More selective than using {@link #TYPE}.
+ */
+ int CLASS= 5;
+
+ /**
+ * The searched element is a module.
+ * More selective than using {@link #TYPE}.
+ */
+ int MODULE= 6;
+
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchScope.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchScope.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/IRubySearchScope.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.core.search;
import org.eclipse.core.runtime.IPath;
+import org.rubypeople.rdt.core.IRubyElement;
public interface IRubySearchScope {
@@ -68,4 +69,6 @@
*/
public boolean encloses(String resourcePath);
+ boolean encloses(IRubyElement element);
+
}
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchEngine.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -0,0 +1,98 @@
+package org.rubypeople.rdt.core.search;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.WorkingCopyOwner;
+import org.rubypeople.rdt.internal.core.search.BasicSearchEngine;
+
+public class SearchEngine {
+
+ private BasicSearchEngine basicEngine;
+
+ /**
+ * Creates a new search engine.
+ */
+ public SearchEngine() {
+ this.basicEngine = new BasicSearchEngine();
+ }
+
+ /**
+ * Creates a new search engine with the given working copy owner.
+ * The working copies owned by this owner will take precedence over
+ * the primary compilation units in the subsequent search operations.
+ *
+ * @param workingCopyOwner the owner of the working copies that take precedence over their original compilation units
+ * @since 1.0
+ */
+ public SearchEngine(WorkingCopyOwner workingCopyOwner) {
+ this.basicEngine = new BasicSearchEngine(workingCopyOwner);
+ }
+
+ public static IRubySearchScope createWorkspaceScope() {
+ return BasicSearchEngine.createWorkspaceScope();
+ }
+
+ /**
+ * Searches for all top-level types and member types in the given scope.
+ * The search can be selecting specific types (given a package or a type name
+ * prefix and match modes).
+ *
+ * @param packageName the full name of the package of the searched types, or a prefix for this
+ * package, or a wild-carded string for this package.
+ * @param typeName the dot-separated qualified name of the searched type (the qualification include
+ * the enclosing types if the searched type is a member type), or a prefix
+ * for this type, or a wild-carded string for this type.
+ * @param matchRule one of
+ * <ul>
+ * <li>{@link SearchPattern#R_EXACT_MATCH} if the package name and type name are the full names
+ * of the searched types.</li>
+ * <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name and type name are prefixes of the names
+ * of the searched types.</li>
+ * <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name and type name contain wild-cards.</li>
+ * <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are camel case of the names of the searched types.</li>
+ * </ul>
+ * combined with {@link SearchPattern#R_CASE_SENSITIVE},
+ * e.g. {@link SearchPattern#R_EXACT_MATCH} | {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * or {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case sensitive match is requested.
+ * @param searchFor determines the nature of the searched elements
+ * <ul>
+ * <li>{@link IJavaSearchConstants#CLASS}: only look for classes</li>
+ * <li>{@link IJavaSearchConstants#INTERFACE}: only look for interfaces</li>
+ * <li>{@link IJavaSearchConstants#ENUM}: only look for enumeration</li>
+ * <li>{@link IJavaSearchConstants#ANNOTATION_TYPE}: only look for annotation type</li>
+ * <li>{@link IJavaSearchConstants#CLASS_AND_ENUM}: only look for classes and enumerations</li>
+ * <li>{@link IJavaSearchConstants#CLASS_AND_INTERFACE}: only look for classes and interfaces</li>
+ * <li>{@link IJavaSearchConstants#TYPE}: look for all types (ie. classes, interfaces, enum and annotation types)</li>
+ * </ul>
+ * @param scope the scope to search in
+ * @param nameRequestor the requestor that collects the results of the search
+ * @param waitingPolicy one of
+ * <ul>
+ * <li>{@link IJavaSearchConstants#FORCE_IMMEDIATE_SEARCH} if the search should start immediately</li>
+ * <li>{@link IJavaSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH} if the search should be cancelled if the
+ * underlying indexer has not finished indexing the workspace</li>
+ * <li>{@link IJavaSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if the search should wait for the
+ * underlying indexer to finish indexing the workspace</li>
+ * </ul>
+ * @param progressMonitor the progress monitor to report progress to, or <code>null</code> if no progress
+ * monitor is provided
+ * @exception JavaModelException if the search failed. Reasons include:
+ * <ul>
+ * <li>the classpath is incorrectly set</li>
+ * </ul>
+ * @since 1.0
+ */
+ public void searchAllTypeNames(
+ final char[] packageName,
+ final char[] typeName,
+ final int matchRule,
+ int searchFor,
+ IRubySearchScope scope,
+ final TypeNameRequestor nameRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws RubyModelException {
+
+ this.basicEngine.searchAllTypeNames(packageName, typeName, matchRule, searchFor, scope, nameRequestor, waitingPolicy, progressMonitor);
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchPattern.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchPattern.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/SearchPattern.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.core.search;
import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.internal.compiler.parser.ScannerHelper;
import org.rubypeople.rdt.internal.core.search.indexing.IIndexConstants;
import org.rubypeople.rdt.internal.core.search.matching.ConstructorPattern;
import org.rubypeople.rdt.internal.core.search.matching.FieldPattern;
@@ -466,5 +467,325 @@
matchRule);
}
}
+
+ /**
+ * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
+ * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * <br>
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ * <br>
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ * <br><br>
+ * Examples:
+ * <ol>
+ * <li><pre>
+ * pattern = "NPE"
+ * name = NullPointerException / NoPermissionException
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "NuPoEx"
+ * name = NullPointerException
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "npe"
+ * name = NullPointerException
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ * @see CharOperation#camelCaseMatch(char[], char[])
+ * Implementation has been entirely copied from this method except for array lengthes
+ * which were obviously replaced with calls to {@link String#length()}.
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @return true if the pattern matches the given name, false otherwise
+ * @since 3.2
+ */
+ public static final boolean camelCaseMatch(String pattern, String name) {
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (name == null)
+ return false; // null name cannot match
+
+ return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length());
+ }
+ /**
+ * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.
+ * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * Can match only subset of name/pattern, considering end positions as non-inclusive.
+ * The subpattern is defined by the patternStart and patternEnd positions.
+ * <br>
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ * <br>
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ * <br><br>
+ * Examples:
+ * <ol>
+ * <li><pre>
+ * pattern = "NPE"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "NPE"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NoPermissionException
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "NuPoEx"
+ * patternStart = 0
+ * patternEnd = 6
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "NuPoEx"
+ * patternStart = 0
+ * patternEnd = 6
+ * name = NoPermissionException
+ * nameStart = 0
+ * nameEnd = 21
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = "npe"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int)
+ * Implementation has been entirely copied from this method except for array lengthes
+ * which were obviously replaced with calls to {@link String#length()} and
+ * for array direct access which were replaced with calls to {@link String#charAt(int)}.
+ *
+ * @param pattern the given pattern
+ * @param patternStart the start index of the pattern, inclusive
+ * @param patternEnd the end index of the pattern, exclusive
+ * @param name the given name
+ * @param nameStart the start index of the name, inclusive
+ * @param nameEnd the end index of the name, exclusive
+ * @return true if a sub-pattern matches the subpart of the given name, false otherwise
+ * @since 3.2
+ */
+ public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) {
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (patternEnd < 0) patternEnd = pattern.length();
+ if (nameEnd < 0) nameEnd = name.length();
+
+ if (patternEnd <= patternStart) return nameEnd <= nameStart;
+ if (nameEnd <= nameStart) return false;
+ // check first pattern char
+ if (name.charAt(nameStart) != pattern.charAt(patternStart)) {
+ // first char must strictly match (upper/lower)
+ return false;
+ }
+
+ char patternChar, nameChar;
+ int iPattern = patternStart;
+ int iName = nameStart;
+
+ // Main loop is on pattern characters
+ while (true) {
+
+ iPattern++;
+ iName++;
+
+ if (iPattern == patternEnd) {
+ // We have exhausted pattern, so it's a match
+ return true;
+ }
+
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ // For as long as we're exactly matching, bring it on (even if it's a lower case character)
+ if ((patternChar = pattern.charAt(iPattern)) == name.charAt(iName)) {
+ continue;
+ }
+
+ // If characters are not equals, then it's not a match if patternChar is lowercase
+ if (patternChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & ScannerHelper.C_UPPER_LETTER) == 0) {
+ return false;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar)) {
+ return false;
+ }
+
+ // patternChar is uppercase, so let's find the next uppercase in name
+ while (true) {
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ nameChar = name.charAt(iName);
+
+ if (nameChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & (ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_SPECIAL | ScannerHelper.C_DIGIT)) != 0) {
+ // nameChar is lowercase
+ iName++;
+ // nameChar is uppercase...
+ } else if (patternChar != nameChar) {
+ //.. and it does not match patternChar, so it's not a match
+ return false;
+ } else {
+ //.. and it matched patternChar. Back to the big loop
+ break;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(nameChar) && !Character.isUpperCase(nameChar)) {
+ // nameChar is lowercase
+ iName++;
+ // nameChar is uppercase...
+ } else if (patternChar != nameChar) {
+ //.. and it does not match patternChar, so it's not a match
+ return false;
+ } else {
+ //.. and it matched patternChar. Back to the big loop
+ break;
+ }
+ }
+ // At this point, either name has been exhausted, or it is at an uppercase letter.
+ // Since pattern is also at an uppercase letter
+ }
+ }
+
+ /**
+ * Validate compatibility between given string pattern and match rule.
+ *<br>
+ * Optimized (ie. returned match rule is modified) combinations are:
+ * <ul>
+ * <li>{@link #R_PATTERN_MATCH} without any '*' or '?' in string pattern:
+ * pattern match bit is unset,
+ * </li>
+ * <li>{@link #R_PATTERN_MATCH} and {@link #R_PREFIX_MATCH} bits simultaneously set:
+ * prefix match bit is unset,
+ * </li>
+ * <li>{@link #R_PATTERN_MATCH} and {@link #R_CAMELCASE_MATCH} bits simultaneously set:
+ * camel case match bit is unset,
+ * </li>
+ * <li>{@link #R_CAMELCASE_MATCH} with invalid combination of uppercase and lowercase characters:
+ * camel case match bit is unset and replaced with prefix match pattern,
+ * </li>
+ * <li>{@link #R_CAMELCASE_MATCH} combined with {@link #R_PREFIX_MATCH} and {@link #R_CASE_SENSITIVE}
+ * bits is reduced to only {@link #R_CAMELCASE_MATCH} as Camel Case search is already prefix and case sensitive,
+ * </li>
+ * </ul>
+ *<br>
+ * Rejected (ie. returned match rule -1) combinations are:
+ * <ul>
+ * <li>{@link #R_REGEXP_MATCH} with any other match mode bit set,
+ * </li>
+ * </ul>
+ *
+ * @param stringPattern The string pattern
+ * @param matchRule The match rule
+ * @return Optimized valid match rule or -1 if an incompatibility was detected.
+ * @since 3.2
+ */
+ public static int validateMatchRule(String stringPattern, int matchRule) {
+
+ // Verify Regexp match rule
+ if ((matchRule & R_REGEXP_MATCH) != 0) {
+ if ((matchRule & R_PATTERN_MATCH) != 0 || (matchRule & R_PREFIX_MATCH) != 0 || (matchRule & R_CAMELCASE_MATCH) != 0) {
+ return -1;
+ }
+ }
+
+ // Verify Pattern match rule
+ int starIndex = stringPattern.indexOf('*');
+ int questionIndex = stringPattern.indexOf('?');
+ if (starIndex < 0 && questionIndex < 0) {
+ // reset pattern match bit if any
+ matchRule &= ~R_PATTERN_MATCH;
+ } else {
+ // force Pattern rule
+ matchRule |= R_PATTERN_MATCH;
+ }
+ if ((matchRule & R_PATTERN_MATCH) != 0) {
+ // remove Camel Case and Prefix match bits if any
+ matchRule &= ~R_CAMELCASE_MATCH;
+ matchRule &= ~R_PREFIX_MATCH;
+ }
+
+ // Verify Camel Case match rule
+ if ((matchRule & R_CAMELCASE_MATCH) != 0) {
+ // Verify sting pattern validity
+ int length = stringPattern.length();
+ boolean validCamelCase = true;
+ boolean uppercase = false;
+ for (int i=0; i<length && validCamelCase; i++) {
+ char ch = stringPattern.charAt(i);
+ validCamelCase = ScannerHelper.isJavaIdentifierStart(ch);
+ // at least one uppercase character is need in CamelCase pattern
+ // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=136313)
+ if (!uppercase) uppercase = ScannerHelper.isUpperCase(ch);
+ }
+ validCamelCase = validCamelCase && uppercase;
+ // Verify bits compatibility
+ if (validCamelCase) {
+ if ((matchRule & R_PREFIX_MATCH) != 0) {
+ if ((matchRule & R_CASE_SENSITIVE) != 0) {
+ // This is equivalent to Camel Case match rule
+ matchRule &= ~R_PREFIX_MATCH;
+ matchRule &= ~R_CASE_SENSITIVE;
+ }
+ }
+ } else {
+ matchRule &= ~R_CAMELCASE_MATCH;
+ if ((matchRule & R_PREFIX_MATCH) == 0) {
+ matchRule |= R_PREFIX_MATCH;
+ matchRule |= R_CASE_SENSITIVE;
+ }
+ }
+ }
+ return matchRule;
+ }
+
}
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/TypeNameRequestor.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/TypeNameRequestor.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/search/TypeNameRequestor.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.core.search;
+
+/**
+ * A <code>TypeNameRequestor</code> collects search results from a <code>searchAllTypeNames</code>
+ * query to a <code>SearchEngine</code>. Clients must subclass this abstract class and pass
+ * an instance to the <code>SearchEngine.searchAllTypeNames(...)</code> method. Only top-level and
+ * member types are reported. Local types are not reported.
+ * <p>
+ * This class may be subclassed by clients.
+ * </p>
+ * @since 1.0
+ */
+public abstract class TypeNameRequestor {
+ /**
+ * Accepts a top-level or a member type.
+ * <p>
+ * The default implementation of this method does nothing.
+ * Subclasses should override.
+ * </p>
+ *
+ * @param modifiers the modifier flags of the type. Note that for source type,
+ * these flags may slightly differ from thoses get after resolution.
+ * For example an interface defined by <code>interface A {}</code>,
+ * although obviously public, will be returned false by <code>Flags.isPublic(modifiers)</code>
+ * due to the fact that its declaration does not explicitely define public flag.
+ * @see org.eclipse.jdt.core.Flags
+ * @param packageName the dot-separated name of the package of the type
+ * @param simpleTypeName the simple name of the type
+ * @param enclosingTypeNames if the type is a member type,
+ * the simple names of the enclosing types from the outer-most to the
+ * direct parent of the type (for example, if the class is x.y.A$B$C then
+ * the enclosing types are [A, B]. This is an empty array if the type
+ * is a top-level type.
+ * @param path the full path to the resource containing the type. If the resource is a .class file
+ * or a source file, this is the full path in the workspace to this resource. If the
+ * resource is an archive (that is, a .zip or .jar file), the path is composed of 2 paths separated
+ * by <code>IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR</code>:
+ * the first path is the full OS path to the archive (if it is an external archive),
+ * or the workspace relative <code>IPath</code> to the archive (if it is an internal archive),
+ * the second path is the path to the resource inside the archive.
+ */
+ public void acceptType(boolean isModule, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
+ // do nothing
+ }
+}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/parser/ScannerHelper.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -1,7 +1,6 @@
package org.rubypeople.rdt.internal.compiler.parser;
-
public class ScannerHelper {
public final static int MAX_OBVIOUS = 128;
public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];
@@ -101,5 +100,19 @@
}
}
return Character.toLowerCase(c);
+ }
+
+ public static boolean isUpperCase(char c) {
+ if (c < MAX_OBVIOUS) {
+ return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0;
+ }
+ return Character.isUpperCase(c);
+ }
+
+ public static boolean isJavaIdentifierStart(char c) {
+ if (c < MAX_OBVIOUS) {
+ return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
+ }
+ return Character.isJavaIdentifierStart(c);
+ }
}
-}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/NamedMember.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/NamedMember.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/NamedMember.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -10,7 +10,11 @@
*******************************************************************************/
package org.rubypeople.rdt.internal.core;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.RubyModelException;
+
public abstract class NamedMember extends Member {
/*
@@ -27,4 +31,26 @@
public String getElementName() {
return this.name;
}
+
+ public String getTypeQualifiedName(String enclosingTypeSeparator, boolean showParameters) throws RubyModelException {
+ NamedMember declaringType;
+ switch (this.parent.getElementType()) {
+ case IRubyElement.SCRIPT:
+ return this.name;
+ case IRubyElement.TYPE:
+ declaringType = (NamedMember) this.parent;
+ break;
+ case IRubyElement.FIELD:
+ case IRubyElement.METHOD:
+ declaringType = (NamedMember) ((IMember) this.parent).getDeclaringType();
+ break;
+ default:
+ return null;
+ }
+ StringBuffer buffer = new StringBuffer(declaringType.getTypeQualifiedName(enclosingTypeSeparator, showParameters));
+ buffer.append(enclosingTypeSeparator);
+ String simpleName = this.name.length() == 0 ? Integer.toString(this.occurrenceCount) : this.name;
+ buffer.append(simpleName);
+ return buffer.toString();
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScript.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScript.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScript.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -645,7 +645,7 @@
}
/**
- * @see ICompilationUnit#getTypeNames()
+ * @see IRubyScript#getTypeNames()
*/
public IType[] getTypes() throws RubyModelException {
ArrayList list = getChildrenOfType(TYPE);
@@ -707,4 +707,29 @@
protected char getHandleMementoDelimiter() {
return RubyElement.JEM_RUBYSCRIPT;
}
+
+ /**
+ * @see IRubyScript#getAllTypes()
+ */
+ public IType[] getAllTypes() throws RubyModelException {
+ IRubyElement[] types = getTypes();
+ int i;
+ ArrayList allTypes = new ArrayList(types.length);
+ ArrayList typesToTraverse = new ArrayList(types.length);
+ for (i = 0; i < types.length; i++) {
+ typesToTraverse.add(types[i]);
+ }
+ while (!typesToTraverse.isEmpty()) {
+ IType type = (IType) typesToTraverse.get(0);
+ typesToTraverse.remove(type);
+ allTypes.add(type);
+ types = type.getTypes();
+ for (i = 0; i < types.length; i++) {
+ typesToTraverse.add(types[i]);
+ }
+ }
+ IType[] arrayOfAllTypes = new IType[allTypes.size()];
+ allTypes.toArray(arrayOfAllTypes);
+ return arrayOfAllTypes;
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyType.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -281,4 +281,26 @@
return null;
}
+ /**
+ * @see IType#getTypeQualifiedName(char)
+ */
+ public String getTypeQualifiedName(String enclosingTypeSeparator) {
+ try {
+ return getTypeQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
+ } catch (RubyModelException e) {
+ // exception thrown only when showing parameters
+ return null;
+ }
+ }
+
+ /**
+ * @see IType
+ */
+ public IType[] getTypes() throws RubyModelException {
+ ArrayList list= getChildrenOfType(TYPE);
+ IType[] array= new IType[list.size()];
+ list.toArray(array);
+ return array;
+ }
+
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/BasicSearchEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/BasicSearchEngine.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/BasicSearchEngine.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -10,6 +10,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
+import org.rubypeople.rdt.core.Flags;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.IType;
@@ -19,21 +20,31 @@
import org.rubypeople.rdt.core.search.IRubySearchConstants;
import org.rubypeople.rdt.core.search.IRubySearchScope;
import org.rubypeople.rdt.core.search.SearchDocument;
+import org.rubypeople.rdt.core.search.SearchEngine;
import org.rubypeople.rdt.core.search.SearchMatch;
import org.rubypeople.rdt.core.search.SearchParticipant;
import org.rubypeople.rdt.core.search.SearchPattern;
import org.rubypeople.rdt.core.search.SearchRequestor;
+import org.rubypeople.rdt.core.search.TypeNameRequestor;
import org.rubypeople.rdt.internal.core.DefaultWorkingCopyOwner;
import org.rubypeople.rdt.internal.core.RubyModelManager;
import org.rubypeople.rdt.internal.core.RubyProject;
import org.rubypeople.rdt.internal.core.RubyScript;
+import org.rubypeople.rdt.internal.core.search.indexing.IIndexConstants;
import org.rubypeople.rdt.internal.core.search.indexing.IndexManager;
import org.rubypeople.rdt.internal.core.search.matching.MatchLocator;
+import org.rubypeople.rdt.internal.core.search.matching.RubySearchPattern;
+import org.rubypeople.rdt.internal.core.search.matching.TypeDeclarationPattern;
+import org.rubypeople.rdt.internal.core.util.CharOperation;
import org.rubypeople.rdt.internal.core.util.Messages;
import org.rubypeople.rdt.internal.core.util.Util;
public class BasicSearchEngine {
+ // Type decl kinds
+ public static final int CLASS_DECL = 1;
+ public static final int MODULE_DECL = 2;
+
public static final boolean VERBOSE = false;
/*
@@ -48,7 +59,22 @@
*/
private WorkingCopyOwner workingCopyOwner;
+
+ /*
+ * Creates a new search basic engine.
+ */
+ public BasicSearchEngine() {
+ // will use working copies of PRIMARY owner
+ }
+
/**
+ * @see SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
+ */
+ public BasicSearchEngine(WorkingCopyOwner workingCopyOwner) {
+ this.workingCopyOwner = workingCopyOwner;
+ }
+
+ /**
* Searches for matches of a given search pattern. Search patterns can be created using helper
* methods (from a String pattern or a Ruby element) and encapsulate the description of what is
* being searched (for example, search method declarations in a case sensitive way).
@@ -270,4 +296,272 @@
return types;
}
}
+
+
+ /**
+ * Searches for all top-level types and member types in the given scope.
+ * The search can be selecting specific types (given a package or a type name
+ * prefix and match modes).
+ *
+ * @see SearchEngine#searchAllTypeNames(char[], char[], int, int, IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor)
+ * for detailed comment
+ */
+ public void searchAllTypeNames(
+ final char[] packageName,
+ final char[] typeName,
+ final int matchRule,
+ int searchFor,
+ IRubySearchScope scope,
+ final TypeNameRequestor nameRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws RubyModelException {
+
+ if (VERBOSE) {
+ Util.verbose("BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IRubySearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
+ Util.verbose(" - package name: "+(packageName==null?"null":new String(packageName))); //$NON-NLS-1$ //$NON-NLS-2$
+ Util.verbose(" - type name: "+(typeName==null?"null":new String(typeName))); //$NON-NLS-1$ //$NON-NLS-2$
+ Util.verbose(" - match rule: "+getMatchRuleString(matchRule)); //$NON-NLS-1$
+ Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$
+ Util.verbose(" - scope: "+scope); //$NON-NLS-1$
+ }
+
+ // Return on invalid combination of package and type names
+ if (packageName == null || packageName.length == 0) {
+ if (typeName != null && typeName.length == 0) {
+ if (VERBOSE) {
+ Util.verbose(" => return no result due to invalid empty values for package and type names!"); //$NON-NLS-1$
+ }
+ return;
+ }
+ }
+
+ IndexManager indexManager = RubyModelManager.getRubyModelManager().getIndexManager();
+ final char typeSuffix;
+ switch(searchFor){
+ case IRubySearchConstants.CLASS :
+ typeSuffix = IIndexConstants.CLASS_SUFFIX;
+ break;
+// case IRubySearchConstants.CLASS_AND_MODULE :
+// typeSuffix = IIndexConstants.CLASS_AND_MODULE_SUFFIX; FIXME Converge the TYPE_SUFFIX and CLASS_AND_MODULE_SUFFIX
+// break;
+ case IRubySearchConstants.MODULE :
+ typeSuffix = IIndexConstants.MODULE_SUFFIX;
+ break;
+ default :
+ typeSuffix = IIndexConstants.TYPE_SUFFIX;
+ break;
+ }
+ final TypeDeclarationPattern pattern = new TypeDeclarationPattern(
+ packageName,
+ null, // do find member types
+ typeName,
+ typeSuffix,
+ matchRule);
+
+ // Get working copy path(s). Store in a single string in case of only one to optimize comparison in requestor
+ final HashSet workingCopyPaths = new HashSet();
+ String workingCopyPath = null;
+ IRubyScript[] copies = getWorkingCopies();
+ final int copiesLength = copies == null ? 0 : copies.length;
+ if (copies != null) {
+ if (copiesLength == 1) {
+ workingCopyPath = copies[0].getPath().toString();
+ } else {
+ for (int i = 0; i < copiesLength; i++) {
+ IRubyScript workingCopy = copies[i];
+ workingCopyPaths.add(workingCopy.getPath().toString());
+ }
+ }
+ }
+ final String singleWkcpPath = workingCopyPath;
+
+ // Index requestor
+ IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
+ public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+ // Filter unexpected types
+ TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
+ if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) {
+ return true; // filter out local and anonymous classes
+ }
+ switch (copiesLength) {
+ case 0:
+ break;
+ case 1:
+ if (singleWkcpPath.equals(documentPath)) {
+ return true; // fliter out *the* working copy
+ }
+ break;
+ default:
+ if (workingCopyPaths.contains(documentPath)) {
+ return true; // filter out working copies
+ }
+ break;
+ }
+
+ // Accept document path
+ if (match(record.typeSuffix, record.modifiers)) {
+ nameRequestor.acceptType(record.typeSuffix == IIndexConstants.MODULE_SUFFIX, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath);
+ }
+ return true;
+ }
+ };
+
+ try {
+ if (progressMonitor != null) {
+ progressMonitor.beginTask(Messages.engine_searching, 100);
+ }
+ // add type names from indexes
+ indexManager.performConcurrentJob(
+ new PatternSearchJob(
+ pattern,
+ getDefaultSearchParticipant(), // Ruby search only
+ scope,
+ searchRequestor),
+ waitingPolicy,
+ progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
+
+ // add type names from working copies
+ if (copies != null) {
+ for (int i = 0; i < copiesLength; i++) {
+ IRubyScript workingCopy = copies[i];
+ if (!scope.encloses(workingCopy)) continue;
+ final String path = workingCopy.getPath().toString();
+ if (workingCopy.isConsistent()) {
+ // TODO Clean this up and figure out what we use instead of package names...
+// IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
+// char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
+ char[] packageDeclaration = CharOperation.NO_CHAR;
+ IType[] allTypes = workingCopy.getAllTypes();
+ for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
+ IType type = allTypes[j];
+ IRubyElement parent = type.getParent();
+ char[][] enclosingTypeNames;
+ if (parent instanceof IType) {
+ char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName("::").toCharArray();
+ enclosingTypeNames = CharOperation.splitOn("::", parentQualifiedName);
+ } else {
+ enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+ }
+ char[] simpleName = type.getElementName().toCharArray();
+ int kind;
+ if (type.isClass()) {
+ kind = CLASS_DECL;
+ } else /*if (type.isModule())*/ {
+ kind = MODULE_DECL;
+ }
+ if (match(typeSuffix, packageName, typeName, matchRule, kind, packageDeclaration, simpleName)) {
+ nameRequestor.acceptType(type.isModule(), packageDeclaration, simpleName, enclosingTypeNames, path);
+ }
+ }
+ } else {
+ // TODO Parse and traverse AST, report all type declarations...
+ }
+ }
+ }
+ } finally {
+ if (progressMonitor != null) {
+ progressMonitor.done();
+ }
+ }
+ }
+
+ boolean match(char patternTypeSuffix, int modifiers) {
+ switch(patternTypeSuffix) {
+ case IIndexConstants.CLASS_SUFFIX :
+ return (modifiers & (Flags.AccModule)) == 0;
+ case IIndexConstants.CLASS_AND_MODULE_SUFFIX:
+ return true;
+ case IIndexConstants.MODULE_SUFFIX :
+ return (modifiers & Flags.AccModule) != 0;
+ }
+ return true;
+ }
+
+ boolean match(char patternTypeSuffix, char[] patternPkg, char[] patternTypeName, int matchRule, int typeKind, char[] pkg, char[] typeName) {
+ switch(patternTypeSuffix) {
+ case IIndexConstants.CLASS_SUFFIX :
+ if (typeKind != CLASS_DECL) return false;
+ break;
+ case IIndexConstants.CLASS_AND_MODULE_SUFFIX:
+ if (typeKind != CLASS_DECL && typeKind != MODULE_DECL) return false;
+ break;
+ case IIndexConstants.MODULE_SUFFIX :
+ if (typeKind != MODULE_DECL) return false;
+ break;
+ case IIndexConstants.TYPE_SUFFIX : // nothing
+ }
+
+ boolean isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
+ if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isCaseSensitive))
+ return false;
+
+ if (patternTypeName != null) {
+ boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
+ int matchMode = matchRule & RubySearchPattern.MATCH_MODE_MASK;
+ if (!isCaseSensitive && !isCamelCase) {
+ patternTypeName = CharOperation.toLowerCase(patternTypeName);
+ }
+ boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0];
+ if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName)) {
+ return true;
+ }
+ switch(matchMode) {
+ case SearchPattern.R_EXACT_MATCH :
+ if (!isCamelCase) {
+ return matchFirstChar && CharOperation.equals(patternTypeName, typeName, isCaseSensitive);
+ }
+ // fall through next case to match as prefix if camel case failed
+ case SearchPattern.R_PREFIX_MATCH :
+ return matchFirstChar && CharOperation.prefixEquals(patternTypeName, typeName, isCaseSensitive);
+ case SearchPattern.R_PATTERN_MATCH :
+ return CharOperation.match(patternTypeName, typeName, isCaseSensitive);
+ case SearchPattern.R_REGEXP_MATCH :
+ // TODO (frederic) implement regular expression match
+ break;
+ }
+ }
+ return true;
+
+ }
+
+ /**
+ * @param matchRule
+ */
+ public static String getMatchRuleString(final int matchRule) {
+ if (matchRule == 0) {
+ return "R_EXACT_MATCH"; //$NON-NLS-1$
+ }
+ StringBuffer buffer = new StringBuffer();
+ for (int i=1; i<=8; i++) {
+ int bit = matchRule & (1<<(i-1));
+ if (bit != 0 && buffer.length()>0) buffer.append(" | "); //$NON-NLS-1$
+ switch (bit) {
+ case SearchPattern.R_PREFIX_MATCH:
+ buffer.append("R_PREFIX_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_CASE_SENSITIVE:
+ buffer.append("R_CASE_SENSITIVE"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_EQUIVALENT_MATCH:
+ buffer.append("R_EQUIVALENT_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_ERASURE_MATCH:
+ buffer.append("R_ERASURE_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_FULL_MATCH:
+ buffer.append("R_FULL_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_PATTERN_MATCH:
+ buffer.append("R_PATTERN_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_REGEXP_MATCH:
+ buffer.append("R_REGEXP_MATCH"); //$NON-NLS-1$
+ break;
+ case SearchPattern.R_CAMELCASE_MATCH:
+ buffer.append("R_CAMELCASE_MATCH"); //$NON-NLS-1$
+ break;
+ }
+ }
+ return buffer.toString();
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/RubySearchScope.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/RubySearchScope.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/RubySearchScope.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -442,4 +442,65 @@
return getPath(element.getParent(), relativeToRoot);
}
}
+
+ /* (non-Javadoc)
+ * @see IRubySearchScope#encloses(IRubyElement)
+ */
+ public boolean encloses(IRubyElement element) {
+ if (this.elements != null) {
+ for (int i = 0, length = this.elements.size(); i < length; i++) {
+ IRubyElement scopeElement = (IRubyElement)this.elements.get(i);
+ IRubyElement searchedElement = element;
+ while (searchedElement != null) {
+ if (searchedElement.equals(scopeElement))
+ return true;
+ searchedElement = searchedElement.getParent();
+ }
+ }
+ return false;
+ }
+ ISourceFolderRoot root = (ISourceFolderRoot) element.getAncestor(IRubyElement.SOURCE_FOLDER_ROOT);
+ if (root != null && root.isExternal()) {
+ // external
+ IPath rootPath = root.getPath();
+ String rootPathToString = rootPath.getDevice() == null ? rootPath.toString() : rootPath.toOSString();
+ IPath relativePath = getPath(element, true/*relative path*/);
+ return indexOf(rootPathToString, relativePath.toString()) >= 0;
+ }
+ // resource in workspace
+ String fullResourcePathString = getPath(element, false/*full path*/).toString();
+ return indexOf(fullResourcePathString) >= 0;
+ }
+
+ /**
+ * Returns paths list index of given path or -1 if not found.
+ * @param containerPath the path of the container, e.g.
+ * 1. /P/src
+ * 2. /P
+ * 3. /P/lib.jar
+ * 4. /home/mylib.jar
+ * 5. c:\temp\mylib.jar
+ * @param relativePath the forward slash path relatively to the container, e.g.
+ * 1. x/y/Z.class
+ * 2. x/y
+ * 3. X.java
+ * 4. (empty)
+ */
+ private int indexOf(String containerPath, String relativePath) {
+ // use the hash to get faster comparison
+ int length = this.containerPaths.length,
+ index = (containerPath.hashCode()& 0x7FFFFFFF) % length;
+ String currentContainerPath;
+ while ((currentContainerPath = this.containerPaths[index]) != null) {
+ if (currentContainerPath.equals(containerPath)) {
+ String currentRelativePath = this.relativePaths[index];
+ if (encloses(currentRelativePath, relativePath, index))
+ return index;
+ }
+ if (++index == length) {
+ index = 0;
+ }
+ }
+ return -1;
+ }
}
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java 2007-05-01 14:53:45 UTC (rev 2406)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/search/indexing/SourceIndexerRequestor.java 2007-05-01 14:54:54 UTC (rev 2407)
@@ -78,7 +78,7 @@
if (type.superclass != null) {
superclass = type.superclass.toCharArray();
}
- indexer.addClassDeclaration(type.isModule ? Flags.AccModule : 0, type.name.toCharArray(), packName, null, superclass, mod, type.secondary);
+ indexer.addClassDeclaration(type.isModule ? Flags.AccModule : 0, packName, type.name.toCharArray(), null, superclass, mod, type.secondary);
}
public void exitConstructor(int endOffset) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-05-01 14:53:46
|
Revision: 2406
http://svn.sourceforge.net/rubyeclipse/?rev=2406&view=rev
Author: cawilliams
Date: 2007-05-01 07:53:45 -0700 (Tue, 01 May 2007)
Log Message:
-----------
change our existing OpenTypeAction to use the new TypeSelectionDialog2 which is backed by the SearchEngine. Now we can do much quicker search of type names, keep track of thse user picked, do external library types, etc.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPlugin.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/RubyElementLabels.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/OpenTypeAction.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/view_menu.gif
trunk/org.rubypeople.rdt.ui/icons/full/elcl16/view_menu.gif
trunk/org.rubypeople.rdt.ui/icons/full/obj16/type_separator.gif
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/ExternalFileTypeInfo.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/History.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/IFileTypeInfo.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/OpenTypeHistory.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/SearchUtils.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeFilter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfoFactory.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfoFilter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/UnresolvableTypeInfo.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/OpenTypeSelectionDialog2.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TextFieldNavigationHandler.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeInfoViewer.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionComponent.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dialogs/TypeSelectionDialog2.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyBreakIterator.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyWordIterator.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/SequenceCharacterIterator.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/TypeInfoLabelProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/ITypeInfoFilterExtension.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/ITypeInfoImageProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/ITypeInfoRequestor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/ITypeSelectionComponent.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/TypeSelectionExtension.java
Modified: trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
===================================================================
--- trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-05-01 14:52:12 UTC (rev 2405)
+++ trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-05-01 14:53:45 UTC (rev 2406)
@@ -58,6 +58,7 @@
org.eclipse.compare,
org.eclipse.core.filesystem,
org.eclipse.core.expressions,
- org.eclipse.ltk.core.refactoring
+ org.eclipse.ltk.core.refactoring,
+ com.ibm.icu
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Added: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/view_menu.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/view_menu.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/view_menu.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/view_menu.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/obj16/type_separator.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/obj16/type_separator.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,16 @@
+package org.rubypeople.rdt.internal.corext.util;
+
+import org.eclipse.osgi.util.NLS;
+
+public class CorextMessages extends NLS {
+
+ private static final String BUNDLE_NAME = CorextMessages.class.getName();
+
+ public static String History_error_serialize;
+ public static String History_error_read;
+ public static String TypeInfoHistory_consistency_check;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, CorextMessages.class);
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.properties (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/CorextMessages.properties 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,3 @@
+History_error_serialize= Problems serializing information to XML ''{0}''
+TypeInfoHistory_consistency_check=Checking consistency of type history...
+History_error_read=Problems reading information from XML ''{0}''
\ No newline at end of file
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/ExternalFileTypeInfo.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/ExternalFileTypeInfo.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/ExternalFileTypeInfo.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.util;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileInfo;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyModel;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.ISourceFolder;
+import org.rubypeople.rdt.core.ISourceFolderRoot;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+
+/**
+ * A <tt>ExternalFileTypeInfo</tt> represents a type in a Jar file.
+ */
+public class ExternalFileTypeInfo extends TypeInfo {
+
+ private final String fPath;
+
+ public ExternalFileTypeInfo(String pkg, String name, char[][] enclosingTypes, boolean isModule, String path) {
+ super(pkg, name, enclosingTypes, isModule);
+ fPath = path;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!ExternalFileTypeInfo.class.equals(obj.getClass()))
+ return false;
+ ExternalFileTypeInfo other= (ExternalFileTypeInfo)obj;
+ return doEquals(other) && fPath.equals(other.fPath);
+ }
+
+ public int getElementType() {
+ return TypeInfo.JAR_FILE_ENTRY_TYPE_INFO;
+ }
+
+ protected IRubyElement getContainer(IRubySearchScope scope) throws RubyModelException {
+ IRubyModel jmodel= RubyCore.create(ResourcesPlugin.getWorkspace().getRoot());
+ IPath[] enclosedPaths= scope.enclosingProjectsAndJars();
+
+ // TODO Remove the last segment of the path, it's the filename. Also remove "package names" from path
+ String rootPath = new File(fPath).getParent();
+ for (int i= 0; i < enclosedPaths.length; i++) {
+ IPath curr= enclosedPaths[i];
+ if (curr.segmentCount() == 1) {
+ IRubyProject jproject= jmodel.getRubyProject(curr.segment(0));
+ ISourceFolderRoot root= jproject.getSourceFolderRoot(rootPath);
+ if (root.exists()) {
+ return findElementInRoot(root);
+ }
+ }
+ }
+ List paths= Arrays.asList(enclosedPaths);
+ IRubyProject[] projects= jmodel.getRubyProjects();
+ for (int i= 0; i < projects.length; i++) {
+ IRubyProject jproject= projects[i];
+ if (!paths.contains(jproject.getPath())) {
+ ISourceFolderRoot root= jproject.getSourceFolderRoot(fPath);
+ if (root.exists()) {
+ return findElementInRoot(root);
+ }
+ }
+ }
+ return null;
+ }
+
+ private IRubyElement findElementInRoot(ISourceFolderRoot root) {
+ IRubyElement res;
+ ISourceFolder frag= root.getSourceFolder(getPackageName());
+ String extension= getExtension();
+ String fullName= getFileName() + '.' + extension;
+
+ if (RubyCore.isRubyLikeFileName(fullName)) {
+ res= frag.getRubyScript(fullName);
+ } else {
+ return null;
+ }
+ if (res.exists()) {
+ return res;
+ }
+ return null;
+ }
+
+ private String getFileName() {
+ String name = new File(fPath).getName();
+ return name.substring(0, name.lastIndexOf('.'));
+ }
+
+ private String getExtension() {
+ String name = new File(fPath).getName();
+ return name.substring(name.lastIndexOf('.') + 1);
+ }
+
+ public IPath getPackageFragmentRootPath() {
+ return new Path(fPath);
+ }
+
+ public String getPackageFragmentRootName() {
+ // we can't remove the '/' since the jar can be external.
+ return fPath;
+ }
+
+ public String getPath() {
+ StringBuffer result= new StringBuffer(fPath);
+// result.append(IRubySearchScope.JAR_FILE_ENTRY_SEPARATOR);
+ getElementPath(result);
+ return result.toString();
+ }
+
+ public long getContainerTimestamp() {
+ // First try internal Jar
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IPath path= new Path(fPath);
+ IResource resource= root.findMember(path);
+ IFileInfo info= null;
+ IRubyElement element= null;
+ if (resource != null && resource.exists()) {
+ URI location= resource.getLocationURI();
+ if (location != null) {
+ try {
+ info= EFS.getStore(location).fetchInfo();
+ if (info.exists()) {
+ element= RubyCore.create(resource);
+ // The exist test for external jars is expensive due to
+ // JDT/Core. So do the test here since we know that the
+ // Ruby element points to an internal Jar.
+ if (element != null && !element.exists())
+ element= null;
+ }
+ } catch (CoreException e) {
+ // Fall through
+ }
+ }
+ } else {
+ info= EFS.getLocalFileSystem().getStore(Path.fromOSString(fPath)).fetchInfo();
+ if (info.exists()) {
+ element= getPackageFragementRootForExternalJar();
+ }
+ }
+ if (info != null && info.exists() && element != null) {
+ return info.getLastModified();
+ }
+ return IResource.NULL_STAMP;
+ }
+
+ public boolean isContainerDirty() {
+ return false;
+ }
+
+ private void getElementPath(StringBuffer result) {
+ String pack= getPackageName();
+ if (pack != null && pack.length() > 0) {
+ result.append(pack.replace(TypeInfo.PACKAGE_PART_SEPARATOR, TypeInfo.SEPARATOR));
+ result.append(TypeInfo.SEPARATOR);
+ }
+ result.append(getFileName());
+ result.append('.');
+ result.append(getExtension());
+ }
+
+ private ISourceFolderRoot getPackageFragementRootForExternalJar() {
+ try {
+ IRubyModel jmodel= RubyCore.create(ResourcesPlugin.getWorkspace().getRoot());
+ IRubyProject[] projects= jmodel.getRubyProjects();
+ for (int i= 0; i < projects.length; i++) {
+ IRubyProject project= projects[i];
+ ISourceFolderRoot root= project.getSourceFolderRoot(fPath);
+ // Cheaper check than calling root.exists().
+ if (project.isOnLoadpath(root))
+ return root;
+ }
+ } catch (RubyModelException e) {
+ // Fall through
+ }
+ return null;
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/History.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/History.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/History.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.RubyUIException;
+import org.rubypeople.rdt.internal.ui.RubyUIStatus;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * History stores a list of key, object pairs. The list is bounded at size
+ * MAX_HISTORY_SIZE. If the list exceeds this size the eldest element is removed
+ * from the list. An element can be added/renewed with a call to <code>accessed(Object)</code>.
+ *
+ * The history can be stored to/loaded from an xml file.
+ */
+public abstract class History {
+
+ private static final String DEFAULT_ROOT_NODE_NAME= "histroyRootNode"; //$NON-NLS-1$
+ private static final String DEFAULT_INFO_NODE_NAME= "infoNode"; //$NON-NLS-1$
+ private static final int MAX_HISTORY_SIZE= 60;
+
+ private static RubyUIException createException(Throwable t, String message) {
+ return new RubyUIException(RubyUIStatus.createError(IStatus.ERROR, message, t));
+ }
+
+ private final Map fHistory;
+ private final Hashtable fPositions;
+ private final String fFileName;
+ private final String fRootNodeName;
+ private final String fInfoNodeName;
+
+ public History(String fileName, String rootNodeName, String infoNodeName) {
+ fHistory= new LinkedHashMap(80, 0.75f, true) {
+ private static final long serialVersionUID= 1L;
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > MAX_HISTORY_SIZE;
+ }
+ };
+ fFileName= fileName;
+ fRootNodeName= rootNodeName;
+ fInfoNodeName= infoNodeName;
+ fPositions= new Hashtable(MAX_HISTORY_SIZE);
+ }
+
+ public History(String fileName) {
+ this(fileName, DEFAULT_ROOT_NODE_NAME, DEFAULT_INFO_NODE_NAME);
+ }
+
+ public synchronized void accessed(Object object) {
+ fHistory.put(getKey(object), object);
+ rebuildPositions();
+ }
+
+ public synchronized boolean contains(Object object) {
+ return fHistory.containsKey(getKey(object));
+ }
+
+ public synchronized boolean containsKey(Object key) {
+ return fHistory.containsKey(key);
+ }
+
+ public synchronized boolean isEmpty() {
+ return fHistory.isEmpty();
+ }
+
+ public synchronized Object remove(Object object) {
+ Object removed= fHistory.remove(getKey(object));
+ rebuildPositions();
+ return removed;
+ }
+
+ public synchronized Object removeKey(Object key) {
+ Object removed= fHistory.remove(key);
+ rebuildPositions();
+ return removed;
+ }
+
+ /**
+ * Normalized position in history of object denoted by key.
+ * The position is a value between zero and one where zero
+ * means not contained in history and one means newest element
+ * in history. The lower the value the older the element.
+ *
+ * @param key The key of the object to inspect
+ * @return value in [0.0, 1.0] the lower the older the element
+ */
+ public synchronized float getNormalizedPosition(Object key) {
+ if (!containsKey(key))
+ return 0.0f;
+
+ int pos= ((Integer)fPositions.get(key)).intValue() + 1;
+
+ //containsKey(key) implies fHistory.size()>0
+ return (float)pos / (float)fHistory.size();
+ }
+
+ /**
+ * Absolute position of object denoted by key in the
+ * history or -1 if !containsKey(key). The higher the
+ * newer.
+ *
+ * @param key The key of the object to inspect
+ * @return value between 0 and MAX_HISTORY_SIZE - 1, or -1
+ */
+ public synchronized int getPosition(Object key) {
+ if (!containsKey(key))
+ return -1;
+
+ return ((Integer)fPositions.get(key)).intValue();
+ }
+
+ public synchronized void load() {
+ IPath stateLocation= RubyPlugin.getDefault().getStateLocation().append(fFileName);
+ File file= new File(stateLocation.toOSString());
+ if (file.exists()) {
+ InputStreamReader reader= null;
+ try {
+ reader = new InputStreamReader(new FileInputStream(file), "utf-8");//$NON-NLS-1$
+ load(new InputSource(reader));
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ } catch (CoreException e) {
+ RubyPlugin.log(e);
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ }
+ }
+ }
+ }
+
+ public synchronized void save() {
+ IPath stateLocation= RubyPlugin.getDefault().getStateLocation().append(fFileName);
+ File file= new File(stateLocation.toOSString());
+ OutputStream out= null;
+ try {
+ out= new FileOutputStream(file);
+ save(out);
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ } catch (CoreException e) {
+ RubyPlugin.log(e);
+ } catch (TransformerFactoryConfigurationError e) {
+ // The XML library can be misconficgured (e.g. via
+ // -Djava.endorsed.dirs=C:\notExisting\xerces-2_7_1)
+ RubyPlugin.log(e);
+ } finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ }
+ }
+ }
+
+ protected Set getKeys() {
+ return fHistory.keySet();
+ }
+
+ protected Collection getValues() {
+ return fHistory.values();
+ }
+
+ /**
+ * Store <code>Object</code> in <code>Element</code>
+ *
+ * @param object The object to store
+ * @param element The Element to store to
+ */
+ protected abstract void setAttributes(Object object, Element element);
+
+ /**
+ * Return a new instance of an Object given <code>element</code>
+ *
+ * @param element The element containing required information to create the Object
+ */
+ protected abstract Object createFromElement(Element element);
+
+ /**
+ * Get key for object
+ *
+ * @param object The object to calculate a key for, not null
+ * @return The key for object, not null
+ */
+ protected abstract Object getKey(Object object);
+
+ private void rebuildPositions() {
+ fPositions.clear();
+ Collection values= fHistory.values();
+ int pos=0;
+ for (Iterator iter= values.iterator(); iter.hasNext();) {
+ Object element= iter.next();
+ fPositions.put(getKey(element), new Integer(pos));
+ pos++;
+ }
+ }
+
+ private void load(InputSource inputSource) throws CoreException {
+ Element root;
+ try {
+ DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ root = parser.parse(inputSource).getDocumentElement();
+ } catch (SAXException e) {
+ throw createException(e, Messages.format(CorextMessages.History_error_read, fFileName));
+ } catch (ParserConfigurationException e) {
+ throw createException(e, Messages.format(CorextMessages.History_error_read, fFileName));
+ } catch (IOException e) {
+ throw createException(e, Messages.format(CorextMessages.History_error_read, fFileName));
+ }
+
+ if (root == null) return;
+ if (!root.getNodeName().equalsIgnoreCase(fRootNodeName)) {
+ return;
+ }
+ NodeList list= root.getChildNodes();
+ int length= list.getLength();
+ for (int i= 0; i < length; ++i) {
+ Node node= list.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element type= (Element) node;
+ if (type.getNodeName().equalsIgnoreCase(fInfoNodeName)) {
+ Object object= createFromElement(type);
+ fHistory.put(getKey(object), object);
+ }
+ }
+ }
+ rebuildPositions();
+ }
+
+ private void save(OutputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder= factory.newDocumentBuilder();
+ Document document= builder.newDocument();
+
+ Element rootElement = document.createElement(fRootNodeName);
+ document.appendChild(rootElement);
+
+ Iterator values= getValues().iterator();
+ while (values.hasNext()) {
+ Object object= values.next();
+ Element element= document.createElement(fInfoNodeName);
+ setAttributes(object, element);
+ rootElement.appendChild(element);
+ }
+
+ Transformer transformer=TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(stream);
+
+ transformer.transform(source, result);
+ } catch (TransformerException e) {
+ throw createException(e, Messages.format(CorextMessages.History_error_serialize, fFileName));
+ } catch (ParserConfigurationException e) {
+ throw createException(e, Messages.format(CorextMessages.History_error_serialize, fFileName));
+ }
+ }
+
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/IFileTypeInfo.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/IFileTypeInfo.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/IFileTypeInfo.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.util;
+
+import java.net.URI;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileInfo;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+
+/**
+ * A <tt>IFileTypeInfo</tt> represents a type in a class or java file.
+ */
+public class IFileTypeInfo extends TypeInfo {
+
+ private final String fProject;
+ private final String fFolder;
+ private final String fFile;
+ private final String fExtension;
+
+ public IFileTypeInfo(String pkg, String name, char[][] enclosingTypes, boolean isModule, String project, String sourceFolder, String file, String extension) {
+ super(pkg, name, enclosingTypes, isModule);
+ fProject= project;
+ fFolder= sourceFolder;
+ fFile= file;
+ fExtension= extension;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!IFileTypeInfo.class.equals(obj.getClass()))
+ return false;
+ IFileTypeInfo other= (IFileTypeInfo)obj;
+ return doEquals(other) && fProject.equals(other.fProject) && equals(fFolder, other.fFolder) &&
+ fFile.equals(other.fFile) && fExtension.equals(other.fExtension);
+ }
+
+ public int getElementType() {
+ return TypeInfo.IFILE_TYPE_INFO;
+ }
+
+ protected IRubyElement getContainer(IRubySearchScope scope) {
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IPath path= new Path(getPath());
+ IResource resource= root.findMember(path);
+ if (resource != null) {
+ IRubyElement elem= RubyCore.create(resource);
+ if (elem != null && elem.exists()) {
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ public IPath getPackageFragmentRootPath() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(TypeInfo.SEPARATOR);
+ buffer.append(fProject);
+ if (fFolder != null && fFolder.length() > 0) {
+ buffer.append(TypeInfo.SEPARATOR);
+ buffer.append(fFolder);
+ }
+ return new Path(buffer.toString());
+ }
+
+ public String getPackageFragmentRootName() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(fProject);
+ if (fFolder != null && fFolder.length() > 0) {
+ buffer.append(TypeInfo.SEPARATOR);
+ buffer.append(fFolder);
+ }
+ return buffer.toString();
+ }
+
+ public String getPath() {
+ StringBuffer result= new StringBuffer();
+ result.append(TypeInfo.SEPARATOR);
+ result.append(fProject);
+ result.append(TypeInfo.SEPARATOR);
+ if (fFolder != null && fFolder.length() > 0) {
+ result.append(fFolder);
+ result.append(TypeInfo.SEPARATOR);
+ }
+ if (fPackage != null && fPackage.length() > 0) {
+ result.append(fPackage.replace(TypeInfo.PACKAGE_PART_SEPARATOR, TypeInfo.SEPARATOR));
+ result.append(TypeInfo.SEPARATOR);
+ }
+ result.append(fFile);
+ result.append('.');
+ result.append(fExtension);
+ return result.toString();
+ }
+
+ public String getProject() {
+ return fProject;
+ }
+
+ public String getFolder() {
+ return fFolder;
+ }
+
+ public String getFileName() {
+ return fFile;
+ }
+
+ public String getExtension() {
+ return fExtension;
+ }
+
+ public long getContainerTimestamp() {
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IPath path= new Path(getPath());
+ IResource resource= root.findMember(path);
+ if (resource != null) {
+ URI location= resource.getLocationURI();
+ if (location != null) {
+ try {
+ IFileInfo info= EFS.getStore(location).fetchInfo();
+ if (info.exists()) {
+ // The element could be removed from the build path. So check
+ // if the Ruby element still exists.
+ IRubyElement element= RubyCore.create(resource);
+ if (element != null && element.exists())
+ return info.getLastModified();
+ }
+ } catch (CoreException e) {
+ // Fall through
+ }
+ }
+ }
+ return IResource.NULL_STAMP;
+ }
+
+ public boolean isContainerDirty() {
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IPath path= new Path(getPath());
+ IResource resource= root.findMember(path);
+ ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
+ ITextFileBuffer textFileBuffer= manager.getTextFileBuffer(resource.getFullPath());
+ if (textFileBuffer != null) {
+ return textFileBuffer.isDirty();
+ }
+ return false;
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/OpenTypeHistory.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/OpenTypeHistory.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/OpenTypeHistory.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+ package org.rubypeople.rdt.internal.corext.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.rubypeople.rdt.core.ElementChangedEvent;
+import org.rubypeople.rdt.core.IElementChangedListener;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyElementDelta;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.w3c.dom.Element;
+
+/**
+ * History for the open type dialog. Object and keys are both {@link TypeInfo}s.
+ */
+public class OpenTypeHistory extends History {
+
+ private static class TypeHistoryDeltaListener implements IElementChangedListener {
+ public void elementChanged(ElementChangedEvent event) {
+ if (processDelta(event.getDelta())) {
+ OpenTypeHistory.getInstance().markAsInconsistent();
+ }
+ }
+
+ /**
+ * Computes whether the history needs a consistency check or not.
+ *
+ * @param delta the Ruby element delta
+ *
+ * @return <code>true</code> if consistency must be checked
+ * <code>false</code> otherwise.
+ */
+ private boolean processDelta(IRubyElementDelta delta) {
+ IRubyElement elem= delta.getElement();
+
+ boolean isChanged= delta.getKind() == IRubyElementDelta.CHANGED;
+ boolean isRemoved= delta.getKind() == IRubyElementDelta.REMOVED;
+
+ switch (elem.getElementType()) {
+ case IRubyElement.RUBY_PROJECT:
+ if (isRemoved || (isChanged &&
+ (delta.getFlags() & IRubyElementDelta.F_CLOSED) != 0)) {
+ return true;
+ }
+ return processChildrenDelta(delta);
+ case IRubyElement.SOURCE_FOLDER_ROOT:
+ if (isRemoved || (isChanged && (
+ (delta.getFlags() & IRubyElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0 ||
+ (delta.getFlags() & IRubyElementDelta.F_REMOVED_FROM_CLASSPATH) != 0))) {
+ return true;
+ }
+ return processChildrenDelta(delta);
+ case IRubyElement.TYPE:
+ if (isChanged && (delta.getFlags() & IRubyElementDelta.F_MODIFIERS) != 0) {
+ return true;
+ }
+ // type children can be inner classes: fall through
+ case IRubyElement.RUBY_MODEL:
+ case IRubyElement.SOURCE_FOLDER:
+ if (isRemoved) {
+ return true;
+ }
+ return processChildrenDelta(delta);
+ case IRubyElement.SCRIPT:
+ // Not the primary compilation unit. Ignore it
+ if (!RubyModelUtil.isPrimary((IRubyScript) elem)) {
+ return false;
+ }
+
+ if (isRemoved || (isChanged && isUnknownStructuralChange(delta.getFlags()))) {
+ return true;
+ }
+ return processChildrenDelta(delta);
+ default:
+ // fields, methods, imports ect
+ return false;
+ }
+ }
+
+ private boolean isUnknownStructuralChange(int flags) {
+ if ((flags & IRubyElementDelta.F_CONTENT) == 0)
+ return false;
+ return (flags & IRubyElementDelta.F_FINE_GRAINED) == 0;
+ }
+
+ /*
+ private boolean isPossibleStructuralChange(int flags) {
+ return (flags & (IRubyElementDelta.F_CONTENT | IRubyElementDelta.F_FINE_GRAINED)) == IRubyElementDelta.F_CONTENT;
+ }
+ */
+
+ private boolean processChildrenDelta(IRubyElementDelta delta) {
+ IRubyElementDelta[] children= delta.getAffectedChildren();
+ for (int i= 0; i < children.length; i++) {
+ if (processDelta(children[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private static class UpdateJob extends Job {
+ public static final String FAMILY= UpdateJob.class.getName();
+ public UpdateJob() {
+ super(CorextMessages.TypeInfoHistory_consistency_check);
+ }
+ protected IStatus run(IProgressMonitor monitor) {
+ OpenTypeHistory history= OpenTypeHistory.getInstance();
+ history.internalCheckConsistency(monitor);
+ return new Status(IStatus.OK, RubyPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+ }
+ public boolean belongsTo(Object family) {
+ return FAMILY.equals(family);
+ }
+ }
+
+ // Needs to be volatile since accesses aren't synchronized.
+ private volatile boolean fNeedsConsistencyCheck;
+ // Map of cached time stamps
+ private Map fTimestampMapping;
+
+ private final IElementChangedListener fDeltaListener;
+ private final UpdateJob fUpdateJob;
+ private final TypeInfoFactory fTypeInfoFactory;
+
+ private static final String FILENAME= "OpenTypeHistory.xml"; //$NON-NLS-1$
+ private static final String NODE_ROOT= "typeInfoHistroy"; //$NON-NLS-1$
+ private static final String NODE_TYPE_INFO= "typeInfo"; //$NON-NLS-1$
+ private static final String NODE_NAME= "name"; //$NON-NLS-1$
+ private static final String NODE_PACKAGE= "package"; //$NON-NLS-1$
+ private static final String NODE_ENCLOSING_NAMES= "enclosingTypes"; //$NON-NLS-1$
+ private static final String NODE_PATH= "path"; //$NON-NLS-1$
+ private static final String NODE_MODIFIERS= "modifiers"; //$NON-NLS-1$
+ private static final String NODE_TIMESTAMP= "timestamp"; //$NON-NLS-1$
+ private static final char[][] EMPTY_ENCLOSING_NAMES= new char[0][0];
+
+ private static OpenTypeHistory fgInstance;
+
+ public static synchronized OpenTypeHistory getInstance() {
+ if (fgInstance == null)
+ fgInstance= new OpenTypeHistory();
+ return fgInstance;
+ }
+
+ public static synchronized void shutdown() {
+ if (fgInstance == null)
+ return;
+ fgInstance.doShutdown();
+ }
+
+ private OpenTypeHistory() {
+ super(FILENAME, NODE_ROOT, NODE_TYPE_INFO);
+ fTypeInfoFactory= new TypeInfoFactory();
+ fTimestampMapping= new HashMap();
+ fNeedsConsistencyCheck= true;
+ load();
+ fDeltaListener= new TypeHistoryDeltaListener();
+ RubyCore.addElementChangedListener(fDeltaListener);
+ fUpdateJob= new UpdateJob();
+ // It is not necessary anymore that the update job has a rule since
+ // markAsInconsistent isn't synchronized anymore. See bugs
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=128399 and
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=135278
+ // for details.
+ fUpdateJob.setPriority(Job.SHORT);
+ }
+
+ public void markAsInconsistent() {
+ fNeedsConsistencyCheck= true;
+ // cancel the old job. If no job is running this is a NOOP.
+ fUpdateJob.cancel();
+ fUpdateJob.schedule();
+ }
+
+ public boolean needConsistencyCheck() {
+ return fNeedsConsistencyCheck;
+ }
+
+ public void checkConsistency(IProgressMonitor monitor) throws OperationCanceledException {
+ if (!fNeedsConsistencyCheck)
+ return;
+ if (fUpdateJob.getState() == Job.RUNNING) {
+ try {
+ Platform.getJobManager().join(UpdateJob.FAMILY, monitor);
+ } catch (OperationCanceledException e) {
+ // Ignore and do the consistency check without
+ // waiting for the update job.
+ } catch (InterruptedException e) {
+ // Ignore and do the consistency check without
+ // waiting for the update job.
+ }
+ }
+ if (!fNeedsConsistencyCheck)
+ return;
+ internalCheckConsistency(monitor);
+ }
+
+ public synchronized boolean contains(TypeInfo type) {
+ return super.contains(type);
+ }
+
+ public synchronized void accessed(TypeInfo info) {
+ // Fetching the timestamp might not be cheap (remote file system
+ // external Jars. So check if we alreay have one.
+ if (!fTimestampMapping.containsKey(info)) {
+ fTimestampMapping.put(info, new Long(info.getContainerTimestamp()));
+ }
+ super.accessed(info);
+ }
+
+ public synchronized TypeInfo remove(TypeInfo info) {
+ fTimestampMapping.remove(info);
+ return (TypeInfo)super.remove(info);
+ }
+
+ public synchronized TypeInfo[] getTypeInfos() {
+ Collection values= getValues();
+ int size= values.size();
+ TypeInfo[] result= new TypeInfo[size];
+ int i= size - 1;
+ for (Iterator iter= values.iterator(); iter.hasNext();) {
+ result[i]= (TypeInfo)iter.next();
+ i--;
+ }
+ return result;
+ }
+
+ public synchronized TypeInfo[] getFilteredTypeInfos(TypeInfoFilter filter) {
+ Collection values= getValues();
+ List result= new ArrayList();
+ for (Iterator iter= values.iterator(); iter.hasNext();) {
+ TypeInfo type= (TypeInfo)iter.next();
+ if ((filter == null || filter.matchesHistoryElement(type)) && !TypeFilter.isFiltered(type.getFullyQualifiedName()))
+ result.add(type);
+ }
+ Collections.reverse(result);
+ return (TypeInfo[])result.toArray(new TypeInfo[result.size()]);
+
+ }
+
+ protected Object getKey(Object object) {
+ return object;
+ }
+
+ private synchronized void internalCheckConsistency(IProgressMonitor monitor) throws OperationCanceledException {
+ // Setting fNeedsConsistencyCheck is necessary here since
+ // markAsInconsistent isn't synchronized.
+ fNeedsConsistencyCheck= true;
+ IRubySearchScope scope= SearchEngine.createWorkspaceScope();
+ List typesToCheck= new ArrayList(getKeys());
+ monitor.beginTask(CorextMessages.TypeInfoHistory_consistency_check, typesToCheck.size());
+ monitor.setTaskName(CorextMessages.TypeInfoHistory_consistency_check);
+ for (Iterator iter= typesToCheck.iterator(); iter.hasNext();) {
+ TypeInfo type= (TypeInfo)iter.next();
+ long currentTimestamp= type.getContainerTimestamp();
+ Long lastTested= (Long)fTimestampMapping.get(type);
+ if (lastTested != null && currentTimestamp != IResource.NULL_STAMP && currentTimestamp == lastTested.longValue() && !type.isContainerDirty())
+ continue;
+ try {
+ IType jType= type.resolveType(scope);
+ if (jType == null || !jType.exists()) {
+ remove(type);
+ } else {
+ // copy over the modifiers since they may have changed
+ type.setIsModule(jType.isModule());
+ fTimestampMapping.put(type, new Long(currentTimestamp));
+ }
+ } catch (RubyModelException e) {
+ remove(type);
+ }
+ if (monitor.isCanceled())
+ throw new OperationCanceledException();
+ monitor.worked(1);
+ }
+ monitor.done();
+ fNeedsConsistencyCheck= false;
+ }
+
+ private void doShutdown() {
+ RubyCore.removeElementChangedListener(fDeltaListener);
+ save();
+ }
+
+ protected Object createFromElement(Element type) {
+ String name= type.getAttribute(NODE_NAME);
+ String pack= type.getAttribute(NODE_PACKAGE);
+ char[][] enclosingNames= getEnclosingNames(type);
+ String path= type.getAttribute(NODE_PATH);
+ boolean isModule = false;
+ try {
+ isModule= Boolean.parseBoolean(type.getAttribute(NODE_MODIFIERS));
+ } catch (NumberFormatException e) {
+ // take zero
+ }
+ TypeInfo info= fTypeInfoFactory.create(
+ pack.toCharArray(), name.toCharArray(), enclosingNames, isModule, path);
+ long timestamp= IResource.NULL_STAMP;
+ String timestampValue= type.getAttribute(NODE_TIMESTAMP);
+ if (timestampValue != null && timestampValue.length() > 0) {
+ try {
+ timestamp= Long.parseLong(timestampValue);
+ } catch (NumberFormatException e) {
+ // take null stamp
+ }
+ }
+ if (timestamp != IResource.NULL_STAMP) {
+ fTimestampMapping.put(info, new Long(timestamp));
+ }
+ return info;
+ }
+
+ protected void setAttributes(Object object, Element typeElement) {
+ TypeInfo type= (TypeInfo)object;
+ typeElement.setAttribute(NODE_NAME, type.getTypeName());
+ typeElement.setAttribute(NODE_PACKAGE, type.getPackageName());
+ typeElement.setAttribute(NODE_ENCLOSING_NAMES, type.getEnclosingName());
+ typeElement.setAttribute(NODE_PATH, type.getPath());
+ typeElement.setAttribute(NODE_MODIFIERS, Boolean.toString(type.isModule()));
+ Long timestamp= (Long) fTimestampMapping.get(type);
+ if (timestamp == null) {
+ typeElement.setAttribute(NODE_TIMESTAMP, Long.toString(IResource.NULL_STAMP));
+ } else {
+ typeElement.setAttribute(NODE_TIMESTAMP, timestamp.toString());
+ }
+ }
+
+ private char[][] getEnclosingNames(Element type) {
+ String enclosingNames= type.getAttribute(NODE_ENCLOSING_NAMES);
+ if (enclosingNames.length() == 0)
+ return EMPTY_ENCLOSING_NAMES;
+ StringTokenizer tokenizer= new StringTokenizer(enclosingNames, "."); //$NON-NLS-1$
+ List names= new ArrayList();
+ while(tokenizer.hasMoreTokens()) {
+ String name= tokenizer.nextToken();
+ names.add(name.toCharArray());
+ }
+ return (char[][])names.toArray(new char[names.size()][]);
+ }
+}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java 2007-05-01 14:52:12 UTC (rev 2405)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -7,6 +7,7 @@
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.ISourceFolderRoot;
+import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.util.CharOperation;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
@@ -82,4 +83,60 @@
}
return false;
}
+
+ /**
+ * Concatenates two names. Uses a '/' for separation.
+ * Both strings can be empty or <code>null</code>.
+ */
+ public static String concatenateName(char[] name1, char[] name2) {
+ StringBuffer buf= new StringBuffer();
+ if (name1 != null && name1.length > 0) {
+ buf.append(name1);
+ }
+ if (name2 != null && name2.length > 0) {
+ if (buf.length() > 0) {
+ buf.append("/");
+ }
+ buf.append(name2);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Returns the fully qualified name of the given type using '::' as separators.
+ * This is a replace for IType.getFullyQualifiedTypeName
+ * which uses '$' as separators. As '$' is also a valid character in an id
+ * this is ambiguous.
+ */
+ public static String getFullyQualifiedName(IType type) {
+ return type.getFullyQualifiedName();
+ }
+
+ /**
+ * Finds a type in a ruby script. Typical usage is to find the corresponding
+ * type in a working copy.
+ * @param script the compilation unit to search in
+ * @param typeQualifiedName the type qualified name (type name with enclosing type names (separated by dots))
+ * @return the type found, or null if not existing
+ */
+ public static IType findTypeInRubyScript(IRubyScript script, String typeQualifiedName) throws RubyModelException {
+ IType[] types= script.getAllTypes();
+ for (int i= 0; i < types.length; i++) {
+ String currName= getTypeQualifiedName(types[i]);
+ if (typeQualifiedName.equals(currName)) {
+ return types[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the qualified type name of the given type using '.' as separators.
+ * This is a replace for IType.getTypeQualifiedName()
+ * which uses '$' as separators. As '$' is also a valid character in an id
+ * this is ambiguous. JavaCore PR: 1GCFUNT
+ */
+ public static String getTypeQualifiedName(IType type) {
+ return type.getTypeQualifiedName("::");
+ }
}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/SearchUtils.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/SearchUtils.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/SearchUtils.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,19 @@
+package org.rubypeople.rdt.internal.corext.util;
+
+import org.rubypeople.rdt.core.search.SearchPattern;
+
+public class SearchUtils {
+
+ /**
+ * Returns whether the given pattern is a camel case pattern or not.
+ *
+ * @param pattern the pattern to inspect
+ * @return whether it is a camel case pattern or not
+ */
+ public static boolean isCamelCasePattern(String pattern) {
+ return SearchPattern.validateMatchRule(
+ pattern,
+ SearchPattern.R_CAMELCASE_MATCH) == SearchPattern.R_CAMELCASE_MATCH;
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java 2007-05-01 14:52:12 UTC (rev 2405)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/Strings.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -101,4 +101,47 @@
return true;
}
+ public static boolean equals(String s, char[] c) {
+ if (s.length() != c.length)
+ return false;
+
+ for (int i = c.length; --i >= 0;)
+ if (s.charAt(i) != c[i])
+ return false;
+ return true;
+ }
+
+ public static boolean startsWithIgnoreCase(String text, String prefix) {
+ int textLength= text.length();
+ int prefixLength= prefix.length();
+ if (textLength < prefixLength)
+ return false;
+ for (int i= prefixLength - 1; i >= 0; i--) {
+ if (Character.toLowerCase(prefix.charAt(i)) != Character.toLowerCase(text.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * tests if a char is lower case. Fix for 26529
+ */
+ public static boolean isLowerCase(char ch) {
+ return Character.toLowerCase(ch) == ch;
+ }
+
+ public static String removeMnemonicIndicator(String string) {
+ int length= string.length();
+ StringBuffer result= new StringBuffer(length);
+ char lastChar= ' '; // everything except & is OK as an initializer
+ for(int i= 0; i < length; i++) {
+ char ch= string.charAt(i);
+ if (ch != '&' || lastChar == '&') {
+ result.append(ch);
+ }
+ lastChar= ch;
+ }
+ return result.toString();
+ }
+
}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeFilter.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeFilter.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeFilter.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.util;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.util.StringMatcher;
+import org.rubypeople.rdt.ui.PreferenceConstants;
+
+/**
+ *
+ */
+public class TypeFilter implements IPropertyChangeListener {
+
+ public static TypeFilter getDefault() {
+ return RubyPlugin.getDefault().getTypeFilter();
+ }
+
+ public static boolean isFiltered(String fullTypeName) {
+ return getDefault().filter(fullTypeName);
+ }
+
+ public static boolean isFiltered(char[] fullTypeName) {
+ return getDefault().filter(new String(fullTypeName));
+ }
+
+ public static boolean isFiltered(char[] packageName, char[] typeName) {
+ return getDefault().filter(RubyModelUtil.concatenateName(packageName, typeName));
+ }
+
+ public static boolean isFiltered(IType type) {
+ TypeFilter typeFilter = getDefault();
+ if (typeFilter.hasFilters()) {
+ return typeFilter.filter(RubyModelUtil.getFullyQualifiedName(type));
+ }
+ return false;
+ }
+
+
+ private StringMatcher[] fStringMatchers;
+
+ /**
+ *
+ */
+ public TypeFilter() {
+ fStringMatchers= null;
+ PreferenceConstants.getPreferenceStore().addPropertyChangeListener(this);
+ }
+
+ private synchronized StringMatcher[] getStringMatchers() {
+ if (fStringMatchers == null) {
+ String str= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.TYPEFILTER_ENABLED);
+ StringTokenizer tok= new StringTokenizer(str, ";"); //$NON-NLS-1$
+ int nTokens= tok.countTokens();
+
+ fStringMatchers= new StringMatcher[nTokens];
+ for (int i= 0; i < nTokens; i++) {
+ String curr= tok.nextToken();
+ if (curr.length() > 0) {
+ fStringMatchers[i]= new StringMatcher(curr, false, false);
+ }
+ }
+ }
+ return fStringMatchers;
+ }
+
+ public void dispose() {
+ PreferenceConstants.getPreferenceStore().removePropertyChangeListener(this);
+ fStringMatchers= null;
+ }
+
+
+ public boolean hasFilters() {
+ return getStringMatchers().length > 0;
+ }
+
+ public boolean filter(String fullTypeName) {
+ StringMatcher[] matchers= getStringMatchers();
+ for (int i= 0; i < matchers.length; i++) {
+ StringMatcher curr= matchers[i];
+ if (curr.match(fullTypeName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public synchronized void propertyChange(PropertyChangeEvent event) {
+ if (PreferenceConstants.TYPEFILTER_ENABLED.equals(event.getProperty())) {
+ fStringMatchers= null;
+ }
+ }
+}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/TypeInfo.java 2007-05-01 14:53:45 UTC (rev 2406)
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.util;
+
+import org.eclipse.core.runtime.IPath;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.internal.core.util.CharOperation;
+import org.rubypeople.rdt.ui.dialogs.ITypeInfoRequestor;
+
+public abstract class TypeInfo {
+
+ public static class TypeInfoAdapter implements ITypeInfoRequestor {
+ private TypeInfo fInfo;
+ public void setInfo(TypeInfo info) {
+ fInfo= info;
+ }
+ public boolean isModule() {
+ return fInfo.isModule();
+ }
+ public String getTypeName() {
+ return fInfo.getTypeName();
+ }
+ public String getPackageName() {
+ return fInfo.getPackageName();
+ }
+ public String getEnclosingName() {
+ return fInfo.getEnclosingName();
+ }
+ }
+
+ final String fName;
+ final String fPackage;
+ final char[][] fEnclosingNames;
+
+ private boolean fIsModule;
+
+ public static final int UNRESOLVABLE_TYPE_INFO= 1;
+ public static final int JAR_FILE_ENTRY_TYPE_INFO= 2;
+ public static final int IFILE_TYPE_INFO= 3;
+
+ static final char SEPARATOR= '/';
+ static final char EXTENSION_SEPARATOR= '.';
+ static final char PACKAGE_PART_SEPARATOR='.';
+
+ static final String EMPTY_STRING= ""; //$NON-NLS-1$
+
+ protected TypeInfo(String pkg, String name, char[][] enclosingTypes, boolean isModule) {
+ fPackage= pkg;
+ fName= name;
+ fIsModule= isModule;
+ fEnclosingNames= enclosingTypes;
+ }
+
+ public int hashCode() {
+ return (fPackage.hashCode() << 16) + fName.hashCode();
+ }
+
+ /**
+ * Returns this type info's kind encoded as an integer.
+ *
+ * @return the type info's kind
+ */
+ public abstract int getElementType();
+
+ /**
+ * Returns the path reported by the <tt>ITypeNameRequestor</tt>.
+ *
+ * @return the path of the type info
+ */
+ public abstract String getPath();
+
+ /**
+ * Returns the container (class file or CU) this type info is contained
+ * in.
+ *
+ * @param scope the scope used to resolve the <tt>IRubyElement</tt>.
+ * @return the container this type info is contained in.
+ * @throws RubyModelException if an error occurs while access the Ruby
+ * model.
+ */
+ protected abstract IRubyElement getContainer(IRubySearchScope scope) throws RubyModelException;
+
+ /**
+ * Returns the package fragment root path of this type info.
+ *
+ * @return the package fragment root as an <tt>IPath</tt>.
+ */
+ public abstract IPath getPackageFragmentRootPath();
+
+ /**
+ * Returns the package fragment root name of this type info
+ */
+ public abstract String getPackageFragmentRootName();
+
+ /**
+ * Returns the type name.
+ *
+ * @return the info's type name.
+ */
+ public String getTypeName() {
+ return fName;
+ }
+
+ /**
+ * Returns the package name.
+ *
+ * @return the info's package name.
+ */
+ public String getPackageName() {
+ return fPackage;
+ }
+
+ /**
+ * Returns true iff the type info describes an interface.
+ */
+ public boolean isModule() {
+ return fIsModule;
+ }
+
+ /**
+ * Returns true if the info is enclosed in the given scope
+ */
+ public boolean isEnclosed(IRubySearchScope scope) {
+ return scope.encloses(getPath());
+ }
+
+ /**
+ * Gets the enclosing name (dot separated).
+ */
+ public String getEnclosingName() {
+ if (fEnclosingNames == null || fEnclosingNames.length == 0)
+ return EMPTY_STRING;
+ StringBuffer buf= new StringBuffer();
+ for (int i= 0; i < fEnclosingNames.length; i++) {
+ if (i != 0) {
+ buf.append('.');
+ }
+ buf.append(fEnclosingNames[i]);
+ }
+ return buf.toString();
+ }
+
+ public boolean isInnerType() {
+ return fEnclosingNames != null && fEnclosingNames.length > 0;
+ }
+
+ /**
+ * Gets the type qualified name: Includes enclosing type names, but
+ * not package name. Identifiers are separated by dots.
+ */
+ public String getTypeQualifiedName() {
+ if (fEnclosingNames != null && fEnclosingNames.length > 0) {
+ StringBuffer buf= new StringBuffer();
+ for (int i= 0; i < fEnclosingNames.length; i++) {
+ buf.append(fEnclosingNames[i]);
+ buf.append('.');
+ }
+ buf.append(fName);
+ return buf.toString();
+ }
+ return fName;
+ }
+
+ /**
+ * Gets the fully qualified type name: Includes enclosing type names and
+ * package. All identifiers are separated by dots.
+ */
+ public String getFullyQualifiedName() {
+ StringBuffer buf= new StringBuffer();
+ if (fPackage.length() > 0) {
+ buf.append(fPackage);
+ buf.append('.');
+ }
+ if (fEnclosingNames != null) {
+ for (int i= 0; i < fEnclosingNames.length; i++) {
+ buf.append(fEnclosingNames[i]);
+ buf.append('.');
+ }
+ }
+ buf.append(fName);
+ return buf.toString();
+ }
+
+ /**
+ * Gets the fully qualified type container name: Package name or
+ * enclosing type name with package name.
+ * All identifiers are separated by dots.
+ */
+ public String getTypeContainerName() {
+ if (fEnclosingNames != null && fEnclosingNames.length > 0) {
+ StringBuffer buf= new StringBuffer();
+ if (fPackage.length() > 0) {
+ buf.append(fPackage);
+ }
+ for (int i= 0; i < fEnclosingNames.length; i++) {
+ if (buf.length() > 0) {
+ buf.append('.');
+ }
+ buf.append(fEnclosingNames[i]);
+ }
+ return buf.toString();
+ }
+ return fPackage;
+ }
+
+ /**
+ * Resolves the type in a scope if was searched for.
+ * The parent project of JAR files is the first project found in scope.
+ * Returns null if the type could not be resolved
+ */
+ public IType resolveType(IRubySearchScope scope) throws RubyModelException {
+ IRubyElement elem = getContainer(scope);
+ if (elem instanceof IRubyScript)
+ return RubyModelUtil.findTypeInRubyScript((IRubyScript)elem, getTypeQualifiedName());
+ return null;
+ }
+
+ protected boolean doEquals(TypeInfo other) {
+ // Don't compare the modifiers since they aren't relevant to identify
+ // a type.
+ return fName.equals(other.fName) && fPackage.equals(other.fPackage)
+ && CharOperation.equals(fEnclosingNames, other.fEnclosingNames);
+ }
+
+...
[truncated message content] |
|
From: <caw...@us...> - 2007-05-01 14:53:00
|
Revision: 2405
http://svn.sourceforge.net/rubyeclipse/?rev=2405&view=rev
Author: cawilliams
Date: 2007-05-01 07:52:12 -0700 (Tue, 01 May 2007)
Log Message:
-----------
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/dialogs/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mba...@us...> - 2007-05-01 13:15:14
|
Revision: 2404
http://svn.sourceforge.net/rubyeclipse/?rev=2404&view=rev
Author: mbarchfe
Date: 2007-05-01 06:15:12 -0700 (Tue, 01 May 2007)
Log Message:
-----------
set current ruby-debug-ide from 0.1.2 to 0.1.4
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties 2007-05-01 13:13:41 UTC (rev 2403)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties 2007-05-01 13:15:12 UTC (rev 2404)
@@ -162,7 +162,7 @@
DebuggerPreferencePage_description_label=Debugger preferences
DebuggerPreferencePage_useRubyDebug_label=Use ruby-debug library
DebuggerPreferencePage_verboseDebugger_label=Debugger verbose mode
-DebuggerPreferencePage_useRubyDebug_comment=In order to use ruby-debug you have to install the gem ruby-debug-ide,\n version 0.1 is compatible with this release of RDT.\nYou should always take the latest service release (currently being 0.1.2)\nFor the installation you usually have to enter ''gem install ruby-debug-ide''
+DebuggerPreferencePage_useRubyDebug_comment=In order to use ruby-debug you have to install the gem ruby-debug-ide,\n version 0.1 is compatible with this release of RDT.\nYou should always take the latest service release (currently being 0.1.4)\nFor the installation you usually have to enter ''gem install ruby-debug-ide''
PropertyAndPreferencePage_useprojectsettings_label=Enable pr&oject specific settings
PropertyAndPreferencePage_useworkspacesettings_change=Configure Workspace Settings...
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
Revision: 2403
http://svn.sourceforge.net/rubyeclipse/?rev=2403&view=rev
Author: mbarchfe
Date: 2007-05-01 06:13:41 -0700 (Tue, 01 May 2007)
Log Message:
-----------
inspect timeout: reduced from 100sec to 15sec
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_AbstractDebuggerCommunicationTest.java
Modified: trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_AbstractDebuggerCommunicationTest.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_AbstractDebuggerCommunicationTest.java 2007-05-01 13:12:09 UTC (rev 2402)
+++ trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_AbstractDebuggerCommunicationTest.java 2007-05-01 13:13:41 UTC (rev 2403)
@@ -319,6 +319,7 @@
public void testBreakpointOnFirstLine() throws Exception {
createSocket(new String[] { "puts 'a'" });
runTo("test.rb", 1);
+ sendRuby("exit") ;
}
public void testBreakpointAddAndRemove() throws Exception {
@@ -904,7 +905,8 @@
public void testInspectTimeout() throws Exception {
createSocket(new String[] { "puts 'test'", "puts 'test'" });
runToLine(2);
- sendRuby("v inspect sleep(100)");
+ // timeout is 10 seconds
+ sendRuby("v inspect sleep(15)");
try {
getVariableReader().readVariables(createStackFrame());
fail("Timeout did not occur.");
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mba...@us...> - 2007-05-01 13:12:10
|
Revision: 2402
http://svn.sourceforge.net/rubyeclipse/?rev=2402&view=rev
Author: mbarchfe
Date: 2007-05-01 06:12:09 -0700 (Tue, 01 May 2007)
Log Message:
-----------
set the timeout for inspection on the ruby side (requires ruby-debug-ide 0.1.4)
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/VariableReader.java
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/VariableReader.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/VariableReader.java 2007-05-01 13:11:08 UTC (rev 2401)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/VariableReader.java 2007-05-01 13:12:09 UTC (rev 2402)
@@ -39,8 +39,7 @@
this.parent = parent;
this.variables = new ArrayList<IVariable>();
try {
- // TODO: timeout should be configurable
- this.read(10000);
+ this.read();
} catch (Exception ex) {
RdtDebugCorePlugin.log(ex);
return new RubyVariable[0];
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mba...@us...> - 2007-05-01 13:11:11
|
Revision: 2401
http://svn.sourceforge.net/rubyeclipse/?rev=2401&view=rev
Author: mbarchfe
Date: 2007-05-01 06:11:08 -0700 (Tue, 01 May 2007)
Log Message:
-----------
set isConnected flag earlier
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/MultiReaderStrategy.java
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/MultiReaderStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/MultiReaderStrategy.java 2007-05-01 13:10:21 UTC (rev 2400)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/parsing/MultiReaderStrategy.java 2007-05-01 13:11:08 UTC (rev 2401)
@@ -34,11 +34,11 @@
// RdtDebugCorePlugin.log(e);
e.printStackTrace();
} finally {
+ isConnected = false;
try {
Thread.sleep(1000) ; // Avoid Commodfication Exceptions
} catch (InterruptedException e) {
}
- isConnected = false;
releaseAllReaders();
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mba...@us...> - 2007-05-01 13:10:22
|
Revision: 2400
http://svn.sourceforge.net/rubyeclipse/?rev=2400&view=rev
Author: mbarchfe
Date: 2007-05-01 06:10:21 -0700 (Tue, 01 May 2007)
Log Message:
-----------
do *not* close the socked connection *before* sending the exit command
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/commands/RubyDebugConnection.java
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/commands/RubyDebugConnection.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/commands/RubyDebugConnection.java 2007-05-01 13:09:38 UTC (rev 2399)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/commands/RubyDebugConnection.java 2007-05-01 13:10:21 UTC (rev 2400)
@@ -32,7 +32,6 @@
@Override
public void exit() throws IOException {
- super.exit();
GenericCommand command = new GenericCommand("exit", true);
command.execute(this);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mba...@us...> - 2007-05-01 13:09:41
|
Revision: 2399
http://svn.sourceforge.net/rubyeclipse/?rev=2399&view=rev
Author: mbarchfe
Date: 2007-05-01 06:09:38 -0700 (Tue, 01 May 2007)
Log Message:
-----------
Applied patch from Martin Krauskopf: added forced step/next; use finish for step return
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ClassicDebuggerCommandFactory.java
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ICommandFactory.java
trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/RubyDebugCommandFactory.java
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ClassicDebuggerCommandFactory.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ClassicDebuggerCommandFactory.java 2007-04-30 14:48:33 UTC (rev 2398)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ClassicDebuggerCommandFactory.java 2007-05-01 13:09:38 UTC (rev 2399)
@@ -1,75 +1,85 @@
-package org.rubypeople.rdt.internal.debug.core;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.debug.core.model.IBreakpoint;
-import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
-import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
-import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
-
-public class ClassicDebuggerCommandFactory implements ICommandFactory {
-
- public String createReadFrames(RubyThread thread) {
- return "th " + thread.getId() + " ; w" ;
- }
-
- public String createReadLocalVariables(RubyStackFrame frame) {
- return "th " + ((RubyThread) frame.getThread()).getId() + " ; frame " + frame.getIndex() + " ; v l " ;
- }
-
- public String createReadInstanceVariable(RubyVariable variable) {
- return "th " + ((RubyThread) variable.getStackFrame().getThread()).getId() + " ; v i " + variable.getStackFrame().getIndex() + " " + variable.getObjectId();
- }
-
- public String createStepOver(RubyStackFrame stackFrame) {
- return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; next";
- }
-
- public String createStepReturn(RubyStackFrame stackFrame) {
- return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; next " + (stackFrame.getLineNumber() + 1);
- }
-
- public String createStepInto(RubyStackFrame stackFrame) {
- return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; step";
- }
-
- public String createReadThreads() {
- return "th l";
- }
-
- public String createLoad(String filename) {
- return "load " + filename;
- }
-
- public String createInspect(RubyStackFrame frame, String expression) {
- return "th " + ((RubyThread) frame.getThread()).getId() + " ; v inspect " + frame.getIndex() + " " + expression;
- }
-
- public String createResume(RubyThread thread) {
- return "th " + thread.getId() + ";cont";
- }
-
- public String createAddBreakpoint(String file, int line) {
- StringBuffer setBreakPointCommand = new StringBuffer();
- setBreakPointCommand.append("b ") ;
- setBreakPointCommand.append(file);
- setBreakPointCommand.append(":");
- setBreakPointCommand.append(line);
- return setBreakPointCommand.toString();
- }
-
- public String createRemoveBreakpoint(int index) {
- return "delete " + index ;
- }
-
- public String createCatchOff() {
- return "catch off";
- }
-
- public String createCatchOn(IBreakpoint breakpoint) throws CoreException {
- return "catch " + ((RubyExceptionBreakpoint) breakpoint).getException();
- }
-
- public String createThreadStop(RubyThread thread) {
- return "th stop " +thread.getId() ;
- }
-}
+package org.rubypeople.rdt.internal.debug.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
+import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
+import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
+
+public class ClassicDebuggerCommandFactory implements ICommandFactory {
+
+ public String createReadFrames(RubyThread thread) {
+ return "th " + thread.getId() + " ; w" ;
+ }
+
+ public String createReadLocalVariables(RubyStackFrame frame) {
+ return "th " + ((RubyThread) frame.getThread()).getId() + " ; frame " + frame.getIndex() + " ; v l " ;
+ }
+
+ public String createReadInstanceVariable(RubyVariable variable) {
+ return "th " + ((RubyThread) variable.getStackFrame().getThread()).getId() + " ; v i " + variable.getStackFrame().getIndex() + " " + variable.getObjectId();
+ }
+
+ public String createStepOver(RubyStackFrame stackFrame) {
+ return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; next";
+ }
+
+ public String createForcedStepOver(RubyStackFrame stackFrame) {
+ // not supported by Classic Debugger
+ return createStepOver(stackFrame);
+ }
+
+ public String createStepReturn(RubyStackFrame stackFrame) {
+ return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; next " + (stackFrame.getLineNumber() + 1);
+ }
+
+ public String createStepInto(RubyStackFrame stackFrame) {
+ return "th " + ((RubyThread) stackFrame.getThread()).getId() + " ; step";
+ }
+
+ public String createForcedStepInto(RubyStackFrame stackFrame) {
+ // not supported by Classic Debugger
+ return createStepInto(stackFrame);
+ }
+
+ public String createReadThreads() {
+ return "th l";
+ }
+
+ public String createLoad(String filename) {
+ return "load " + filename;
+ }
+
+ public String createInspect(RubyStackFrame frame, String expression) {
+ return "th " + ((RubyThread) frame.getThread()).getId() + " ; v inspect " + frame.getIndex() + " " + expression;
+ }
+
+ public String createResume(RubyThread thread) {
+ return "th " + thread.getId() + ";cont";
+ }
+
+ public String createAddBreakpoint(String file, int line) {
+ StringBuffer setBreakPointCommand = new StringBuffer();
+ setBreakPointCommand.append("b ") ;
+ setBreakPointCommand.append(file);
+ setBreakPointCommand.append(":");
+ setBreakPointCommand.append(line);
+ return setBreakPointCommand.toString();
+ }
+
+ public String createRemoveBreakpoint(int index) {
+ return "delete " + index ;
+ }
+
+ public String createCatchOff() {
+ return "catch off";
+ }
+
+ public String createCatchOn(IBreakpoint breakpoint) throws CoreException {
+ return "catch " + ((RubyExceptionBreakpoint) breakpoint).getException();
+ }
+
+ public String createThreadStop(RubyThread thread) {
+ return "th stop " +thread.getId() ;
+ }
+}
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ICommandFactory.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ICommandFactory.java 2007-04-30 14:48:33 UTC (rev 2398)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/ICommandFactory.java 2007-05-01 13:09:38 UTC (rev 2399)
@@ -1,40 +1,44 @@
-package org.rubypeople.rdt.internal.debug.core;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.debug.core.model.IBreakpoint;
-import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
-import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
-import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
-
-public interface ICommandFactory {
-
- public String createReadFrames(RubyThread thread);
-
- public String createReadLocalVariables(RubyStackFrame frame);
-
- public String createReadInstanceVariable(RubyVariable variable);
-
- public String createStepOver(RubyStackFrame stackFrame);
-
- public String createStepReturn(RubyStackFrame stackFrame);
-
- public String createStepInto(RubyStackFrame stackFrame);
-
- public String createReadThreads();
-
- public String createThreadStop(RubyThread thread);
-
- public String createInspect(RubyStackFrame frame, String expression);
-
- public String createResume(RubyThread thread);
-
- public String createAddBreakpoint(String file, int line);
-
- public String createRemoveBreakpoint(int index);
-
- public String createCatchOff();
-
- public String createCatchOn(IBreakpoint breakpoint) throws CoreException;
-
- public String createLoad(String filename);
-}
\ No newline at end of file
+package org.rubypeople.rdt.internal.debug.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
+import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
+import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
+
+public interface ICommandFactory {
+
+ public String createReadFrames(RubyThread thread);
+
+ public String createReadLocalVariables(RubyStackFrame frame);
+
+ public String createReadInstanceVariable(RubyVariable variable);
+
+ public String createStepOver(RubyStackFrame stackFrame);
+
+ public String createForcedStepOver(RubyStackFrame stackFrame);
+
+ public String createStepReturn(RubyStackFrame stackFrame);
+
+ public String createStepInto(RubyStackFrame stackFrame);
+
+ public String createForcedStepInto(RubyStackFrame stackFrame);
+
+ public String createReadThreads();
+
+ public String createThreadStop(RubyThread thread);
+
+ public String createInspect(RubyStackFrame frame, String expression);
+
+ public String createResume(RubyThread thread);
+
+ public String createAddBreakpoint(String file, int line);
+
+ public String createRemoveBreakpoint(int index);
+
+ public String createCatchOff();
+
+ public String createCatchOn(IBreakpoint breakpoint) throws CoreException;
+
+ public String createLoad(String filename);
+}
Modified: trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/RubyDebugCommandFactory.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/RubyDebugCommandFactory.java 2007-04-30 14:48:33 UTC (rev 2398)
+++ trunk/org.rubypeople.rdt.debug.core/src/org/rubypeople/rdt/internal/debug/core/RubyDebugCommandFactory.java 2007-05-01 13:09:38 UTC (rev 2399)
@@ -1,75 +1,83 @@
-package org.rubypeople.rdt.internal.debug.core;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.debug.core.model.IBreakpoint;
-import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
-import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
-import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
-
-public class RubyDebugCommandFactory implements ICommandFactory {
-
- public String createReadFrames(RubyThread thread) {
- return "w" ;
- }
-
- public String createReadLocalVariables(RubyStackFrame frame) {
- return "frame " + frame.getIndex() + " ; v l " ;
- }
-
- public String createReadInstanceVariable(RubyVariable variable) {
- return "frame " + variable.getStackFrame().getIndex() + " ; v i " + variable.getObjectId();
- }
-
- public String createStepOver(RubyStackFrame frame) {
- return "frame " + frame.getIndex() + " ; next" ;
- }
-
- public String createStepReturn(RubyStackFrame frame) {
- return "frame " + frame.getIndex() + " ; next 1 " + (frame.getIndex() + 1) ;
- }
-
- public String createStepInto(RubyStackFrame frame) {
- return "frame " + frame.getIndex() + " ; step";
- }
-
- public String createReadThreads() {
- return "th l";
- }
-
- public String createLoad(String filename) {
- return "load " + filename;
- }
-
- public String createInspect(RubyStackFrame frame, String expression) {
- return "frame " + frame.getIndex() + " ; v inspect " + expression.replaceAll(";", "\\;");
- }
-
- public String createResume(RubyThread thread) {
- return "cont";
- }
-
- public String createAddBreakpoint(String file, int line) {
- StringBuffer setBreakPointCommand = new StringBuffer();
- setBreakPointCommand.append("b ") ;
- setBreakPointCommand.append(file);
- setBreakPointCommand.append(":");
- setBreakPointCommand.append(line);
- return setBreakPointCommand.toString();
- }
-
- public String createRemoveBreakpoint(int index) {
- return "delete " + index ;
- }
-
- public String createCatchOff() {
- return "catch off";
- }
-
- public String createCatchOn(IBreakpoint breakpoint) throws CoreException {
- return "catch " + ((RubyExceptionBreakpoint) breakpoint).getException();
- }
-
- public String createThreadStop(RubyThread thread) {
- return "thread stop " + thread.getId();
- }
-}
+package org.rubypeople.rdt.internal.debug.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
+import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
+import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
+
+public class RubyDebugCommandFactory implements ICommandFactory {
+
+ public String createReadFrames(RubyThread thread) {
+ return "w" ;
+ }
+
+ public String createReadLocalVariables(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + " ; v l " ;
+ }
+
+ public String createReadInstanceVariable(RubyVariable variable) {
+ return "frame " + variable.getStackFrame().getIndex() + " ; v i " + variable.getObjectId();
+ }
+
+ public String createStepOver(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + " ; next" ;
+ }
+
+ public String createForcedStepOver(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + " ; next+";
+ }
+
+ public String createStepReturn(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + "; finish";
+ }
+
+ public String createStepInto(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + " ; step";
+ }
+
+ public String createForcedStepInto(RubyStackFrame frame) {
+ return "frame " + frame.getIndex() + " ; step+";
+ }
+
+ public String createReadThreads() {
+ return "th l";
+ }
+
+ public String createLoad(String filename) {
+ return "load " + filename;
+ }
+
+ public String createInspect(RubyStackFrame frame, String expression) {
+ return "frame " + frame.getIndex() + " ; v inspect " + expression.replaceAll(";", "\\;");
+ }
+
+ public String createResume(RubyThread thread) {
+ return "cont";
+ }
+
+ public String createAddBreakpoint(String file, int line) {
+ StringBuffer setBreakPointCommand = new StringBuffer();
+ setBreakPointCommand.append("b ") ;
+ setBreakPointCommand.append(file);
+ setBreakPointCommand.append(":");
+ setBreakPointCommand.append(line);
+ return setBreakPointCommand.toString();
+ }
+
+ public String createRemoveBreakpoint(int index) {
+ return "delete " + index ;
+ }
+
+ public String createCatchOff() {
+ return "catch off";
+ }
+
+ public String createCatchOn(IBreakpoint breakpoint) throws CoreException {
+ return "catch " + ((RubyExceptionBreakpoint) breakpoint).getException();
+ }
+
+ public String createThreadStop(RubyThread thread) {
+ return "thread stop " + thread.getId();
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-04-30 14:48:37
|
Revision: 2398
http://svn.sourceforge.net/rubyeclipse/?rev=2398&view=rev
Author: cawilliams
Date: 2007-04-30 07:48:33 -0700 (Mon, 30 Apr 2007)
Log Message:
-----------
try checking System path to find a ruby executable on windows
Modified Paths:
--------------
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMType.java
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMType.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMType.java 2007-04-30 14:09:45 UTC (rev 2397)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/StandardVMType.java 2007-04-30 14:48:33 UTC (rev 2398)
@@ -255,34 +255,45 @@
* @see org.eclipse.jdt.launching.IVMInstallType#detectInstallLocation()
*/
public File detectInstallLocation() {
- // do not detect on Windows
+ File rubyExecutable = null;
if (Platform.getOS().equals(Constants.OS_WIN32)) {
- return null;
- }
-
- String[] cmdLine = new String[] { "which", "ruby" }; //$NON-NLS-1$ //$NON-NLS-2$
- Process p = null;
- File rubyExecutable = null;
- try {
- p = Runtime.getRuntime().exec(cmdLine);
- IProcess process = DebugPlugin.newProcess(new Launch(null, ILaunchManager.RUN_MODE, null), p, "Standard Ruby VM Install Detection"); //$NON-NLS-1$
- for (int i = 0; i < 200; i++) {
- // Wait no more than 10 seconds (200 * 50 mils)
- if (process.isTerminated()) {
+ String winPath = System.getenv("Path"); // iterate through system path and try to find ruby.exe
+ String[] paths = winPath.split(";");
+ for (int i = 0; i < paths.length; i++) {
+ String possibleExecutablePath = paths[i] + File.separator + "ruby.exe";
+ File possible = new File(possibleExecutablePath);
+ if (possible.exists()) {
+ rubyExecutable = possible;
break;
}
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {}
}
- rubyExecutable = parseRubyExecutableLocation(process);
- } catch (IOException ioe) {
- LaunchingPlugin.log(ioe);
- } finally {
- if (p != null) {
- p.destroy();
+ } else { // Mac, Linux - so let's just run 'which ruby' and parse out the result
+ String[] cmdLine = new String[] { "which", "ruby" }; //$NON-NLS-1$ //$NON-NLS-2$
+ Process p = null;
+ try {
+ p = Runtime.getRuntime().exec(cmdLine);
+ IProcess process = DebugPlugin.newProcess(new Launch(null,
+ ILaunchManager.RUN_MODE, null), p,
+ "Standard Ruby VM Install Detection"); //$NON-NLS-1$
+ for (int i = 0; i < 200; i++) {
+ // Wait no more than 10 seconds (200 * 50 mils)
+ if (process.isTerminated()) {
+ break;
+ }
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ }
+ rubyExecutable = parseRubyExecutableLocation(process);
+ } catch (IOException ioe) {
+ LaunchingPlugin.log(ioe);
+ } finally {
+ if (p != null) {
+ p.destroy();
+ }
}
- }
+ }
if (rubyExecutable == null) {
return null;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|