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-08-02 17:54:55
|
Revision: 2922
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2922&view=rev
Author: cawilliams
Date: 2007-08-02 10:54:52 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/LintOptions.java
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/LintOptions.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/LintOptions.java 2007-08-02 17:50:41 UTC (rev 2921)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/LintOptions.java 2007-08-02 17:54:52 UTC (rev 2922)
@@ -26,6 +26,8 @@
public static final long EnumerableMissingMethod = 0x80000;
public static final long SubclassDoesntCallSuper = 0x100000;
public static final long AssignmentPrecedence = 0x200000;
+ public static final long MethodMissingWithoutRespondTo = 0x400000;
+ public static final long ConstantNamingConvention = 0x800000;
public static final String ERROR = RubyCore.ERROR;
public static final String WARNING = RubyCore.WARNING;
@@ -44,6 +46,8 @@
| UnreachableCode
| AssignmentPrecedence
| SubclassDoesntCallSuper
+ | MethodMissingWithoutRespondTo
+ | ConstantNamingConvention
/*| NullReference -- keep RubyCore#getDefaultOptions comment in sync */;
public int maxLocals = 5;
@@ -71,11 +75,13 @@
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_UNREACHABLE_CODE, getSeverityString(UnreachableCode));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_COMPARABLE_MISSING_METHOD, getSeverityString(ComparableMissingMethod));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_ENUMERABLE_MISSING_METHOD, getSeverityString(EnumerableMissingMethod));
+ optionsMap.put(AptanaRDTPlugin.COMPILER_PB_CONSTANT_NAMING_CONVENTION, getSeverityString(ConstantNamingConvention));
+ optionsMap.put(AptanaRDTPlugin.COMPILER_PB_METHOD_MISSING_NO_RESPOND_TO, getSeverityString(MethodMissingWithoutRespondTo));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_ARGUMENTS, String.valueOf(maxArguments));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_LINES, String.valueOf(maxLines));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_LOCALS, String.valueOf(maxLocals));
optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_RETURNS, String.valueOf(maxReturns));
- optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_BRANCHES, String.valueOf(maxBranches));
+ optionsMap.put(AptanaRDTPlugin.COMPILER_PB_MAX_BRANCHES, String.valueOf(maxBranches));
return optionsMap;
}
@@ -106,6 +112,8 @@
if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_ENUMERABLE_MISSING_METHOD)) != null) updateSeverity(EnumerableMissingMethod, optionValue);
if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_SUBCLASS_DOESNT_CALL_SUPER)) != null) updateSeverity(SubclassDoesntCallSuper, optionValue);
if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_ASSIGNMENT_PRECEDENCE)) != null) updateSeverity(AssignmentPrecedence, optionValue);
+ if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_CONSTANT_NAMING_CONVENTION)) != null) updateSeverity(ConstantNamingConvention, optionValue);
+ if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_METHOD_MISSING_NO_RESPOND_TO)) != null) updateSeverity(MethodMissingWithoutRespondTo, optionValue);
if ((optionValue = optionsMap.get(AptanaRDTPlugin.COMPILER_PB_MAX_LOCALS)) != null) {
if (optionValue instanceof String) {
String stringValue = (String) optionValue;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 17:50:42
|
Revision: 2921
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2921&view=rev
Author: cawilliams
Date: 2007-08-02 10:50:41 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java 2007-08-02 17:50:08 UTC (rev 2920)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java 2007-08-02 17:50:41 UTC (rev 2921)
@@ -12,6 +12,9 @@
public class MethodMissingWithoutRespondTo extends RubyLintVisitor {
+ private static final String RESPOND_TO = "respond_to";
+ private static final String METHOD_MISSING = "method_missing";
+
private Map<String, DefnNode> methods = new HashMap<String, DefnNode>();
public MethodMissingWithoutRespondTo(String contents) {
@@ -31,8 +34,8 @@
@Override
public void exitClassNode(ClassNode iVisited) {
- if (methods.containsKey("method_missing") && !methods.containsKey("respond_to")) {
- createProblem(methods.get("method_missing").getNameNode().getPosition(), "Class defines method_missing, but does not define custom respond_to");
+ if (methods.containsKey(METHOD_MISSING) && !methods.containsKey(RESPOND_TO)) {
+ createProblem(methods.get(METHOD_MISSING).getNameNode().getPosition(), "Class defines method_missing, but does not define custom respond_to");
}
methods.clear();
super.exitClassNode(iVisited);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 17:50:10
|
Revision: 2920
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2920&view=rev
Author: cawilliams
Date: 2007-08-02 10:50:08 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
fix #5427 - Add code check for defining method_missing but no respond_to
Modified Paths:
--------------
trunk/com.aptana.rdt/plugin.xml
trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java
Added Paths:
-----------
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java
Modified: trunk/com.aptana.rdt/plugin.xml
===================================================================
--- trunk/com.aptana.rdt/plugin.xml 2007-08-02 17:35:18 UTC (rev 2919)
+++ trunk/com.aptana.rdt/plugin.xml 2007-08-02 17:50:08 UTC (rev 2920)
@@ -77,9 +77,16 @@
<argument prefKey="com.aptana.rdt.compiler.problem.maxReturns"/>
</error>
<error
+ categoryId="org.rubypeople.rdt.errors.codeConvention"
+ label="Constant name doesn't match convention"
+ prefKey="com.aptana.rdt.compiler.problem.constantNamingConvention"/>
+ <category
+ id="org.rubypeople.rdt.errors.codeConvention"
+ name="Ruby Coding Conventions"/>
+ <error
categoryId="org.rubypeople.rdt.errors.potentialProblems"
- label="Constant name doesn't match convention"
- prefKey="com.aptana.rdt.compiler.problem.constantNamingConvention"/>
+ label="method_missing defined without re-defined respond_to"
+ prefKey="com.aptana.rdt.compiler.problem.methodMissingWithoutRespondTo"/>
</extension>
<!-- =================================================================================== -->
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java 2007-08-02 17:35:18 UTC (rev 2919)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java 2007-08-02 17:50:08 UTC (rev 2920)
@@ -203,6 +203,12 @@
*/
public static final String COMPILER_PB_CONSTANT_NAMING_CONVENTION = PLUGIN_ID + ".compiler.problem.constantNamingConvention"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 1.0.0
+ */
+ public static final String COMPILER_PB_METHOD_MISSING_NO_RESPOND_TO = PLUGIN_ID + "com.aptana.rdt.compiler.problem.methodMissingWithoutRespondTo";
// The shared instance
private static AptanaRDTPlugin plugin;
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java 2007-08-02 17:50:08 UTC (rev 2920)
@@ -0,0 +1,41 @@
+package com.aptana.rdt.internal.parser.warnings;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jruby.ast.ClassNode;
+import org.jruby.ast.DefnNode;
+import org.jruby.evaluator.Instruction;
+import org.rubypeople.rdt.internal.core.parser.warnings.RubyLintVisitor;
+
+import com.aptana.rdt.AptanaRDTPlugin;
+
+public class MethodMissingWithoutRespondTo extends RubyLintVisitor {
+
+ private Map<String, DefnNode> methods = new HashMap<String, DefnNode>();
+
+ public MethodMissingWithoutRespondTo(String contents) {
+ super(contents);
+ }
+
+ @Override
+ protected String getOptionKey() {
+ return AptanaRDTPlugin.COMPILER_PB_METHOD_MISSING_NO_RESPOND_TO;
+ }
+
+ @Override
+ public Instruction visitDefnNode(DefnNode iVisited) {
+ methods.put(iVisited.getName(), iVisited);
+ return super.visitDefnNode(iVisited);
+ }
+
+ @Override
+ public void exitClassNode(ClassNode iVisited) {
+ if (methods.containsKey("method_missing") && !methods.containsKey("respond_to")) {
+ createProblem(methods.get("method_missing").getNameNode().getPosition(), "Class defines method_missing, but does not define custom respond_to");
+ }
+ methods.clear();
+ super.exitClassNode(iVisited);
+ }
+
+}
Property changes on: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/MethodMissingWithoutRespondTo.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java 2007-08-02 17:35:18 UTC (rev 2919)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java 2007-08-02 17:50:08 UTC (rev 2920)
@@ -83,6 +83,7 @@
visitors.add(new EnumerableInclusionVisitor(contents));
visitors.add(new AndOrUsedOnRighthandAssignment(contents));
visitors.add(new ConstantNamingConvention(contents));
+ visitors.add(new MethodMissingWithoutRespondTo(contents));
return visitors;
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 17:35:22
|
Revision: 2919
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2919&view=rev
Author: cawilliams
Date: 2007-08-02 10:35:18 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
Fix #5425 - Add code check for constant naming convention
Modified Paths:
--------------
trunk/com.aptana.rdt/plugin.xml
trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java
Added Paths:
-----------
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/ConstantNamingConvention.java
Modified: trunk/com.aptana.rdt/plugin.xml
===================================================================
--- trunk/com.aptana.rdt/plugin.xml 2007-08-02 15:34:45 UTC (rev 2918)
+++ trunk/com.aptana.rdt/plugin.xml 2007-08-02 17:35:18 UTC (rev 2919)
@@ -75,7 +75,11 @@
label="Maximum number of returns in a method"
prefKey="com.aptana.rdt.compiler.problem.codeComplexityReturns">
<argument prefKey="com.aptana.rdt.compiler.problem.maxReturns"/>
- </error>
+ </error>
+ <error
+ categoryId="org.rubypeople.rdt.errors.potentialProblems"
+ label="Constant name doesn't match convention"
+ prefKey="com.aptana.rdt.compiler.problem.constantNamingConvention"/>
</extension>
<!-- =================================================================================== -->
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java 2007-08-02 15:34:45 UTC (rev 2918)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/AptanaRDTPlugin.java 2007-08-02 17:35:18 UTC (rev 2919)
@@ -196,6 +196,14 @@
*/
public static final String COMPILER_PB_ASSIGNMENT_PRECEDENCE = PLUGIN_ID + ".compiler.problem.assignmentPrecedence"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 1.0.0
+ */
+ public static final String COMPILER_PB_CONSTANT_NAMING_CONVENTION = PLUGIN_ID + ".compiler.problem.constantNamingConvention"; //$NON-NLS-1$
+
+
// The shared instance
private static AptanaRDTPlugin plugin;
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/ConstantNamingConvention.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/ConstantNamingConvention.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/ConstantNamingConvention.java 2007-08-02 17:35:18 UTC (rev 2919)
@@ -0,0 +1,29 @@
+package com.aptana.rdt.internal.parser.warnings;
+
+import org.jruby.ast.ConstDeclNode;
+import org.jruby.evaluator.Instruction;
+import org.rubypeople.rdt.internal.core.parser.warnings.RubyLintVisitor;
+
+import com.aptana.rdt.AptanaRDTPlugin;
+
+public class ConstantNamingConvention extends RubyLintVisitor {
+
+ public ConstantNamingConvention(String contents) {
+ super(contents);
+ }
+
+ @Override
+ protected String getOptionKey() {
+ return AptanaRDTPlugin.COMPILER_PB_CONSTANT_NAMING_CONVENTION;
+ }
+
+ @Override
+ public Instruction visitConstDeclNode(ConstDeclNode iVisited) {
+ String name = iVisited.getName();
+ if (!name.toUpperCase().equals(name)) {
+ createProblem(iVisited.getPosition(), "Constant name doesn't match ALL_CAPS_WITH_UNDERSCORES convention: " + name);
+ }
+ return super.visitConstDeclNode(iVisited);
+ }
+
+}
Property changes on: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/ConstantNamingConvention.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java 2007-08-02 15:34:45 UTC (rev 2918)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/parser/warnings/RubyRedLint.java 2007-08-02 17:35:18 UTC (rev 2919)
@@ -82,6 +82,7 @@
visitors.add(new ComparableInclusionVisitor(contents));
visitors.add(new EnumerableInclusionVisitor(contents));
visitors.add(new AndOrUsedOnRighthandAssignment(contents));
+ visitors.add(new ConstantNamingConvention(contents));
return visitors;
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 15:34:46
|
Revision: 2918
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2918&view=rev
Author: cawilliams
Date: 2007-08-02 08:34:45 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
fix #5423 - Outline view shows no content for external files opened via File > Open File...
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/ExternalSourceFolderRoot.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/ExternalSourceFolderRoot.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/ExternalSourceFolderRoot.java 2007-08-02 15:34:39 UTC (rev 2917)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/ExternalSourceFolderRoot.java 2007-08-02 15:34:45 UTC (rev 2918)
@@ -8,6 +8,8 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyModelStatusConstants;
import org.rubypeople.rdt.core.ISourceFolder;
@@ -175,6 +177,11 @@
}
return null;
}
+
+ @Override
+ protected IStatus validateOnLoadpath() { // FIXME This is a HACK. Override so all external roots are said to be on loadpath. This is done so opening external file through File > Open File.. shows content in outline page.
+ return Status.OK_STATUS;
+ }
protected boolean resourceExists() {
if (this.isExternal()) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 15:34:40
|
Revision: 2917
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2917&view=rev
Author: cawilliams
Date: 2007-08-02 08:34:39 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
fix #5423 - Outline view shows no content for external files opened via File > Open File...
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2007-08-02 15:33:36 UTC (rev 2916)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2007-08-02 15:34:39 UTC (rev 2917)
@@ -6,7 +6,9 @@
import java.util.List;
import java.util.Map;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -64,6 +66,7 @@
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.internal.editors.text.JavaFileEditorInput;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.IDocumentProvider;
@@ -77,10 +80,13 @@
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.ISourceFolder;
+import org.rubypeople.rdt.core.ISourceFolderRoot;
import org.rubypeople.rdt.core.ISourceRange;
import org.rubypeople.rdt.core.ISourceReference;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.ExternalRubyScript;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor.ITextConverter;
import org.rubypeople.rdt.internal.ui.search.IOccurrencesFinder;
@@ -347,6 +353,17 @@
* @see org.eclipse.ui.editors.text.TextEditor#doSetInput(org.eclipse.ui.IEditorInput)
*/
protected void doSetInput(IEditorInput input) throws CoreException {
+ if (input instanceof JavaFileEditorInput) {
+ JavaFileEditorInput duh = (JavaFileEditorInput) input;
+ IProject[] projects = RubyCore.getRubyProjects();
+ if (projects != null && projects.length > 0) {
+ IRubyProject proj = RubyCore.create(projects[0]);
+ ISourceFolderRoot root = proj.getSourceFolderRoot(duh.getPath().removeLastSegments(1).toPortableString());
+ ISourceFolder folder = root.getSourceFolder("");
+ IRubyScript script = folder.getRubyScript(duh.getPath().lastSegment());
+ input = new RubyScriptEditorInput((ExternalRubyScript) script);
+ }
+ }
if (input instanceof IRubyScriptEditorInput) {
setDocumentProvider(RubyPlugin.getDefault().getExternalDocumentProvider());
} else {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-02 15:33:37
|
Revision: 2916
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2916&view=rev
Author: cawilliams
Date: 2007-08-02 08:33:36 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-08-01 18:52:24 UTC (rev 2915)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-08-02 15:33:36 UTC (rev 2916)
@@ -165,7 +165,7 @@
private boolean middleOfBlockRightAfterBeginning(String trimmed, String previousLine) {
return middleOfIfRightAfterBeginning(trimmed, previousLine) || middleOfBeginRightAfterBeginning(trimmed, previousLine) || elseRightAfterElsif(trimmed, previousLine)
- || ensureRightAfterRescue(trimmed, previousLine) || whenAfterCase(trimmed, previousLine);
+ || ensureRightAfterRescue(trimmed, previousLine) || whenAfterCase(trimmed, previousLine) || elsifRightAfterElsif(trimmed, previousLine);
}
private boolean middleOfBeginRightAfterBeginning(String trimmed, String previousLine) {
@@ -184,6 +184,10 @@
return previousLine.startsWith("elsif ") && trimmed.equals("else");
}
+ private boolean elsifRightAfterElsif(String trimmed, String previousLine) {
+ return previousLine.startsWith("elsif ") && trimmed.startsWith("elsif ");
+ }
+
private boolean whenAfterCase(String trimmed, String previousLine) {
return previousLine.startsWith("case ") && trimmed.startsWith("when ");
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 18:52:28
|
Revision: 2915
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2915&view=rev
Author: cawilliams
Date: 2007-08-01 11:52:24 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
try to avoid index out of bounds exception
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyPartitionScanner.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyPartitionScanner.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyPartitionScanner.java 2007-08-01 18:52:17 UTC (rev 2914)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyPartitionScanner.java 2007-08-01 18:52:24 UTC (rev 2915)
@@ -205,7 +205,12 @@
private int indexOf(String opening, String string) {
String trimmed = opening.trim();
- int diff = opening.indexOf(trimmed.charAt(0)); // Count leading whitespace
+ int diff;
+ if (trimmed.length() == 0) {
+ diff = opening.length();
+ } else {
+ diff = opening.indexOf(trimmed.charAt(0)); // Count leading whitespace
+ }
int lowest = -1;
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 18:52:18
|
Revision: 2914
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2914&view=rev
Author: cawilliams
Date: 2007-08-01 11:52:17 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
try to handle more cases of indent/de-indenting code
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
Modified: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java 2007-08-01 18:52:12 UTC (rev 2913)
+++ trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java 2007-08-01 18:52:17 UTC (rev 2914)
@@ -67,6 +67,20 @@
"end", d.get());
}
+ public void testHandlesElsifAfterIfProperly() throws Exception {
+ DocumentCommand c = addNewline("def if_else_test\r\n" +
+" if a == true\r\n" +
+" elsif false\r\n" +
+" end\r\n" +
+"end", 49);
+ assertEquals("\r\n ", c.text);
+ assertEquals("def if_else_test\r\n" +
+ " if a == true\r\n" +
+ " elsif false\r\n" +
+ " end\r\n" +
+ "end", d.get());
+ }
+
private DocumentCommand addNewline(String source, int offset) {
RubyAutoIndentStrategy strategy = new RubyAutoIndentStrategy(null, null);
DocumentCommand c = createNewLineCommandAt(offset);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 18:52:13
|
Revision: 2913
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2913&view=rev
Author: cawilliams
Date: 2007-08-01 11:52:12 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
try to handle more cases of indent/de-indenting code
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-08-01 15:29:47 UTC (rev 2912)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-08-01 18:52:12 UTC (rev 2913)
@@ -8,12 +8,13 @@
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.jruby.lexer.yacc.SyntaxException;
import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants;
import org.rubypeople.rdt.internal.core.parser.RubyParser;
import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
@@ -83,37 +84,49 @@
StringBuffer buf= new StringBuffer(c.text + indent);
- IRegion reg= d.getLineInformation(line);
- int lineEnd= reg.getOffset() + reg.getLength();
+ IRegion currentLineRegion= d.getLineInformation(line);
+ int lineEnd= currentLineRegion.getOffset() + currentLineRegion.getLength();
int contentStart= findEndOfWhiteSpace(d, c.offset, lineEnd);
c.length= Math.max(contentStart - c.offset, 0);
- int start= reg.getOffset();
- ITypedRegion region= TextUtilities.getPartition(d, fPartitioning, start, true);
-// if (IRubyPartitions.RUBY_DOC.equals(region.getType()))
-// start= d.getLineInformationOfOffset(region.getOffset()).getOffset();
- // if
- String trimmed = getTrimmedLine(d, start, c.offset);
- if (shouldDeIndent(trimmed)) {
+ int startOfCurrentLine= currentLineRegion.getOffset();
+
+ String trimmed = getTrimmedLine(d, startOfCurrentLine, c.offset);
+ if (mightHaveToShiftCurrentLine(trimmed)) {// check to see if we need to fix the indentation of this line
IRegion previousLineRegion = d.getLineInformation(line - 1);
+ String previousLine = getTrimmedLine(d, previousLineRegion.getOffset(), previousLineRegion.getOffset() + previousLineRegion.getLength());
String previousIndent= indenter.computeIndentation(previousLineRegion.getOffset()).toString();
- // FIXME This all assumes spaces!
- int length = previousIndent.length() - CodeFormatterUtil.createIndentString(1, fProject).length();
+
+ // FIXME This all assumes spaces!
String unindented = "";
- if (length > 0) {
- unindented = previousIndent.substring(0, length);
+ if (middleOfBlockRightAfterBeginning(trimmed, previousLine) ) {
+ unindented = previousIndent;
+ if (whenAfterCase(trimmed, previousLine)) {
+ // add extra indent, dpending upon code formatting option
+ if (RubyCore.getPlugin().getPluginPreferences().getBoolean(DefaultCodeFormatterConstants.FORMATTER_INDENT_CASE_BODY)) {
+ unindented += CodeFormatterUtil.createIndentString(1, fProject);
+ }
+ }
+ } else {
+ int length = previousIndent.length() - CodeFormatterUtil.createIndentString(1, fProject).length();
+ int nextCalculated = nextMeaningfulIndentLength(d, indenter, line);
+ int unit = CodeFormatterUtil.createIndentString(1, fProject).length();
+ if (nextCalculated != -1 && (length > (nextCalculated + unit))) {
+ unindented = previousIndent.substring(0, length - unit);
+ } else {
+ unindented = previousIndent.substring(0, length);
+ }
} // FIXME Deindenting 'end' of case that has indented 'when's comes out incorrectly
- if (length < indent.length()) { // if calculated indent length is less than indent we currently have queued up...
- d.replace(start, c.offset - start, unindented + trimmed); // fix indent of this line
- int shift = previousIndent.length() - unindented.length();
+ if (unindented.length() != indent.length()) { // if calculated indent length is less than indent we currently have queued up...
+ d.replace(startOfCurrentLine, c.offset - startOfCurrentLine, unindented + trimmed); // fix indent of this line
+ int shift = indent.length() - unindented.length();
c.offset = c.offset - shift; // change where we're adding the newline
- if (trimmed.equals(BLOCK_CLOSER)) // if we're closing the block, remove an indent unit
- buf.delete(buf.length() - shift, buf.length());
+ buf.delete(buf.length() - shift, buf.length()); // remove additional indent from being inserted
}
}
// If we're hitting return at the end of the line of a new block, add indent
- if (atStartOfBlock(trimmed)) {
+ if (atIndentPoint(trimmed)) {
buf.append(CodeFormatterUtil.createIndentString(1, fProject));
c.caretOffset= c.offset + buf.length();
c.shiftsCaret= false;
@@ -139,11 +152,57 @@
}
}
- private boolean shouldDeIndent(String trimmed) {
+ private int nextMeaningfulIndentLength(IDocument d, RubyIndenter indenter, int line) throws BadLocationException {
+ for (int i = line + 1; i < d.getNumberOfLines(); i++) {
+ IRegion nextLineRegion = d.getLineInformation(i);
+ String trimmed = getTrimmedLine(d, nextLineRegion.getOffset(), nextLineRegion.getOffset() + nextLineRegion.getLength());
+ if (trimmed == null || trimmed.length() == 0) continue;
+ String nextIndent= indenter.computeIndentation(nextLineRegion.getOffset()).toString();
+ return nextIndent.length();
+ }
+ return -1;
+ }
+
+ private boolean middleOfBlockRightAfterBeginning(String trimmed, String previousLine) {
+ return middleOfIfRightAfterBeginning(trimmed, previousLine) || middleOfBeginRightAfterBeginning(trimmed, previousLine) || elseRightAfterElsif(trimmed, previousLine)
+ || ensureRightAfterRescue(trimmed, previousLine) || whenAfterCase(trimmed, previousLine);
+ }
+
+ private boolean middleOfBeginRightAfterBeginning(String trimmed, String previousLine) {
+ return previousLine.equals("begin") && (trimmed.startsWith("rescue") || trimmed.equals("ensure") || trimmed.equals("rescue"));
+ }
+
+ private boolean middleOfIfRightAfterBeginning(String trimmed, String previousLine) {
+ return previousLine.startsWith("if ") && (trimmed.startsWith("elsif") || trimmed.equals("else"));
+ }
+
+ private boolean ensureRightAfterRescue(String trimmed, String previousLine) {
+ return (previousLine.startsWith("rescue ") || previousLine.equals("rescue")) && trimmed.equals("ensure");
+ }
+
+ private boolean elseRightAfterElsif(String trimmed, String previousLine) {
+ return previousLine.startsWith("elsif ") && trimmed.equals("else");
+ }
+
+ private boolean whenAfterCase(String trimmed, String previousLine) {
+ return previousLine.startsWith("case ") && trimmed.startsWith("when ");
+ }
+
+ private boolean atIndentPoint(String trimmed) {
if (trimmed == null || trimmed.length() == 0) return false;
+ return atStartOfBlock(trimmed) || isMiddleOfBlockKeyword(trimmed);
+ }
+
+ private boolean isMiddleOfBlockKeyword(String trimmed) {
+ if (trimmed == null || trimmed.length() == 0) return false;
return trimmed.equals("rescue") || trimmed.equals("else") || trimmed.equals("ensure")
- || trimmed.equals(BLOCK_CLOSER) || trimmed.startsWith("elsif ");
+ || trimmed.startsWith("elsif ") || trimmed.startsWith("rescue ") || trimmed.startsWith("when ");
}
+
+ private boolean mightHaveToShiftCurrentLine(String trimmed) {
+ if (trimmed == null || trimmed.length() == 0) return false;
+ return isMiddleOfBlockKeyword(trimmed) || trimmed.equals(BLOCK_CLOSER);
+ }
private boolean unclosedBlock(IDocument d, String trimmed, int offset) {
// FIXME wow is this ugly! There has to be an easier way to tell if there's an unclosed block besides parsing and catching a syntaxError!
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 15:29:54
|
Revision: 2912
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2912&view=rev
Author: cawilliams
Date: 2007-08-01 08:29:47 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
be extra careful to avoid null pointers or other runtime exceptiosn with new code for user-defined keywords.
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-08-01 15:27:22 UTC (rev 2911)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java 2007-08-01 15:29:47 UTC (rev 2912)
@@ -231,8 +231,16 @@
private boolean isKeyword(int i) {
if (i >= MIN_KEYWORD && i <= MAX_KEYWORD) return true;
if (i != Tokens.tIDENTIFIER) return false;
- String src = fContents.substring((fOffset - origOffset), (fOffset - origOffset) + fTokenLength);
+ String src;
+ try {
+ src = fContents.substring((fOffset - origOffset), (fOffset - origOffset) + fTokenLength);
+ } catch (RuntimeException e) {
+ RubyPlugin.log(e);
+ return false;
+ }
+ if (src == null || src.trim().length() == 0) return false;
Preferences prefs = RubyPlugin.getDefault().getPluginPreferences();
+ if (prefs == null) return false;
String rawKeywords = prefs.getString(PreferenceConstants.EDITOR_USER_KEYWORDS);
if (rawKeywords == null || rawKeywords.length() == 0) {
return false;
@@ -242,6 +250,7 @@
return false;
}
for (int j = 0; j < keywords.length; j++) {
+ if (keywords[j] == null) continue;
if (keywords[j].equals(src.trim())) return true;
}
return false;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 15:27:27
|
Revision: 2911
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2911&view=rev
Author: cawilliams
Date: 2007-08-01 08:27:22 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
fix #4229 - Allow users to specify tokens to be highlighted like keywords
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/plugin.xml
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java
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/text/ruby/RubyTokenScanner.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordConfigurationBlock.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordInputDialog.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordPreferencePage.java
Modified: trunk/org.rubypeople.rdt.ui/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.ui/plugin.xml 2007-08-01 14:38:26 UTC (rev 2910)
+++ trunk/org.rubypeople.rdt.ui/plugin.xml 2007-08-01 15:27:22 UTC (rev 2911)
@@ -96,6 +96,11 @@
class="org.rubypeople.rdt.internal.ui.preferences.DebuggerPreferencePage"
id="org.rubypeople.rdt.ui.preferences.debugger"
name="%PreferencePage.rdtDebuggerPreferences"/>
+ <page
+ category="org.rubypeople.rdt.ui.preferences.RubyEditorColoringPreferencePage"
+ class="org.rubypeople.rdt.internal.ui.preferences.KeywordPreferencePage"
+ id="org.rubypeople.rdt.ui.preferences.PreferencePageKeyword"
+ name="Keywords"/>
</extension>
<!-- =========================================================================== -->
<!-- Ruby Perspective -->
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordConfigurationBlock.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordConfigurationBlock.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordConfigurationBlock.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * 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.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.internal.ui.dialogs.StatusInfo;
+import org.rubypeople.rdt.internal.ui.util.PixelConverter;
+import org.rubypeople.rdt.internal.ui.wizards.IStatusChangeListener;
+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;
+import org.rubypeople.rdt.internal.ui.wizards.dialogfields.ListDialogField;
+import org.rubypeople.rdt.ui.PreferenceConstants;
+
+/**
+ */
+public class KeywordConfigurationBlock extends OptionsConfigurationBlock {
+
+ private static final Key PREF_COMPILER_TASK_TAGS= getRDTUIKey(PreferenceConstants.EDITOR_USER_KEYWORDS);
+
+ private static final String ENABLED= RubyCore.ENABLED;
+ private static final String DISABLED= RubyCore.DISABLED;
+
+ public static class Keyword {
+ public String name;
+ }
+
+ private class KeywordLabelProvider extends LabelProvider implements ITableLabelProvider, IFontProvider {
+
+ public KeywordLabelProvider() {
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ return null; // RubyPluginImages.get(RubyPluginImages.IMG_OBJS_REFACTORING_INFO);
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return getColumnText(element, 0);
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ Keyword task= (Keyword) element;
+ if (columnIndex == 0) {
+ return task.name;
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object)
+ */
+ public Font getFont(Object element) {
+ return null;
+ }
+ }
+
+ private static class TodoTaskSorter extends ViewerSorter {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ return collator.compare(((Keyword) e1).name, ((Keyword) e2).name);
+ }
+ }
+
+ private static final int IDX_ADD= 0;
+ private static final int IDX_EDIT= 1;
+ private static final int IDX_REMOVE= 2;
+
+ private IStatus fTaskTagsStatus;
+ private ListDialogField fTodoTasksList;
+
+
+ public KeywordConfigurationBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) {
+ super(context, project, getKeys(), container);
+
+ KeywordAdapter adapter= new KeywordAdapter();
+ String[] buttons= new String[] {
+ PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_add_button,
+ PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_edit_button,
+ PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_remove_button
+ };
+ fTodoTasksList= new ListDialogField(adapter, buttons, new KeywordLabelProvider());
+ fTodoTasksList.setDialogFieldListener(adapter);
+ fTodoTasksList.setRemoveButtonIndex(IDX_REMOVE);
+
+ String[] columnsHeaders= new String[] {
+ PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_name_column
+ };
+
+ fTodoTasksList.setTableColumns(new ListDialogField.ColumnsDescription(columnsHeaders, true));
+ fTodoTasksList.setViewerSorter(new TodoTaskSorter());
+
+ unpackTodoTasks();
+ if (fTodoTasksList.getSize() > 0) {
+ fTodoTasksList.selectFirstElement();
+ } else {
+ fTodoTasksList.enableButton(IDX_EDIT, false);
+ }
+
+ fTaskTagsStatus= new StatusInfo();
+ }
+
+ public void setEnabled(boolean isEnabled) {
+ fTodoTasksList.setEnabled(isEnabled);
+ }
+
+ private static Key[] getKeys() {
+ return new Key[] {
+ PREF_COMPILER_TASK_TAGS
+ };
+ }
+
+ public class KeywordAdapter implements IListAdapter, IDialogFieldListener {
+
+ private boolean canEdit(List selectedElements) {
+ return selectedElements.size() == 1;
+ }
+
+ public void customButtonPressed(ListDialogField field, int index) {
+ doTodoButtonPressed(index);
+ }
+
+ public void selectionChanged(ListDialogField field) {
+ List selectedElements= field.getSelectedElements();
+ field.enableButton(IDX_EDIT, canEdit(selectedElements));
+ }
+
+ public void doubleClicked(ListDialogField field) {
+ if (canEdit(field.getSelectedElements())) {
+ doTodoButtonPressed(IDX_EDIT);
+ }
+ }
+
+ public void dialogFieldChanged(DialogField field) {
+ updateModel(field);
+ }
+
+ }
+
+ protected Control createContents(Composite parent) {
+ setShell(parent.getShell());
+
+ Composite markersComposite= createMarkersTabContent(parent);
+
+ validateSettings(null, null, null);
+
+ return markersComposite;
+ }
+
+ private Composite createMarkersTabContent(Composite folder) {
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 2;
+
+ PixelConverter conv= new PixelConverter(folder);
+
+ Composite markersComposite= new Composite(folder, SWT.NULL);
+ markersComposite.setLayout(layout);
+ markersComposite.setFont(folder.getFont());
+
+ GridData data= new GridData(GridData.FILL_BOTH);
+ data.widthHint= conv.convertWidthInCharsToPixels(50);
+ Control listControl= fTodoTasksList.getListControl(markersComposite);
+ listControl.setLayoutData(data);
+
+ Control buttonsControl= fTodoTasksList.getButtonBox(markersComposite);
+ buttonsControl.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
+
+ return markersComposite;
+ }
+
+ protected void validateSettings(Key changedKey, String oldValue, String newValue) {
+ if (!areSettingsEnabled()) {
+ return;
+ }
+
+ if (changedKey != null) {
+ if (PREF_COMPILER_TASK_TAGS.equals(changedKey)) {
+ fTaskTagsStatus= validateTaskTags();
+ } else {
+ return;
+ }
+ } else {
+ fTaskTagsStatus= validateTaskTags();
+ }
+ IStatus status= fTaskTagsStatus; //StatusUtil.getMostSevere(new IStatus[] { fTaskTagsStatus });
+ fContext.statusChanged(status);
+ }
+
+ private IStatus validateTaskTags() {
+ return new StatusInfo();
+ }
+
+ protected final void updateModel(DialogField field) {
+ if (field == fTodoTasksList) {
+ StringBuffer tags= new StringBuffer();
+ List list= fTodoTasksList.getElements();
+ for (int i= 0; i < list.size(); i++) {
+ if (i > 0) {
+ tags.append(',');
+ }
+ Keyword elem= (Keyword) list.get(i);
+ tags.append(elem.name);
+ }
+ setValue(PREF_COMPILER_TASK_TAGS, tags.toString());
+ validateSettings(PREF_COMPILER_TASK_TAGS, null, null);
+ }
+ }
+
+ protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
+ return null;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
+ */
+ protected void updateControls() {
+ unpackTodoTasks();
+ }
+
+ private void unpackTodoTasks() {
+ String currTags= getValue(PREF_COMPILER_TASK_TAGS);
+ String[] tags= getTokens(currTags, ","); //$NON-NLS-1$
+ ArrayList elements= new ArrayList(tags.length);
+ for (int i= 0; i < tags.length; i++) {
+ Keyword task= new Keyword();
+ task.name= tags[i].trim();
+ elements.add(task);
+ }
+ fTodoTasksList.setElements(elements);
+
+ }
+
+ private void doTodoButtonPressed(int index) {
+ Keyword edited= null;
+ if (index != IDX_ADD) {
+ edited= (Keyword) fTodoTasksList.getSelectedElements().get(0);
+ }
+ if (index == IDX_ADD || index == IDX_EDIT) {
+ KeywordInputDialog dialog= new KeywordInputDialog(getShell(), edited, fTodoTasksList.getElements());
+ if (dialog.open() == Window.OK) {
+ if (edited != null) {
+ fTodoTasksList.replaceElement(edited, dialog.getResult());
+ } else {
+ fTodoTasksList.addElement(dialog.getResult());
+ }
+ }
+ }
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordConfigurationBlock.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordInputDialog.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordInputDialog.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordInputDialog.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.rubypeople.rdt.internal.ui.dialogs.StatusDialog;
+import org.rubypeople.rdt.internal.ui.dialogs.StatusInfo;
+import org.rubypeople.rdt.internal.ui.preferences.KeywordConfigurationBlock.Keyword;
+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.LayoutUtil;
+import org.rubypeople.rdt.internal.ui.wizards.dialogfields.StringDialogField;
+
+/**
+ * Dialog to enter a new keyword
+ */
+public class KeywordInputDialog extends StatusDialog {
+
+ private class KeywordInputAdapter implements IDialogFieldListener {
+ public void dialogFieldChanged(DialogField field) {
+ doValidation();
+ }
+ }
+
+ private StringDialogField fNameDialogField;
+
+ private List fExistingNames;
+
+ public KeywordInputDialog(Shell parent, Keyword task, List existingEntries) {
+ super(parent);
+
+ fExistingNames= new ArrayList(existingEntries.size());
+ for (int i= 0; i < existingEntries.size(); i++) {
+ Keyword curr= (Keyword) existingEntries.get(i);
+ if (!curr.equals(task)) {
+ fExistingNames.add(curr.name);
+ }
+ }
+
+ if (task == null) {
+ setTitle(PreferencesMessages.KeywordInputDialog_new_title);
+ } else {
+ setTitle(PreferencesMessages.KeywordInputDialog_edit_title);
+ }
+
+ KeywordInputAdapter adapter= new KeywordInputAdapter();
+
+ fNameDialogField= new StringDialogField();
+ fNameDialogField.setLabelText(PreferencesMessages.KeywordInputDialog_name_label);
+ fNameDialogField.setDialogFieldListener(adapter);
+
+ fNameDialogField.setText((task != null) ? task.name : ""); //$NON-NLS-1$
+ }
+
+ public Keyword getResult() {
+ Keyword task= new Keyword();
+ task.name= fNameDialogField.getText().trim();
+ return task;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite= (Composite) super.createDialogArea(parent);
+
+ Composite inner= new Composite(composite, SWT.NONE);
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 2;
+ inner.setLayout(layout);
+
+ fNameDialogField.doFillIntoGrid(inner, 2);
+
+ LayoutUtil.setHorizontalGrabbing(fNameDialogField.getTextControl(null));
+ LayoutUtil.setWidthHint(fNameDialogField.getTextControl(null), convertWidthInCharsToPixels(45));
+
+ fNameDialogField.postSetFocusOnDialogField(parent.getDisplay());
+
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ private void doValidation() {
+ StatusInfo status= new StatusInfo();
+ String newText= fNameDialogField.getText();
+ if (newText.length() == 0) {
+ status.setError(PreferencesMessages.KeywordInputDialog_error_enterName);
+ } else {
+ if (newText.indexOf(',') != -1) {
+ status.setError(PreferencesMessages.KeywordInputDialog_error_comma);
+ } else if (fExistingNames.contains(newText)) {
+ status.setError(PreferencesMessages.KeywordInputDialog_error_entryExists);
+ } else if (Character.isWhitespace(newText.charAt(0)) || Character.isWhitespace(newText.charAt(newText.length() - 1))) {
+ status.setError(PreferencesMessages.KeywordInputDialog_error_noSpace);
+ }
+ }
+ updateStatus(status);
+ }
+
+ /*
+ * @see org.eclipse.jface.window.Window#configureShell(Shell)
+ */
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ // FIXME Uncomment for help context!
+ //WorkbenchHelp.setHelp(newShell, IJavaHelpContextIds.TODO_TASK_INPUT_DIALOG);
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordInputDialog.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordPreferencePage.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordPreferencePage.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordPreferencePage.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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.preferences;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+
+/*
+ * The page to configure the task tags
+ */
+public class KeywordPreferencePage extends PropertyAndPreferencePage {
+
+ public static final String PREF_ID= "org.rubypeople.rdt.ui.preferences.KeywordPreferencePage"; //$NON-NLS-1$
+ public static final String PROP_ID= "org.rubypeople.rdt.ui.propertyPages.KeywordPreferencePage"; //$NON-NLS-1$
+
+ private KeywordConfigurationBlock fConfigurationBlock;
+
+ public KeywordPreferencePage() {
+ setPreferenceStore(RubyPlugin.getDefault().getPreferenceStore());
+ setDescription(PreferencesMessages.KeywordPreferencePage_description);
+
+ // only used when page is shown programatically
+ setTitle(PreferencesMessages.KeywordPreferencePage_title);
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ IWorkbenchPreferenceContainer container= (IWorkbenchPreferenceContainer) getContainer();
+ fConfigurationBlock= new KeywordConfigurationBlock(getNewStatusChangedListener(), getProject(), container);
+
+ super.createControl(parent);
+
+// if (isProjectPreferencePage()) {
+// PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IRubyHelpContextIds.KEYWORD_PROPERTY_PAGE);
+// } else {
+// PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IRubyHelpContextIds.KEYWORD_PREFERENCE_PAGE);
+// }
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#createPreferenceContent(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createPreferenceContent(Composite composite) {
+ return fConfigurationBlock.createContents(composite);
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#hasProjectSpecificOptions(org.eclipse.core.resources.IProject)
+ */
+ protected boolean hasProjectSpecificOptions(IProject project) {
+ return fConfigurationBlock.hasProjectSpecificOptions(project);
+ }
+
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#getPreferencePageID()
+ */
+ protected String getPreferencePageID() {
+ return PREF_ID;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#getPropertyPageID()
+ */
+ protected String getPropertyPageID() {
+ return PROP_ID;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean)
+ */
+ protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) {
+ super.enableProjectSpecificSettings(useProjectSpecificSettings);
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.useProjectSpecificSettings(useProjectSpecificSettings);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ super.performDefaults();
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.performDefaults();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ if (fConfigurationBlock != null && !fConfigurationBlock.performOk()) {
+ return false;
+ }
+ return super.performOk();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performApply()
+ */
+ public void performApply() {
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.performApply();
+ }
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jface.dialogs.DialogPage#dispose()
+ */
+ public void dispose() {
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.dispose();
+ }
+ super.dispose();
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage#setElement(org.eclipse.core.runtime.IAdaptable)
+ */
+ public void setElement(IAdaptable element) {
+ super.setElement(element);
+ setDescription(null); // no description for property page
+ }
+
+
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/KeywordPreferencePage.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java 2007-08-01 14:38:26 UTC (rev 2910)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -182,6 +182,15 @@
public static String NewRubyProjectPreferencePage_folders_error_invalidcp;
public static String NewRubyProjectPreferencePage_folders_error_invalidsrcname;
public static String NewRubyProjectPreferencePage_folders_error_namesempty;
+ public static String KeywordPreferencePage_description;
+ public static String KeywordPreferencePage_title;
+ public static String KeywordInputDialog_new_title;
+ public static String KeywordInputDialog_edit_title;
+ public static String KeywordInputDialog_name_label;
+ public static String KeywordInputDialog_error_enterName;
+ public static String KeywordInputDialog_error_comma;
+ public static String KeywordInputDialog_error_entryExists;
+ public static String KeywordInputDialog_error_noSpace;
static {
NLS.initializeMessages(BUNDLE_NAME, PreferencesMessages.class);
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-08-01 14:38:26 UTC (rev 2910)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties 2007-08-01 15:27:22 UTC (rev 2911)
@@ -32,7 +32,7 @@
TodoTaskConfigurationBlock_needsbuild_title=Task Tags Settings Changed
TodoTaskConfigurationBlock_tasks_default={0} (default)
-TodoTaskConfigurationBlock_needsfullbuild_message=The task tags settings have changed. A full rebuild is required to for changes to take effect. Do the full build now?
+TodoTaskConfigurationBlock_needsfullbuild_message=The task tags settings have changed. A full rebuild is required for changes to take effect. Do the full build now?
TodoTaskConfigurationBlock_needsprojectbuild_message=The task tags settings have changed. A rebuild of the project is required for changes to take effect. Build the project now?
TodoTaskInputDialog_new_title=New Task Tag
@@ -47,6 +47,17 @@
TodoTaskInputDialog_error_entryExists=An entry with the same name already exists.
TodoTaskInputDialog_error_noSpace=Name cannot begin or end with a whitespace.
+KeywordPreferencePage_title=Keywords
+KeywordPreferencePage_description=&Strings indicating user defined keywords for syntax coloring purposes.
+
+KeywordInputDialog_new_title=New Keyword
+KeywordInputDialog_edit_title=Edit Keyword
+KeywordInputDialog_name_label=Keyword:
+KeywordInputDialog_error_enterName=Enter keyword.
+KeywordInputDialog_error_comma=Keyword cannot contain a comma.
+KeywordInputDialog_error_entryExists=An entry with the same keyword already exists.
+KeywordInputDialog_error_noSpace=Keyword cannot begin or end with a space.
+
MembersOrderPreferencePage_category_button_up=&Up
MembersOrderPreferencePage_category_button_down=D&own
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-08-01 14:38:26 UTC (rev 2910)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyTokenScanner.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.io.StringReader;
+import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
@@ -19,6 +20,7 @@
import org.jruby.parser.Tokens;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants;
+import org.rubypeople.rdt.ui.PreferenceConstants;
import org.rubypeople.rdt.ui.text.IColorManager;
public class RubyTokenScanner extends AbstractRubyTokenScanner {
@@ -227,7 +229,22 @@
}
private boolean isKeyword(int i) {
- return (i >= MIN_KEYWORD && i <= MAX_KEYWORD);
+ if (i >= MIN_KEYWORD && i <= MAX_KEYWORD) return true;
+ if (i != Tokens.tIDENTIFIER) return false;
+ String src = fContents.substring((fOffset - origOffset), (fOffset - origOffset) + fTokenLength);
+ Preferences prefs = RubyPlugin.getDefault().getPluginPreferences();
+ String rawKeywords = prefs.getString(PreferenceConstants.EDITOR_USER_KEYWORDS);
+ if (rawKeywords == null || rawKeywords.length() == 0) {
+ return false;
+ }
+ String[] keywords = rawKeywords.split(",");
+ if (keywords == null || keywords.length == 0) {
+ return false;
+ }
+ for (int j = 0; j < keywords.length; j++) {
+ if (keywords[j].equals(src.trim())) return true;
+ }
+ return false;
}
public void setRange(IDocument document, int offset, int length) {
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java 2007-08-01 14:38:26 UTC (rev 2910)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java 2007-08-01 15:27:22 UTC (rev 2911)
@@ -680,6 +680,16 @@
* @since 0.9.0
*/
public static final String EDITOR_MARK_METHOD_EXIT_POINTS = "markMethodExitPoints"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds user defined "keywords".
+ * <p>
+ * Value is of type <code>String</code>.
+ * </p>
+ *
+ * @since 1.0
+ */
+ public static final String EDITOR_USER_KEYWORDS = "userDefinedKeywords"; //$NON-NLS-1$
/**
@@ -807,6 +817,7 @@
store.setDefault(LOADPATH_RUBYVMLIBRARY_INDEX, 0);
store.setDefault(PreferenceConstants.EDITOR_SHOW_SEGMENTS, false);
+ store.setDefault(PreferenceConstants.EDITOR_USER_KEYWORDS, "");
// FIXME We can't enabling using code formatter yet, because it breaks
// on formatting templates (when inserting via content assist)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-08-01 14:38:31
|
Revision: 2910
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2910&view=rev
Author: cawilliams
Date: 2007-08-01 07:38:26 -0700 (Wed, 01 Aug 2007)
Log Message:
-----------
use 'ruby' executable, not 'rubyw' (to avoid popup window). Refactor common code
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-07-31 23:43:32 UTC (rev 2909)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-08-01 14:38:26 UTC (rev 2910)
@@ -205,16 +205,18 @@
}
protected File getCachedIndex() {
- IPath location = RubyPlugin.getDefault().getStateLocation();
- location = location.append("ri.index");
- return location.toFile();
+ return getStateFile("ri.index");
}
protected File getFRIIndexFile() {
- IPath location = RubyPlugin.getDefault().getStateLocation();
- location = location.append(".fastri-index");
+ return getStateFile(".fastri-index");
+ }
+
+ private File getStateFile(String name) {
+ IPath location = RubyPlugin.getDefault().getStateLocation();
+ location = location.append(name);
return location.toFile();
- }
+ }
private synchronized void initSearchList() {
File file = getCachedIndex();
@@ -356,12 +358,17 @@
}
private String execAndReadOutput(String file, List<String> commands) {
if (file == null) return null;
- StringBuffer buffer;
+ StringBuffer buffer = new StringBuffer();
try {
List<String> line = new ArrayList<String>();
IVMInstall vm = RubyRuntime.getDefaultVMInstall();
if (vm == null) return "";
File executable = StandardVMType.findRubyExecutable(vm.getInstallLocation());
+ if (executable.getName().contains("rubyw")) {
+ String name = executable.getName();
+ name = name.replace("rubyw", "ruby");
+ executable = new File(executable.getParent() + File.separator + name);
+ }
line.add(executable.getAbsolutePath());
line.add(file);
for (String command : commands) {
@@ -372,8 +379,7 @@
cmdLine = line.toArray(cmdLine);
Process p = DebugPlugin.exec(cmdLine, workingDirectory);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String liner = null;
- buffer = new StringBuffer();
+ String liner = null;
while ((liner = reader.readLine()) != null) {
buffer.append(liner);
buffer.append("\n");
@@ -381,13 +387,16 @@
Thread.yield();
}
}
+ p.waitFor();
} catch (CoreException e) {
AptanaRDTPlugin.log(e);
return "";
} catch (IOException e) {
AptanaRDTPlugin.log(e);
return "";
- }
+ } catch (InterruptedException e) {
+ AptanaRDTPlugin.log(e);
+ }
buffer.deleteCharAt(buffer.length() - 1); // remove last \n
return buffer.toString();
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 23:43:34
|
Revision: 2909
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2909&view=rev
Author: cawilliams
Date: 2007-07-31 16:43:32 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
while looping through stream reader, if reader isn't ready yield so we don't just immediately block
Modified Paths:
--------------
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/core/gems/GemManager.java
Modified: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/core/gems/GemManager.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/core/gems/GemManager.java 2007-07-31 23:42:51 UTC (rev 2908)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/core/gems/GemManager.java 2007-07-31 23:43:32 UTC (rev 2909)
@@ -324,6 +324,9 @@
while ((liner = reader.readLine()) != null) {
buffer.append(liner);
buffer.append("\n");
+ if (!reader.ready()) { // if the reader isn't ready, yield so we don't keep blocking here
+ Thread.yield();
+ }
}
} catch (CoreException e) {
AptanaRDTPlugin.log(e);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 23:42:53
|
Revision: 2908
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2908&view=rev
Author: cawilliams
Date: 2007-07-31 16:42:51 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
when user forces refresh of view, clear cache before reloading (so we don't just load up the exact same cached contents).
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-07-31 23:37:00 UTC (rev 2907)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-07-31 23:42:51 UTC (rev 2908)
@@ -158,6 +158,7 @@
private void contributeToActionBars() {
IAction refreshAction = new Action() {
public void run() {
+ clearCache();
updatePage();
}
};
@@ -169,7 +170,14 @@
manager.add(refreshAction);
}
- private void updatePage() {
+ protected void clearCache() {
+ File index = getCachedIndex();
+ if (index != null) {
+ index.delete();
+ }
+ }
+
+ private void updatePage() {
initSearchList();
Display.getDefault().asyncExec(new Runnable () {
public void run () {
@@ -416,27 +424,24 @@
protected void handleOutput(final String content) {
if (content == null)
return;
-// try {
- buffer = new StringBuffer();
- buffer.append(content.replace("\n", "<br/>"));
- buffer.insert(0, HEADER); // Put the header before all the contents
- buffer.append(TAIL); // Put the body and html close tags at end
- final String text = buffer.toString();
- Display.getDefault().syncExec(new Runnable() {
- public void run() {
- searchResult.setText(text);
- }
- });
-// } catch (IOException ioe) {
-// ioe.printStackTrace();
-// }
+ buffer = new StringBuffer();
+ buffer.append(content.replace("\n", "<br/>"));
+ buffer.insert(0, HEADER); // Put the header before all the contents
+ buffer.append(TAIL); // Put the body and html close tags at end
+ final String text = buffer.toString();
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ searchResult.setText(text);
+ }
+ });
}
}
/**
- * When teh rdoc has changed, automatically update/regenerate the view
+ * When the rdoc has changed, automatically update/regenerate the view
*/
public void rdocChanged() {
+ clearCache();
updatePage();
}
@@ -517,6 +522,7 @@
}
public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) {
+ clearCache();
updatePage();
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 23:37:01
|
Revision: 2907
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2907&view=rev
Author: cawilliams
Date: 2007-07-31 16:37:00 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
Modify RI view to use fastri under the covers, and to cache the listing of all classes/methods/modules
Modified Paths:
--------------
trunk/org.rubypeople.rdt.launching/build.properties
trunk/org.rubypeople.rdt.launching/plugin.xml
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/RubyRuntime.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.launching/ruby/fastri/
trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_index.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_indexer.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/name_descriptor.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_index.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_service.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/util.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri/version.rb
trunk/org.rubypeople.rdt.launching/ruby/fastri-server
trunk/org.rubypeople.rdt.launching/ruby/fri
Modified: trunk/org.rubypeople.rdt.launching/build.properties
===================================================================
--- trunk/org.rubypeople.rdt.launching/build.properties 2007-07-31 23:36:45 UTC (rev 2906)
+++ trunk/org.rubypeople.rdt.launching/build.properties 2007-07-31 23:37:00 UTC (rev 2907)
@@ -1,10 +1,21 @@
bin.includes = plugin.xml,\
plugin.properties,\
- ruby/*,\
launching.jar,\
.options,\
- META-INF/
+ META-INF/,\
+ ruby/,\
+ schema/
plugin = org.rubypeople.rdt.launching
plugin.name = launching
plugin.classpath = ../org.eclipse.core.runtime/runtime.jar;../org.eclipse.core.resources/resources.jar;../org.eclipse.core.boot/boot.jar;../org.eclipse.debug.core/dtcore.jar;../org.eclipse.ui/workbench.jar;../org.apache.xerces/xmlParserAPIs.jar;../org.rubypeople.rdt.core/bin;../org.rubypeople.rdt.debug.core/bin;
source.launching.jar = src/
+src.includes = ruby/,\
+ schema/,\
+ src/,\
+ plugin.xml,\
+ plugin.properties,\
+ build.properties,\
+ META-INF/,\
+ .project,\
+ .loadpath,\
+ .classpath
Modified: trunk/org.rubypeople.rdt.launching/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.launching/plugin.xml 2007-07-31 23:36:45 UTC (rev 2906)
+++ trunk/org.rubypeople.rdt.launching/plugin.xml 2007-07-31 23:37:00 UTC (rev 2907)
@@ -19,10 +19,18 @@
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
- name="%LaunchConfigurationTypeRubyApplication.name"
delegate="org.rubypeople.rdt.launching.RubyLaunchDelegate"
+ id="org.rubypeople.rdt.launching.LaunchConfigurationTypeRubyApplication"
modes="run,debug"
- id="org.rubypeople.rdt.launching.LaunchConfigurationTypeRubyApplication">
+ name="%LaunchConfigurationTypeRubyApplication.name"
+ public="true"
+ sourceLocatorId="org.rubypeople.rdt.debug.ui.rubySourceLocator">
+ <fileExtension
+ default="true"
+ extension="rb"/>
+ <fileExtension
+ default="true"
+ extension="rbw"/>
</launchConfigurationType>
</extension>
<extension
@@ -63,6 +71,6 @@
id="org.rubypeople.rdt.launching.loadpathentry.variableLoadpathEntry"
class="org.rubypeople.rdt.internal.launching.VariableLoadpathEntry">
</runtimeLoadpathEntry>
- </extension>
+ </extension>
</plugin>
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_index.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_index.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_index.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,245 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+
+require 'fastri/full_text_indexer'
+require 'stringio'
+
+module FastRI
+
+class FullTextIndex
+ MAX_QUERY_SIZE = 20
+ MAX_REGEXP_MATCH_SIZE = 255
+ class Result
+ attr_reader :path, :query, :index, :metadata
+
+ def initialize(searcher, query, index, path, metadata)
+ @searcher = searcher
+ @index = index
+ @query = query
+ @path = path
+ @metadata = metadata
+ end
+
+ def context(size)
+ @searcher.fetch_data(@index, 2*size+1, -size)
+ end
+
+ def text(size)
+ @searcher.fetch_data(@index, size, 0)
+ end
+ end
+
+ class << self; private :new end
+
+ DEFAULT_OPTIONS = {
+ :max_query_size => MAX_QUERY_SIZE,
+ }
+
+ def self.new_from_ios(fulltext_IO, suffix_arrray_IO, options = {})
+ new(:io, fulltext_IO, suffix_arrray_IO, options)
+ end
+
+ def self.new_from_filenames(fulltext_fname, suffix_arrray_fname, options = {})
+ new(:filenames, fulltext_fname, suffix_arrray_fname, options)
+ end
+
+ attr_reader :max_query_size
+ def initialize(type, fulltext, sarray, options)
+ options = DEFAULT_OPTIONS.merge(options)
+ case type
+ when :io
+ @fulltext_IO = fulltext
+ @sarray_IO = sarray
+ when :filenames
+ @fulltext_fname = fulltext
+ @sarray_fname = sarray
+ else raise "Unknown type"
+ end
+ @type = type
+ @max_query_size = options[:max_query_size]
+ check_magic
+ end
+
+ def lookup(term)
+ get_fulltext_IO do |fulltextIO|
+ get_sarray_IO do |sarrayIO|
+ case sarrayIO
+ when StringIO
+ num_suffixes = sarrayIO.string.size / 4 - 1
+ else
+ num_suffixes = sarrayIO.stat.size / 4 - 1
+ end
+
+ index, offset = binary_search(sarrayIO, fulltextIO, term, 0, num_suffixes)
+ if offset
+ fulltextIO.pos = offset
+ path, metadata = find_metadata(fulltextIO)
+ return Result.new(self, term, index, path, metadata) if path
+ else
+ nil
+ end
+ end
+ end
+ end
+
+ def next_match(result, term_or_regexp = "")
+ case term_or_regexp
+ when String; size = [result.query.size, term_or_regexp.size].max
+ when Regexp; size = MAX_REGEXP_MATCH_SIZE
+ end
+ get_fulltext_IO do |fulltextIO|
+ get_sarray_IO do |sarrayIO|
+ idx = result.index
+ loop do
+ idx += 1
+ str = get_string(sarrayIO, fulltextIO, idx, size)
+ upto = str.index("\0")
+ str = str[0, upto] if upto
+ break unless str.index(result.query) == 0
+ if str[term_or_regexp]
+ fulltextIO.pos = index_to_offset(sarrayIO, idx)
+ path, metadata = find_metadata(fulltextIO)
+ return Result.new(self, result.query, idx, path, metadata) if path
+ end
+ end
+ end
+ end
+ end
+
+ def next_matches(result, term_or_regexp = "")
+ case term_or_regexp
+ when String; size = [result.query.size, term_or_regexp.size].max
+ when Regexp; size = MAX_REGEXP_MATCH_SIZE
+ end
+ ret = []
+ get_fulltext_IO do |fulltextIO|
+ get_sarray_IO do |sarrayIO|
+ idx = result.index
+ loop do
+ idx += 1
+ str = get_string(sarrayIO, fulltextIO, idx, size)
+ upto = str.index("\0")
+ str = str[0, upto] if upto
+ break unless str.index(result.query) == 0
+ if str[term_or_regexp]
+ fulltextIO.pos = index_to_offset(sarrayIO, idx)
+ path, metadata = find_metadata(fulltextIO)
+ ret << Result.new(self, result.query, idx, path, metadata) if path
+ end
+ end
+ end
+ end
+
+ ret
+ end
+
+ def fetch_data(index, size, offset = 0)
+ raise "Bad offset" unless offset <= 0
+ get_fulltext_IO do |fulltextIO|
+ get_sarray_IO do |sarrayIO|
+ base = index_to_offset(sarrayIO, index)
+ actual_offset = offset
+ newsize = size
+ if base + offset < 0 # at the beginning
+ excess = (base + offset).abs # remember offset is < 0
+ newsize = size - excess
+ actual_offset = offset + excess
+ end
+ str = get_string(sarrayIO, fulltextIO, index, newsize, offset)
+ from = (str.rindex("\0", -actual_offset) || -1) + 1
+ to = (str.index("\0", -actual_offset) || 0) - 1
+ str[from..to]
+ end
+ end
+ end
+
+ private
+ def check_magic
+ get_fulltext_IO do |io|
+ io.rewind
+ header = io.read(FullTextIndexer::MAGIC.size)
+ raise "Unsupported index format." unless header
+ version = header[/\d+\.\d+\.\d+/]
+ raise "Unsupported index format." unless version
+ major, minor, teeny = version.scan(/\d+/)
+ if major != FASTRI_FT_INDEX_FORMAT_MAJOR or
+ minor > FASTRI_FT_INDEX_FORMAT_MINOR
+ raise "Unsupported index format"
+ end
+ end
+ end
+
+ def get_fulltext_IO
+ case @type
+ when :io; yield @fulltext_IO
+ when :filenames
+ File.open(@fulltext_fname, "rb"){|f| yield f}
+ end
+ end
+
+ def get_sarray_IO
+ case @type
+ when :io; yield @sarray_IO
+ when :filenames
+ File.open(@sarray_fname, "rb"){|f| yield f}
+ end
+ end
+
+ def index_to_offset(sarrayIO, index)
+ sarrayIO.pos = index * 4
+ sarrayIO.read(4).unpack("V")[0]
+ end
+
+ def find_metadata(fulltextIO)
+ oldtext = ""
+ loop do
+ text = fulltextIO.read(4096)
+ break unless text
+ if idx = text.index("\0")
+ if idx + 4 >= text.size
+ text.concat(fulltextIO.read(4096))
+ end
+ len = text[idx+1, 4].unpack("V")[0]
+ missing = idx + 5 + len - text.size
+ if missing > 0
+ text.concat(fulltextIO.read(missing))
+ end
+ footer = text[idx + 5, len - 1]
+ path, metadata = /(.*?)\0(.*)/m.match(footer).captures
+ return [path, Marshal.load(metadata)]
+ end
+ oldtext = text
+ end
+ nil
+ end
+
+ def get_string(sarrayIO, fulltextIO, index, size, off = 0)
+ sarrayIO.pos = index * 4
+ offset = sarrayIO.read(4).unpack("V")[0]
+ fulltextIO.pos = [offset + off, 0].max
+ fulltextIO.read(size)
+ end
+
+ def binary_search(sarrayIO, fulltextIO, term, from, to)
+ #puts "BINARY #{from} -- #{to}"
+ #left = get_string(sarrayIO, fulltextIO, from, @max_query_size)
+ #right = get_string(sarrayIO, fulltextIO, to, @max_query_size)
+ #puts " #{left.inspect} -- #{right.inspect}"
+ middle = (from + to) / 2
+ pivot = get_string(sarrayIO, fulltextIO, middle, @max_query_size)
+ if from == to
+ if pivot.index(term) == 0
+ sarrayIO.pos = middle * 4
+ [middle, sarrayIO.read(4).unpack("V")[0]]
+ else
+ nil
+ end
+ elsif term <= pivot
+ binary_search(sarrayIO, fulltextIO, term, from, middle)
+ elsif term > pivot
+ binary_search(sarrayIO, fulltextIO, term, middle+1, to)
+ end
+ end
+end # class FullTextIndex
+
+end # module FastRI
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_index.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_indexer.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_indexer.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_indexer.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,100 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+
+require 'fastri/version'
+
+module FastRI
+
+class FullTextIndexer
+ WORD_RE = /[A-Za-z0-9_]+/
+ NONWORD_RE = /[^A-Za-z0-9_]+/
+ MAGIC = "FastRI full-text index #{FASTRI_FT_INDEX_FORMAT}\0"
+
+ def initialize(max_querysize)
+ @documents = []
+ @doc_hash = {}
+ @max_wordsize = max_querysize
+ end
+
+ def add_document(name, data, metadata = {})
+ @doc_hash[name] = [data, metadata.merge(:size => data.size)]
+ @documents << name
+ end
+
+ def data(name)
+ @doc_hash[name][0]
+ end
+
+ def documents
+ @documents = @documents.uniq
+ end
+
+ def preprocess(str)
+ str.gsub(/\0/,"")
+ end
+
+ require 'strscan'
+ def find_suffixes(text, offset)
+ find_suffixes_simple(text, WORD_RE, NONWORD_RE, offset)
+ end
+
+ def find_suffixes_simple(string, word_re, nonword_re, offset)
+ suffixes = []
+ sc = StringScanner.new(string)
+ until sc.eos?
+ sc.skip(nonword_re)
+ len = string.size
+ loop do
+ break if sc.pos == len
+ suffixes << offset + sc.pos
+ skipped_word = sc.skip(word_re)
+ break unless skipped_word
+ loop do
+ skipped_nonword = sc.skip(nonword_re)
+ break unless skipped_nonword
+ end
+ end
+ end
+ suffixes
+ end
+
+ require 'enumerator'
+ def build_index(full_text_IO, suffix_array_IO)
+ fulltext = ""
+ io = StringIO.new(fulltext)
+ io.write MAGIC
+ full_text_IO.write MAGIC
+ documents.each do |doc|
+ data, metadata = @doc_hash[doc]
+ io.write(data)
+ full_text_IO.write(data)
+ meta_txt = Marshal.dump(metadata)
+ footer = "\0....#{doc}\0#{meta_txt}\0"
+ footer[1,4] = [footer.size - 5].pack("V")
+ io.write(footer)
+ full_text_IO.write(footer)
+ end
+
+ scanner = StringScanner.new(fulltext)
+ scanner.scan(Regexp.new(Regexp.escape(MAGIC)))
+
+ count = 0
+ suffixes = []
+ until scanner.eos?
+ count += 1
+ start = scanner.pos
+ text = scanner.scan_until(/\0/)
+ suffixes.concat find_suffixes(text[0..-2], start)
+ len = scanner.scan(/..../).unpack("V")[0]
+ #puts "LEN: #{len} #{scanner.pos} #{scanner.string.size}"
+ #puts "#{scanner.string[scanner.pos,20].inspect}"
+ scanner.pos += len
+ #scanner.terminate if !text
+ end
+ sorted = suffixes.sort_by{|x| fulltext[x, @max_wordsize]}
+ sorted.each_slice(10000){|x| suffix_array_IO.write x.pack("V*")}
+ nil
+ end
+end # class FullTextIndexer
+
+end # module FastRI
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/full_text_indexer.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/name_descriptor.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/name_descriptor.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/name_descriptor.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,71 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+
+module FastRI
+
+# Alternative NameDescriptor implementation which doesn't require class/module
+# names to be properly capitalized.
+#
+# Rules:
+# * <tt>#foo</tt>: instance method +foo+
+# * <tt>.foo</tt>: method +foo+ (either singleton or instance)
+# * <tt>::foo</tt>: singleton method +foo+
+# * <tt>foo::bar#bar<tt>: instance method +bar+ under <tt>foo::bar</tt>
+# * <tt>foo::bar.bar<tt>: either singleton or instance method +bar+ under
+# <tt>foo::bar</tt>
+# * <tt>foo::bar::Baz<tt>: module/class foo:bar::Baz
+# * <tt>foo::bar::baz</tt>: singleton method +baz+ from <tt>foo::bar</tt>
+# * other: raise RiError
+class NameDescriptor
+ attr_reader :class_names
+ attr_reader :method_name
+
+ # true and false have the obvious meaning. nil means we don't care
+ attr_reader :is_class_method
+
+ def initialize(arg)
+ @class_names = []
+ @method_name = nil
+ @is_class_method = nil
+
+ case arg
+ when /((?:[^:]*::)*[^:]*)(#|::|\.)(.*)$/
+ ns, sep, meth_or_class = $~.captures
+ # optimization attempt: try to guess the real capitalization,
+ # so we get a direct hit
+ @class_names = ns.split(/::/).map{|x| x[0,1] = x[0,1].upcase; x }
+ if %w[# .].include? sep
+ @method_name = meth_or_class
+ @is_class_method =
+ case sep
+ when "#"; false
+ when "."; nil
+ end
+ else
+ if ("A".."Z").include? meth_or_class[0,1] # 1.9 compatibility
+ @class_names << meth_or_class
+ else
+ @method_name = meth_or_class
+ @is_class_method = true
+ end
+ end
+ when /^[^#:.]+/
+ if ("A".."Z").include? arg[0,1]
+ @class_names = [arg]
+ else
+ @method_name = arg.dup
+ @is_class_method = nil
+ end
+ else
+ raise RiError, "Cannot create NameDescriptor from #{arg}"
+ end
+ end
+
+ # Return the full class name (with '::' between the components)
+ # or "" if there's no class name
+ def full_class_name
+ @class_names.join("::")
+ end
+end
+
+end #module FastRI
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/name_descriptor.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_index.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_index.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_index.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,601 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+
+require 'rdoc/ri/ri_cache'
+require 'rdoc/ri/ri_reader'
+require 'rdoc/ri/ri_descriptions'
+require 'fastri/version'
+
+
+# This is taken straight from 1.8.5's rdoc/ri/ri_descriptions.rb.
+# Older releases have a buggy #merge_in that crashes when old.comment is nil.
+if RUBY_RELEASE_DATE < "2006-06-15"
+ module ::RI # :nodoc:
+ class ModuleDescription # :nodoc:
+ remove_method :merge_in
+ # merge in another class desscription into this one
+ def merge_in(old)
+ merge(@class_methods, old.class_methods)
+ merge(@instance_methods, old.instance_methods)
+ merge(@attributes, old.attributes)
+ merge(@constants, old.constants)
+ merge(@includes, old.includes)
+ if @comment.nil? || @comment.empty?
+ @comment = old.comment
+ else
+ unless old.comment.nil? or old.comment.empty? then
+ @comment << SM::Flow::RULE.new
+ @comment.concat old.comment
+ end
+ end
+ end
+ end
+ end
+end
+
+
+module FastRI
+
+# This class provides the same functionality as RiReader, with some
+# improvements:
+# * lower memory consumption
+# * ability to handle information from different sources separately.
+#
+# Some operations can be restricted to a given "scope", that is, a
+# "RI DB directory". This allows you to e.g. look for all the instance methods
+# in String defined by a package.
+#
+# Such operations take a +scope+ argument, which is either an integer which
+# indexes the source in #paths, or a name identifying the source (either
+# "system" or a package name). If <tt>scope == nil</tt>, the information from
+# all sources is merged.
+class RiIndex
+ # Redefine RI::MethodEntry#full_name to use the following notation:
+ # Namespace::Foo.singleton_method (instead of ::). RiIndex depends on this to
+ # tell singleton methods apart.
+ class ::RI::MethodEntry # :nodoc:
+ remove_method :full_name
+ def full_name
+ res = @in_class.full_name
+ unless res.empty?
+ if @is_class_method
+ res << "."
+ else
+ res << "#"
+ end
+ end
+ res << @name
+ end
+ end
+
+ class MethodEntry
+ attr_reader :full_name, :name, :index, :source_index
+
+ def initialize(ri_index, fullname, index, source_index)
+ # index is the index in ri_index' array
+ # source_index either nil (all scopes) or the integer referencing the
+ # path (-> we'll do @ri_index.paths[@source_index])
+ @ri_index = ri_index
+ @full_name = fullname
+ @name = fullname[/[.#](.*)$/, 1]
+ @index = index
+ @source_index = source_index
+ end
+
+ # Returns the "fully resolved" file name of the yaml containing our
+ # description.
+ def path_name
+ prefix = @full_name.split(/::|[#.]/)[0..-2]
+ case @source_index
+ when nil
+ ## we'd like to do
+ #@ri_index.source_paths_for(self).map do |path|
+ # File.join(File.join(path, *prefix), RI::RiWriter.internal_to_external(@name))
+ #end
+ # but RI doesn't support merging at the method-level, so
+ path = @ri_index.source_paths_for(self).first
+ File.join(File.join(path, *prefix),
+ RI::RiWriter.internal_to_external(@name) +
+ (singleton_method? ? "-c" : "-i" ) + ".yaml")
+ else
+ path = @ri_index.paths[@source_index]
+ File.join(File.join(path, *prefix),
+ RI::RiWriter.internal_to_external(@name) +
+ (singleton_method? ? "-c" : "-i" ) + ".yaml")
+ end
+ end
+
+ def singleton_method?
+ /\.[^:]+$/ =~ @full_name
+ end
+
+ def instance_method?
+ !singleton_method?
+ end
+
+ # Returns the type of this entry (<tt>:method</tt>).
+ def type
+ :method
+ end
+ end
+
+ class ClassEntry
+ attr_reader :full_name, :name, :index, :source_index
+
+ def initialize(ri_index, fullname, index, source_index)
+ @ri_index = ri_index
+ @full_name = fullname
+ @name = fullname.split(/::/).last
+ @index = index
+ @source_index = source_index
+ end
+
+ # Returns an array of directory names holding the cdesc-Classname.yaml
+ # files.
+ def path_names
+ prefix = @full_name.split(/::/)
+ case @source_index
+ when nil
+ @ri_index.source_paths_for(self).map{|path| File.join(path, *prefix) }
+ else
+ [File.join(@ri_index.paths[@source_index], *prefix)]
+ end
+ end
+
+ # Returns nested classes and modules matching name (non-recursive).
+ def contained_modules_matching(name)
+ @ri_index.namespaces_under(self, false, @source_index).select do |x|
+ x.name[name]
+ end
+ end
+
+ # Returns all nested classes and modules (non-recursive).
+ def classes_and_modules
+ @ri_index.namespaces_under(self, false, @source_index)
+ end
+
+ # Returns nested class or module named exactly +name+ (non-recursive).
+ def contained_class_named(name)
+ contained_modules_matching(name).find{|x| x.name == name}
+ end
+
+ # Returns instance or singleton methods matching name (non-recursive).
+ def methods_matching(name, is_class_method)
+ @ri_index.methods_under(self, false, @source_index).select do |meth|
+ meth.name[name] &&
+ (is_class_method ? meth.singleton_method? : meth.instance_method?)
+ end
+ end
+
+ # Returns instance or singleton methods matching name (recursive).
+ def recursively_find_methods_matching(name, is_class_method)
+ @ri_index.methods_under(self, true, @source_index).select do |meth|
+ meth.name[name] &&
+ (is_class_method ? meth.singleton_method? : meth.instance_method?)
+ end
+ end
+
+ # Returns all methods, both instance and singleton (non-recursive).
+ def all_method_names
+ @ri_index.methods_under(self, false, @source_index).map{|meth| meth.full_name}
+ end
+
+ # Returns the type of this entry (<tt>:namespace</tt>).
+ def type
+ :namespace
+ end
+ end
+
+ class TopLevelEntry < ClassEntry
+ def methods_matching(name, is_class_method)
+ recursively_find_methods_matching(name, is_class_method)
+ end
+
+ def module_named(name)
+
+ end
+ end
+
+ attr_reader :paths
+
+ class << self; private :new end
+
+ def self.new_from_paths(paths = nil)
+ obj = new
+ obj.rebuild_index(paths)
+ obj
+ end
+
+ def self.new_from_IO(anIO)
+ obj = new
+ obj.load(anIO)
+ obj
+ end
+
+ def rebuild_index(paths = nil)
+ @paths = paths || RI::Paths::PATH
+ @gem_names = paths.map do |p|
+ fullp = File.expand_path(p)
+ gemname = nil
+ begin
+ require 'rubygems'
+ Gem.path.each do |gempath|
+ re = %r!^#{Regexp.escape(File.expand_path(gempath))}/doc/!
+ if re =~ fullp
+ gemname = fullp.gsub(re,"")[%r{^[^/]+}]
+ break
+ end
+ end
+ rescue LoadError
+ # no RubyGems, no gems installed, skip it
+ end
+ gemname ? gemname : "system"
+ end
+ methods = Hash.new{|h,k| h[k] = []}
+ namespaces = methods.clone
+ @paths.each_with_index do |path, source_index|
+ ri_reader = RI::RiReader.new(RI::RiCache.new(path))
+ obtain_classes(ri_reader.top_level_namespace.first).each{|name| namespaces[name] << source_index }
+ obtain_methods(ri_reader.top_level_namespace.first).each{|name| methods[name] << source_index }
+ end
+ @method_array = methods.sort_by{|h,k| h}.map do |name, sources|
+ "#{name} #{sources.map{|x| x.to_s}.join(' ')}"
+ end
+ @namespace_array = namespaces.sort_by{|h,k| h}.map do |name, sources|
+ "#{name} #{sources.map{|x| x.to_s}.join(' ')}"
+ end
+
+=begin
+ puts "@method_array: #{@method_array.size}"
+ puts "@namespace_array: #{@namespace_array.size}"
+ puts @method_array.inject(0){|s,x| s + x.size}
+ puts @namespace_array.inject(0){|s,x| s + x.size}
+=end
+ end
+
+ MAGIC = "FastRI index #{FASTRI_INDEX_FORMAT}"
+ # Load the index from the given IO.
+ # It must contain a textual representation generated by #dump.
+ def load(anIO)
+ header = anIO.gets
+ raise "Invalid format." unless header.chomp == MAGIC
+ anIO.gets # discard "Sources:"
+ paths = []
+ gem_names = []
+ until (line = anIO.gets).index("=" * 80) == 0
+ gemname, path = line.strip.split(/\s+/)
+ paths << path
+ gem_names << gemname
+ end
+ anIO.gets # discard "Namespaces:"
+ namespace_array = []
+ until (line = anIO.gets).index("=" * 80) == 0
+ namespace_array << line
+ end
+ anIO.gets # discard "Methods:"
+ method_array = []
+ until (line = anIO.gets).index("=" * 80) == 0
+ method_array << line
+ end
+ @paths = paths
+ @gem_names = gem_names
+ @namespace_array = namespace_array
+ @method_array = method_array
+ end
+
+ # Serializes index to the given IO.
+ def dump(anIO)
+ anIO.puts MAGIC
+ anIO.puts "Sources:"
+ @paths.zip(@gem_names).each{|p,g| anIO.puts "%-30s %s" % [g, p]}
+ anIO.puts "=" * 80
+ anIO.puts "Namespaces:"
+ anIO.puts @namespace_array
+ anIO.puts "=" * 80
+ anIO.puts "Methods:"
+ anIO.puts @method_array
+ anIO.puts "=" * 80
+ end
+#{{{ RiReader compatibility interface
+
+ # Returns an array with the top level namespace.
+ def top_level_namespace(scope = nil)
+ [TopLevelEntry.new(self, "", -1, scope ? scope_to_sindex(scope) : nil)]
+ end
+
+ # Returns an array of ClassEntry objects whose names match +target+, and
+ # which correspond to the namespaces contained in +namespaces+.
+ # +namespaces+ is an array of ClassEntry objects.
+ def lookup_namespace_in(target, namespaces)
+ result = []
+ namespaces.each do |ns|
+ result.concat(ns.contained_modules_matching(target))
+ end
+ result
+ end
+
+ # Returns the ClassDescription associated to the given +full_name+.
+ def find_class_by_name(full_name, scope = nil)
+ entry = get_entry(@namespace_array, full_name, ClassEntry, scope)
+ return nil unless entry && entry.full_name == full_name
+ get_class(entry)
+ end
+
+ # Returns the MethodDescription associated to the given +full_name+.
+ # Only the first definition is returned when <tt>scope = nil</tt>.
+ def find_method_by_name(full_name, scope = nil)
+ entry = get_entry(@method_array, full_name, MethodEntry, scope)
+ return nil unless entry && entry.full_name == full_name
+ get_method(entry)
+ end
+
+ # Returns an array of MethodEntry objects, corresponding to the methods in
+ # the ClassEntry objects in the +namespaces+ array.
+ def find_methods(name, is_class_method, namespaces)
+ result = []
+ namespaces.each do |ns|
+ result.concat ns.methods_matching(name, is_class_method)
+ end
+ result
+ end
+
+ # Return the MethodDescription for a given MethodEntry
+ # by deserializing the YAML.
+ def get_method(method_entry)
+ path = method_entry.path_name
+ File.open(path) { |f| RI::Description.deserialize(f) }
+ end
+
+ # Return a ClassDescription for a given ClassEntry.
+ def get_class(class_entry)
+ result = nil
+ for path in class_entry.path_names
+ path = RI::RiWriter.class_desc_path(path, class_entry)
+ desc = File.open(path) {|f| RI::Description.deserialize(f) }
+ if result
+ result.merge_in(desc)
+ else
+ result = desc
+ end
+ end
+ result
+ end
+
+ # Return the names of all classes and modules.
+ def full_class_names(scope = nil)
+ all_entries(@namespace_array, scope)
+ end
+
+ # Return the names of all methods.
+ def full_method_names(scope = nil)
+ all_entries(@method_array, scope)
+ end
+
+ # Return a list of all classes, modules, and methods.
+ def all_names(scope = nil)
+ full_class_names(scope).concat(full_method_names(scope))
+ end
+
+#{{{ New (faster) interface
+
+ # Returns the number of methods in the index.
+ def num_methods
+ @method_array.size
+ end
+
+ # Returns the number of namespaces in the index.
+ def num_namespaces
+ @namespace_array.size
+ end
+
+ # Returns the ClassEntry associated to the given +full_name+.
+ def get_class_entry(full_name, scope = nil)
+ entry = get_entry(@namespace_array, full_name, ClassEntry, scope)
+ return nil unless entry && entry.full_name == full_name
+ entry
+ end
+
+ # Returns the MethodEntry associated to the given +full_name+.
+ def get_method_entry(full_name, scope = nil)
+ entry = get_entry(@method_array, full_name, MethodEntry, scope)
+ return nil unless entry && entry.full_name == full_name
+ entry
+ end
+
+ # Returns array of ClassEntry objects under class_entry_or_name
+ # (either String or ClassEntry) in the hierarchy.
+ def namespaces_under(class_entry_or_name, recursive, scope = nil)
+ namespaces_under_matching(class_entry_or_name, //, recursive, scope)
+ end
+
+ # Returns array of ClassEntry objects under class_entry_or_name (either
+ # String or ClassEntry) in the hierarchy whose +full_name+ matches the given
+ # regexp.
+ def namespaces_under_matching(class_entry_or_name, regexp, recursive, scope = nil)
+ case class_entry_or_name
+ when ClassEntry
+ class_entry = class_entry_or_name
+ when ""
+ class_entry = top_level_namespace(scope)[0]
+ else
+ class_entry = get_entry(@namespace_array, class_entry_or_name, ClassEntry, scope)
+ end
+ return [] unless class_entry
+ ret = []
+ re1, re2 = matching_regexps_namespace(class_entry.full_name)
+ (class_entry.index+1...@namespace_array.size).each do |i|
+ entry = @namespace_array[i]
+ break unless re1 =~ entry
+ next if !recursive && re2 !~ entry
+ full_name = entry[/\S+/]
+ next unless regexp =~ full_name
+ if scope
+ sources = namespace_sources(i)
+ if sources.include?(sindex = scope_to_sindex(scope))
+ ret << ClassEntry.new(self, full_name, i, sindex)
+ end
+ else
+ ret << ClassEntry.new(self, full_name, i, nil)
+ end
+ end
+ ret
+ end
+
+ # Returns array of MethodEntry objects under class_entry_or_name
+ # (either String or ClassEntry) in the hierarchy.
+ def methods_under(class_entry_or_name, recursive, scope = nil)
+ methods_under_matching(class_entry_or_name, //, recursive, scope)
+ end
+
+ # Returns array of MethodEntry objects under class_entry_or_name (either
+ # String or ClassEntry) in the hierarchy whose +full_name+ matches the given
+ # regexp.
+ def methods_under_matching(class_entry_or_name, regexp, recursive, scope = nil)
+ case class_entry_or_name
+ when ClassEntry
+ full_name = class_entry_or_name.full_name
+ else
+ full_name = class_entry_or_name
+ end
+ method_entry = get_entry(@method_array, full_name, MethodEntry)
+ return [] unless method_entry
+ ret = []
+ re1, re2 = matching_regexps_method(full_name)
+ (method_entry.index...@method_array.size).each do |i|
+ entry = @method_array[i]
+ break unless re1 =~ entry
+ next if !recursive && re2 !~ entry
+ full_name = entry[/\S+/]
+ next unless regexp =~ full_name
+ if scope
+ sources = method_sources(i)
+ if sources.include?(sindex = scope_to_sindex(scope))
+ ret << MethodEntry.new(self, full_name, i, sindex)
+ end
+ else
+ ret << MethodEntry.new(self, full_name, i, nil)
+ end
+ end
+ ret
+ end
+
+ # Returns array of Strings corresponding to the base directories of all the
+ # sources fo the given entry_or_name.
+ def source_paths_for(entry_or_name)
+ case entry_or_name
+ when ClassEntry
+ namespace_sources(entry_or_name.index).map{|i| @paths[i] }
+ when MethodEntry
+ method_sources(entry_or_name.index).map{|i| @paths[i]}
+ when nil
+ []
+ else
+ case entry_or_name
+ when /[#.]\S+/
+ method_entry = get_entry(@method_array, entry_or_name, MethodEntry, nil)
+ source_paths_for(method_entry)
+ when ""
+ []
+ else
+ class_entry = get_entry(@namespace_array, entry_or_name, ClassEntry, nil)
+ source_paths_for(class_entry)
+ end
+ end
+ end
+
+ private
+ def namespace_sources(index)
+ @namespace_array[index][/\S+ (.*)/,1].split(/\s+/).map{|x| x.to_i}
+ end
+
+ def method_sources(index)
+ @method_array[index][/\S+ (.*)/,1].split(/\s+/).map{|x| x.to_i}
+ end
+
+ def all_entries(array, scope)
+ if scope
+ wanted_sidx = scope_to_sindex(scope)
+ chosen = array.select{|x| x[/ (.*$)/, 1].split(/\s+/).map{|x| x.to_i}.include? wanted_sidx }
+ else
+ chosen = array
+ end
+ chosen.map{|x| x[/(\S+)/]}
+ end
+
+ def matching_regexps_namespace(prefix)
+ if prefix.empty?
+ [//, /^[^:]+ /]
+ else
+ [/^#{Regexp.escape(prefix)}/, /^#{Regexp.escape(prefix)}(::|[#.])[^:]+ / ]
+ end
+ end
+
+ def matching_regexps_method(prefix)
+ if prefix.empty?
+ [//, /^[#.] /] # the second should never match
+ else
+ [/^#{Regexp.escape(prefix)}([#.]|::)/, /^#{Regexp.escape(prefix)}([#.])\S+ / ]
+ end
+ end
+
+ def scope_to_sindex(scope)
+ case scope
+ when Integer
+ scope
+ else
+ @gem_names.index(scope)
+ end
+ end
+
+ def get_entry(array, fullname, klass, scope = nil)
+ index = binary_search(array, fullname)
+ return nil unless index
+ entry = array[index]
+ sources = entry[/\S+ (.*)/,1].split(/\s+/).map{|x| x.to_i}
+ if scope
+ wanted_sidx = scope_to_sindex(scope)
+ return nil unless wanted_sidx
+ return nil unless sources.include?(wanted_sidx)
+ return klass.new(self, entry[/\S+/], index, wanted_sidx)
+ end
+ klass.new(self, entry[/\S+/], index, nil)
+ end
+
+ def binary_search(array, name, from = 0, to = array.size - 1)
+ middle = (from + to) / 2
+ pivot = array[middle][/\S+/]
+ if from == to
+ if pivot.index(name) == 0
+ from
+ else
+ nil
+ end
+ elsif name <= pivot
+ binary_search(array, name, from, middle)
+ elsif name > pivot
+ binary_search(array, name, middle+1, to)
+ end
+ end
+
+ def obtain_classes(namespace, res = [])
+ subnamespaces = namespace.classes_and_modules
+ subnamespaces.each do |ns|
+ res << ns.full_name
+ obtain_classes(ns, res)
+ end
+ res
+ end
+
+ def obtain_methods(namespace, res = [])
+ subnamespaces = namespace.classes_and_modules
+ subnamespaces.each do |ns|
+ res.concat ns.all_method_names
+ obtain_methods(ns, res)
+ end
+ res
+ end
+end
+
+end #module FastRI
+
+# vi: set sw=2 expandtab:
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_index.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_service.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_service.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_service.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,423 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+# Inspired by ri-emacs.rb by Kristof Bastiaensen <kr...@vl...>
+
+require 'rdoc/ri/ri_paths'
+require 'rdoc/ri/ri_util'
+require 'rdoc/ri/ri_formatter'
+require 'rdoc/ri/ri_display'
+
+require 'fastri/ri_index.rb'
+require 'fastri/name_descriptor'
+
+
+module FastRI
+
+class ::DefaultDisplay
+ def full_params(method)
+ method.params.split(/\n/).each do |p|
+ p.sub!(/^#{method.name}\(/o,'(')
+ unless p =~ /\b\.\b/
+ p = method.full_name + p
+ end
+ @formatter.wrap(p)
+ @formatter.break_to_newline
+ end
+ end
+end
+
+class StringRedirectedDisplay < ::DefaultDisplay
+ attr_reader :stringio, :formatter
+ def initialize(*args)
+ super(*args)
+ reset_stringio
+ end
+
+ def puts(*a)
+ @stringio.puts(*a)
+ end
+
+ def print(*a)
+ @stringio.print(*a)
+ end
+
+ def reset_stringio
+ @stringio = StringIO.new("")
+ @formatter.stringio = @stringio
+ end
+end
+
+class ::RI::TextFormatter
+ def puts(*a); @stringio.puts(*a) end
+ def print(*a); @stringio.print(*a) end
+end
+
+module FormatterRedirection
+ attr_accessor :stringio
+ def initialize(*options)
+ @stringio = StringIO.new("")
+ super
+ end
+end
+
+class RedirectedAnsiFormatter < RI::AnsiFormatter
+ include FormatterRedirection
+end
+
+class RedirectedTextFormatter < RI::TextFormatter
+ include FormatterRedirection
+end
+
+class RiService
+
+ class MatchFinder
+ def self.new
+ ret = super
+ yield ret if block_given?
+ ret
+ end
+
+ def initialize
+ @matchers = {}
+ end
+
+ def add_matcher(name, &block)
+ @matchers[name] = block
+ end
+
+ def get_matches(methods)
+ catch(:MatchFinder_return) do
+ methods.each do |name|
+ matcher = @matchers[name]
+ matcher.call(self) if matcher
+ end
+ []
+ end
+ end
+
+ def yield(matches)
+ case matches
+ when nil, []; nil
+ when Array
+ throw :MatchFinder_return, matches
+ else
+ throw :MatchFinder_return, [matches]
+ end
+ end
+ end # MatchFinder
+
+
+ Options = Struct.new(:formatter, :use_stdout, :width)
+
+ def initialize(ri_reader)
+ @ri_reader = ri_reader
+ end
+
+ DEFAULT_OBTAIN_ENTRIES_OPTIONS = {
+ :lookup_order => [
+ :exact, :exact_ci, :nested, :nested_ci, :partial, :partial_ci,
+ :nested_partial, :nested_partial_ci,
+ ],
+ }
+ def obtain_entries(descriptor, options = {})
+ options = DEFAULT_OBTAIN_ENTRIES_OPTIONS.merge(options)
+ if descriptor.class_names.empty?
+ seps = separators(descriptor.is_class_method)
+ return obtain_unqualified_method_entries(descriptor.method_name, seps,
+ options[:lookup_order])
+ end
+
+ # if we're here, some namespace was given
+ full_ns_name = descriptor.class_names.join("::")
+ if descriptor.method_name == nil
+ return obtain_namespace_entries(full_ns_name, options[:lookup_order])
+ else # both namespace and method
+ seps = separators(descriptor.is_class_method)
+ return obtain_qualified_method_entries(full_ns_name, descriptor.method_name,
+ seps, options[:lookup_order])
+ end
+ end
+
+ def completion_list(keyw)
+ return @ri_reader.full_class_names if keyw == ""
+
+ descriptor = NameDescriptor.new(keyw)
+
+ if descriptor.class_names.empty?
+ # try partial matches
+ meths = @ri_reader.methods_under_matching("", /(#|\.)#{descriptor.method_name}/, true)
+ ret = meths.map{|x| x.name}.uniq.sort
+ return ret.empty? ? nil : ret
+ end
+
+ # if we're here, some namespace was given
+ full_ns_name = descriptor.class_names.join("::")
+ if descriptor.method_name == nil && ! [?#, ?:, ?.].include?(keyw[-1])
+ # partial match
+ namespaces = @ri_reader.namespaces_under_matching("", /^#{full_ns_name}/, false)
+ ret = namespaces.map{|x| x.full_name}.uniq.sort
+ return ret.empty? ? nil : ret
+ else
+ if [?#, ?:, ?.].include?(keyw[-1])
+ seps = case keyw[-1]
+ when ?#; %w[#]
+ when ?:; %w[.]
+ when ?.; %w[. #]
+ end
+ else # both namespace and method
+ seps = separators(descriptor.is_class_method)
+ end
+ sep_re = "(" + seps.map{|x| Regexp.escape(x)}.join("|") + ")"
+ # partial
+ methods = @ri_reader.methods_under_matching(full_ns_name, /#{sep_re}#{descriptor.method_name}/, false)
+ ret = methods.map{|x| x.full_name}.uniq.sort
+ return ret.empty? ? nil : ret
+ end
+ rescue RiError
+ return nil
+ end
+
+ DEFAULT_INFO_OPTIONS = {
+ :formatter => :ansi,
+ :width => 72,
+ :extended => false,
+ }
+
+ def matches(keyword, options = {})
+ options = DEFAULT_INFO_OPTIONS.merge(options)
+ return nil if keyword.strip.empty?
+ descriptor = NameDescriptor.new(keyword)
+ ret = obtain_entries(descriptor, options).map{|x| x.full_name}
+ ret ? ret : nil
+ rescue RiError
+ return nil
+ end
+
+ def info(keyw, options = {})
+ options = DEFAULT_INFO_OPTIONS.merge(options)
+ return nil if keyw.strip.empty?
+ descriptor = NameDescriptor.new(keyw)
+ entries = obtain_entries(descriptor, options)
+
+ case entries.size
+ when 0; nil
+ when 1
+ case entries[0].type
+ when :namespace
+ capture_stdout(display(options)) do |display|
+ display.display_class_info(@ri_reader.get_class(entries[0]), @ri_reader)
+ if options[:extended]
+ methods = @ri_reader.methods_under(entries[0], true)
+ methods.each do |meth_entry|
+ display.display_method_info(@ri_reader.get_method(meth_entry))
+ end
+ end
+ end
+ when :method
+ capture_stdout(display(options)) do |display|
+ display.display_method_info(@ri_reader.get_method(entries[0]))
+ end
+ end
+ else
+ capture_stdout(display(options)) do |display|
+ formatter = display.formatter
+ formatter.draw_line("Multiple choices:")
+ formatter.blankline
+ formatter.wrap(entries.map{|x| x.full_name}.join(", "))
+ end
+ end
+ rescue RiError
+ return nil
+ end
+
+ def args(keyword, options = {})
+ options = DEFAULT_INFO_OPTIONS.merge(options)
+ return nil if keyword.strip.empty?
+ descriptor = NameDescriptor.new(keyword)
+ entries = obtain_entries(descriptor, options)
+ return nil if entries.empty? || RiIndex::ClassEntry === entries[0]
+
+ params_text = ""
+ entries.each do |entry|
+ desc = @ri_reader.get_method(entry)
+ params_text << capture_stdout(display(options)) do |display|
+ display.full_params(desc)
+ end
+ end
+ params_text
+ rescue RiError
+ return nil
+ end
+
+ # Returns a list with the names of the modules/classes that define the given
+ # method, or +nil+.
+ def class_list(keyword)
+ _class_list(keyword, '\1')
+ end
+
+ # Returns a list with the names of the modules/classes that define the given
+ # method, followed by a flag (#|::), or +nil+.
+ # e.g. ["Array#", "IO#", "IO::", ... ]
+ def class_list_with_flag(keyword)
+ r = _class_list(keyword, '\1\2')
+ r ? r.map{|x| x.gsub(/\./, "::")} : nil
+ end
+
+ # Return array of strings with the names of all known methods.
+ def all_methods
+ @ri_reader.full_method_names
+ end
+
+ # Return array of strings with the names of all known classes.
+ def all_classes
+ @ri_reader.full_class_names
+ end
+
+ private
+
+ def obtain_unqualified_method_entries(name, separators, order)
+ name = Regexp.escape(name)
+ sep_re = "(" + separators.map{|x| Regexp.escape(x)}.join("|") + ")"
+ matcher = MatchFinder.new do |m|
+ m.add_matcher(:exact) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}#{name}$/, true)
+ end
+ m.add_matcher(:exact_ci) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}#{name}$/i, true)
+ end
+ m.add_matcher(:partial) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}#{name}/, true)
+ end
+ m.add_matcher(:partial_ci) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}#{name}/i, true)
+ end
+ m.add_matcher(:anywhere) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}.*#{name}/, true)
+ end
+ m.add_matcher(:anywhere_ci) do
+ m.yield @ri_reader.methods_under_matching("", /#{sep_re}.*#{name}/i, true)
+ end
+ end
+ matcher.get_matches(order)
+ end
+
+ def obtain_qualified_method_entries(namespace, method, separators, order)
+ namespace, unescaped_namespace = Regexp.escape(namespace), namespace
+ method = Regexp.escape(method)
+ matcher = MatchFinder.new do |m|
+ m.add_matcher(:exact) do
+ separators.each do |sep|
+ m.yield @ri_reader.get_method_entry("#{namespace}#{sep}#{method}")
+ end
+ end
+ sep_re = "(" + separators.map{|x| Regexp.escape(x)}.join("|") + ")"
+ m.add_matcher(:exact_ci) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}#{sep_re}#{method}$/i, true)
+ end
+ m.add_matcher(:nested) do
+ m.yield @ri_reader.methods_under_matching("", /::#{namespace}#{sep_re}#{method}$/, true)
+ end
+ m.add_matcher(:nested_ci) do
+ m.yield @ri_reader.methods_under_matching("", /::#{namespace}#{sep_re}#{method}$/i, true)
+ end
+ m.add_matcher(:partial) do
+ m.yield @ri_reader.methods_under_matching(unescaped_namespace, /#{sep_re}#{method}/, false)
+ end
+ m.add_matcher(:partial_ci) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}#{sep_re}#{method}/i, true)
+ end
+ m.add_matcher(:nested_partial) do
+ m.yield @ri_reader.methods_under_matching("", /::#{namespace}#{sep_re}#{method}/, true)
+ end
+ m.add_matcher(:nested_partial_ci) do
+ m.yield @ri_reader.methods_under_matching("", /::#{namespace}#{sep_re}#{method}/i, true)
+ end
+ m.add_matcher(:namespace_partial) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}[^:]*#{sep_re}#{method}$/, true)
+ end
+ m.add_matcher(:namespace_partial_ci) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}[^:]*#{sep_re}#{method}$/i, true)
+ end
+ m.add_matcher(:full_partial) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}[^:]*#{sep_re}#{method}/, true)
+ end
+ m.add_matcher(:full_partial_ci) do
+ m.yield @ri_reader.methods_under_matching("", /^#{namespace}[^:]*#{sep_re}#{method}/i, true)
+ end
+ end
+ matcher.get_matches(order)
+ end
+
+ def obtain_namespace_entries(name, order)
+ name = Regexp.escape(name)
+ matcher = MatchFinder.new do |m|
+ m.add_matcher(:exact){ m.yield @ri_reader.get_class_entry(name) }
+ m.add_matcher(:exact_ci) do
+ m.yield @ri_reader.namespaces_under_matching("", /^#{name}$/i, true)
+ end
+ m.add_matcher(:nested) do
+ m.yield @ri_reader.namespaces_under_matching("", /::#{name}$/, true)
+ end
+ m.add_matcher(:nested_ci) do
+ m.yield @ri_reader.namespaces_under_matching("", /::#{name}$/i, true)
+ end
+ m.add_matcher(:partial) do
+ m.yield @ri_reader.namespaces_under_matching("", /^#{name}/, true)
+ end
+ m.add_matcher(:partial_ci) do
+ m.yield @ri_reader.namespaces_under_matching("", /^#{name}/i, true)
+ end
+ m.add_matcher(:nested_partial) do
+ m.yield @ri_reader.namespaces_under_matching("", /::#{name}[^:]*$/, true)
+ end
+ m.add_matcher(:nested_partial_ci) do
+ m.yield @ri_reader.namespaces_under_matching("", /::#{name}[^:]*$/i, true)
+ end
+ end
+ matcher.get_matches(order)
+ end
+
+ def _class_list(keyword, rep)
+ return nil if keyword.strip.empty?
+ entries = @ri_reader.methods_under_matching("", /#{keyword}$/, true)
+ return nil if entries.empty?
+
+ entries.map{|entry| entry.full_name.sub(/(.*)(#|\.).*/, rep) }.uniq
+ rescue RiError
+ return nil
+ end
+
+
+ def separators(is_class_method)
+ case is_class_method
+ when true; ["."]
+ when false; ["#"]
+ when nil; [".","#"]
+ end
+ end
+
+ DEFAULT_DISPLAY_OPTIONS = {
+ :formatter => :ansi,
+ :width => 72,
+ }
+ def display(opt = {})
+ opt = DEFAULT_DISPLAY_OPTIONS.merge(opt)
+ options = Options.new
+ options.use_stdout = true
+ case opt[:formatter].to_sym
+ when :ansi
+ options.formatter = RedirectedAnsiFormatter
+ else
+ options.formatter = RedirectedTextFormatter
+ end
+ options.width = opt[:width]
+ StringRedirectedDisplay.new(options)
+ end
+
+ def capture_stdout(display)
+ yield display
+ display.stringio.string
+ end
+end
+
+end # module FastRI
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/ri_service.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/util.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/util.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/util.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,169 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+
+# emulate rubygems.rb and define Gem.path if not loaded
+# This is much faster than requiring rubygems.rb, which loads way too much
+# stuff.
+unless defined? ::Gem
+ require 'rbconfig'
+ module Gem
+ def self.path
+ ENV['GEM_HOME'] || default_dir
+ end
+ def self.default_dir
+ if defined? RUBY_FRAMEWORK_VERSION
+ return File.join(File.dirname(Config::CONFIG["sitedir"]), "Gems")
+ else
+ File.join(Config::CONFIG['libdir'], 'ruby', 'gems', Config::CONFIG['ruby_version'])
+ end
+ end
+ end
+end
+# don't let rdoc/ri/ri_paths load rubygems.rb, that takes ~100ms !
+emulation = $".all?{|x| /rubygems\.rb$/ !~ x} # 1.9 compatibility
+$".unshift "rubygems.rb" if emulation
+require 'rdoc/ri/ri_paths'
+$".delete "rubygems.rb" if emulation
+require 'rdoc/ri/ri_writer'
+
+module FastRI
+module Util
+ # Return an array of <tt>[name, version, path]</tt> arrays corresponding to
+ # the last version of each installed gem. +path+ is the base path of the RI
+ # documentation from the gem. If the version cannot be determined, it will
+ # be +nil+, and the corresponding gem might be repeated in the output array
+ # (once per version).
+ def gem_directories_unique
+ return [] unless defined? Gem
+ gemdirs = Dir["#{Gem.path}/doc/*/ri"]
+ gems = Hash.new{|h,k| h[k] = []}
+ gemdirs.each do |path|
+ gemname, version = %r{/([^/]+)-(.*)/ri$}.match(path).captures
+ if gemname.nil? # doesn't follow any conventions :(
+ gems[path[%r{/([^/]+)/ri$}, 1]] << [nil, path]
+ else
+ gems[gemname] << [version, path]
+ end
+ end
+ gems.sort_by{|name, _| name}.map do |name, versions|
+ version, path = versions.sort.last
+ [name, version, File.expand_path(path)]
+ end
+ end
+ module_function :gem_directories_unique
+
+ # Return the <tt>[name, version, path]</tt> array for the gem owning the RI
+ # information stored in +path+, or +nil+.
+ def gem_info_for_path(path, gem_dir_info = FastRI::Util.gem_directories_unique)
+ path = File.expand_path(path)
+ matches = gem_dir_info.select{|name, version, gem_path| path.index(gem_path) == 0}
+ matches.sort_by{|name, version, gem_path| [gem_path.size, version, name]}.last
+ end
+ module_function :gem_info_for_path
+
+ # Return the +full_name+ (in ClassEntry or MethodEntry's sense) given a path
+ # to a .yaml file relative to a "base RI DB path".
+ def gem_relpath_to_full_name(relpath)
+ case relpath
+ when %r{^(.*)/cdesc-([^/]*)\.yaml$}
+ path, name = $~.captures
+ (path.split(%r{/})[0..-2] << name).join("::")
+ when %r{^(.*)/([^/]*)-(i|c)\.yaml$}
+ path, escaped_name, type = $~.captures
+ name = RI::RiWriter.external_to_internal(escaped_name)
+ sep = ( type == 'c' ) ? "." : "#"
+ path.gsub("/", "::") + sep + name
+ end
+ end
+ module_function :gem_relpath_to_full_name
+
+ # Returns the home directory (win32-aware).
+ def find_home
+ # stolen from RubyGems
+ ['HOME', 'USERPROFILE'].each do |homekey|
+ return ENV[homekey] if ENV[homekey]
+ end
+ if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
+ return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
+ end
+ begin
+ File.expand_path("~")
+ rescue StandardError => ex
+ if File::ALT_SEPARATOR
+ "C:/"
+ else
+ "/"
+ end
+ end
+ end
+ module_function :find_home
+
+ def change_query_method_type(query)
+ if md = /\A(.*)(#|\.|::)([^#.:]+)\z/.match(query)
+ namespace, sep, meth = md.captures
+ case sep
+ when /::/ then "#{namespace}##{meth}"
+ when /#/ then "#{namespace}::#{meth}"
+ else
+ query
+ end
+ else
+ query
+ end
+ end
+ module_function :change_query_method_type
+
+
+ module MagicHelp
+ def help_method_extract(m) # :nodoc:
+ unless m.inspect =~ %r[\A#<(?:Unbound)?Method: (.*?)>\Z]
+ raise "Cannot parse result of #{m.class}#inspect: #{m.inspect}"
+ end
+ $1.sub(/\A.*?\((.*?)\)(.*)\Z/){ "#{$1}#{$2}" }.sub(/\./, "::").sub(/#<Class:(.*?)>#/) { "#{$1}::" }
+ end
+
+ def magic_help(query)
+ if query =~ /\A(.*?)(#|::|\.)([^:#.]+)\Z/
+ c, k, m = $1, $2, $3
+ mid = m
+ begin
+ c = c.split(/::/).inject(Object){|s,x| s.const_get(x)}
+ m = case k
+ when "#"
+ c.instance_method(m)
+ when "::"
+ c.method(m)
+ when "."
+ begin
+ # if it's a private_instance_method, assume it was created
+ # with module_function
+ if c.private_instance_methods.include?(m)
+ c.instance_method(m)
+ else
+ c.method(m)
+ end
+ rescue NameError
+ c.instance_method(m)
+ end
+ end
+
+ ret = help_method_extract(m)
+ if ret == 'Class#new' and
+ c.private_method_defined?(:initialize)
+ return c.name + "::new"
+ elsif ret =~ /^Kernel#/ and
+ Kernel.instance_methods(false).include? mid
+ return "Object##{mid}"
+ end
+ ret
+ rescue Exception
+ query
+ end
+ else
+ query
+ end
+ end
+ end
+
+
+end # module Util
+end # module FastRI
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/util.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri/version.rb
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri/version.rb (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri/version.rb 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,13 @@
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+#
+
+module FastRI
+ FASTRI_VERSION = "0.3.0"
+ FASTRI_RELEASE_DATE = "2007-01-29"
+ FASTRI_INDEX_FORMAT = "0.1.0"
+ FASTRI_FT_INDEX_FORMAT = "1.0.0"
+ FASTRI_FT_INDEX_FORMAT_MAJOR = "1"
+ FASTRI_FT_INDEX_FORMAT_MINOR = "0"
+ FASTRI_FT_INDEX_FORMAT_TEENY = "0"
+end
+# vi: set sw=2 expandtab:
Property changes on: trunk/org.rubypeople.rdt.launching/ruby/fastri/version.rb
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.launching/ruby/fastri-server
===================================================================
--- trunk/org.rubypeople.rdt.launching/ruby/fastri-server (rev 0)
+++ trunk/org.rubypeople.rdt.launching/ruby/fastri-server 2007-07-31 23:37:00 UTC (rev 2907)
@@ -0,0 +1,251 @@
+#!/usr/bin/env ruby
+# fastri-server: serve RI documentation over DRb
+# Copyright (C) 2006 Mauricio Fernandez <mf...@ac...>
+
+require 'fastri/version'
+require 'fastri/ri_index'
+require 'fastri/ri_service'
+require 'fastri/util'
+require 'fastri/full_text_indexer'
+require 'enumerator'
+
+FASTRI_SERVER_VERSION = "0.0.1"
+
+def make_index(index_file)
+ # The local environment is trusted --- what we don't trust is what would come
+ # from the DRb connection. This way the RiService will be untainted, and we
+ # will be able to use it with $SAFE = 1.
+ ObjectSpace.each_object{|obj| obj.untaint unless obj.frozen? }
+
+ paths = [ RI::Paths::SYSDIR, RI::Paths::SITEDIR, RI::Paths::HOMEDIR ].find_all do |p|
+ p && File.directory?(p)
+ end
+ FastRI::Util.gem_directories_unique.each do |name, version, path|
+ paths << path
+ puts "Indexing RI docs for #{name} version #{version || "unknown"}."
+ end
+
+ puts "Building index."
+ t0 = Time.new
+ #ri_reader = RI::RiReader.new(RI::RiCache.new(paths))
+ ri_reader = FastRI::RiIndex.new_from_paths(paths)
+ open(index_file, "wb"){|io| Marshal.dump ri_reader, io}
+ puts <<EOF
+Indexed:
+* #{ri_reader.num_methods} methods
+* #{ri_reader.num_namespaces} classes/modules
+Needed #{Time.new - t0} seconds
+EOF
+ ri_reader
+end
+
+def linearize(comment)
+ case s = comment["body"]
+ when String; s
+ else
+ if Array === (y = comment["contents"])
+ y.map{|z| linearize(z)}.join("\n")
+ elsif s = comment["text"]
+ s
+ else
+ nil
+ end
+ end
+end
+
+def make_full_text_index(dir)
+ paths = [ RI::Paths::SYSDIR, RI::Paths::SITEDIR, RI::Paths::HOMEDIR ].find_all do |p|
+ p && File.directory?(p)
+ end
+ FastRI::Util.gem_directories_unique.each do |name, version, path|
+ paths << path
+ puts "Indexing RI docs for #{name} version #{version || "unknown"}."
+ end
+ unless File.exist?(dir)
+ Dir.mkdir(dir)
+ end
+ indexer = FastRI::FullTextIndexer.new(40)
+ bad = 0
+ paths.each do |path|
+ Dir["#{path}/**/*.yaml"].each do |yamlfile|
+ yaml = File.read(yamlfile)
+ begin
+ data = YAML.load(yaml.gsub(/ \!.*/, ''))
+ rescue Exception
+ bad += 1
+ #puts "Couldn't load #{yamlfile}"
+ next
+ end
+
+ desc = (data['comment']||[]).map{|x| linearize(x)}.join("\n")
+ desc.gsub!(/<\/?(em|b|tt|ul|ol|table)>/, "")
+ desc.gsub!(/"/, "'")
+ desc.gsub!(/</, "<")
+ desc.gsub!(/>/, ">")
+ desc.gsub!(/&/, "&")
+ unless desc.empty?
+ indexer.add_document(yamlfile, desc)
+ end
+ end
+ end
+
+ File.open(File.join(dir, "full_text.dat"), "wb") do |fulltextIO|
+ File.open(File.join(dir, "suffixes.dat"), "wb") do |suffixesIO|
+ indexer.build_index(fulltextIO, suffixesIO)
+ end
+ end
+end
+
+#{{{ Main program
+
+require 'optparse'
+
+home = FastRI::Util.find_home
+options = {:allowed_hosts => ["127.0.0.1"], :addr => "127.0.0.1",
+ :index_file => File.join(home, ".fastri-index"),
+ :do_full_text => false,
+ :full_text_dir => File.join(home, ".fastri-fulltext"),
+}
+OptionParser.new do |opts|
+ opts.version = FastRI::FASTRI_VERSION
+ opts.release = FastRI::FASTRI_RELEASE_DATE
+ opts.banner = "Usag...
[truncated message content] |
|
From: <caw...@us...> - 2007-07-31 23:36:47
|
Revision: 2906
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2906&view=rev
Author: cawilliams
Date: 2007-07-31 16:36:45 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
Modify RI view to use fastri under the covers, and to cache the listing of all classes/methods/modules
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
Modified: trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF
===================================================================
--- trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-07-31 19:01:16 UTC (rev 2905)
+++ trunk/org.rubypeople.rdt.ui/META-INF/MANIFEST.MF 2007-07-31 23:36:45 UTC (rev 2906)
@@ -60,6 +60,7 @@
org.eclipse.core.expressions,
org.eclipse.ltk.core.refactoring,
com.ibm.icu,
- com.aptana.rdt
+ com.aptana.rdt,
+ org.eclipse.debug.core
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-07-31 19:01:16 UTC (rev 2905)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/infoviews/RIView.java 2007-07-31 23:36:45 UTC (rev 2906)
@@ -2,16 +2,28 @@
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
@@ -40,6 +52,8 @@
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ViewPart;
+import org.rubypeople.rdt.internal.launching.LaunchingPlugin;
+import org.rubypeople.rdt.internal.launching.StandardVMType;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
import org.rubypeople.rdt.internal.ui.rdocexport.RDocUtility;
@@ -49,6 +63,8 @@
import org.rubypeople.rdt.launching.PropertyChangeEvent;
import org.rubypeople.rdt.launching.RubyRuntime;
+import com.aptana.rdt.AptanaRDTPlugin;
+
public class RIView extends ViewPart implements RdocListener, IVMInstallChangedListener {
private boolean riFound = false;
@@ -155,9 +171,13 @@
private void updatePage() {
initSearchList();
- if( riFound ){
- pageBook.showPage(form);
- }
+ Display.getDefault().asyncExec(new Runnable () {
+ public void run () {
+ if (riFound) {
+ pageBook.showPage(form);
+ }
+ }
+ });
}
private void showSelectedItem() {
@@ -175,14 +195,67 @@
RubyRuntime.removeVMInstallChangedListener(this);
super.dispose();
}
+
+ protected File getCachedIndex() {
+ IPath location = RubyPlugin.getDefault().getStateLocation();
+ location = location.append("ri.index");
+ return location.toFile();
+ }
+
+ protected File getFRIIndexFile() {
+ IPath location = RubyPlugin.getDefault().getStateLocation();
+ location = location.append(".fastri-index");
+ return location.toFile();
+ }
- private synchronized void initSearchList() {
- RubyInvoker invoker = new RIPopulator(this);
- Job job = new RubyInvokerJob(invoker);
- job.setPriority(Job.LONG);
- job.schedule();
+ private synchronized void initSearchList() {
+ File file = getCachedIndex();
+ if (file.exists()) {
+ try {
+ List<String> results = read(new FileReader(file));
+ fgPossibleMatches = Collections.unmodifiableList(results);
+ riFound = true;
+ Display.getDefault().asyncExec(new Runnable () {
+ public void run () {
+ filterSearchList();
+ if (riFound) pageBook.showPage(form);
+ }
+ });
+ return;
+ } catch (FileNotFoundException e) {
+ RubyPlugin.log(e);
+ }
+ }
+ RubyInvoker invoker = new RIPopulator(this);
+ Job job = new RubyInvokerJob(invoker);
+ job.setPriority(Job.LONG);
+ job.schedule();
}
+ protected List<String> read(Reader reader) {
+ Set<String> results = new HashSet<String>();
+ BufferedReader reader2 = null;
+ try {
+ reader2 = new BufferedReader(reader);
+ String line = null;
+ while ((line = reader2.readLine()) != null) {
+ results.add(line.trim());
+ }
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ } finally {
+ try {
+ if (reader2 != null)
+ reader2.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ List<String> list = new ArrayList<String>(results);
+ Collections.sort(list);
+ return list;
+ }
+
private static class RubyInvokerJob extends Job {
private RubyInvoker invoker;
@@ -209,7 +282,7 @@
}
}
} else {
- filteredList = fgPossibleMatches;
+ filteredList = new ArrayList<String>(fgPossibleMatches);
}
searchListViewer.setInput(filteredList);
if (filteredList.size() > 0) searchListViewer.getTable().setSelection(0);
@@ -237,38 +310,85 @@
abstract class RubyInvoker {
protected abstract List<String> getArgList();
- protected abstract void handleOutput(Process process);
+ protected abstract void handleOutput(String content);
protected void beforeInvoke(){}
- public final void invoke() {
- // check the ri path for existence. It might have been unconfigured
- // and set to the default value or the file could have been removed
- File file = RubyRuntime.getRI();
+ public final void invoke() {
+ File file = getFRIIndexFile();
+ if (!file.exists()) {
+ List<String> commands = new ArrayList<String>();
+ commands.add("--index-file=\"" + file.getAbsolutePath() + "\"");
+ commands.add("-b");
+ String output = execAndReadOutput(getFastRiServerPath(), commands);
+ }
+
+ List<String> commands = getArgList();
+ commands.add("--index-file=\"" + file.getAbsolutePath() + "\"");
+ String content = execAndReadOutput(getFastRiPath(), commands);
- // If we can't find it ourselves then display an error to the user
- if (file == null || !file.exists() || !file.isFile()) {
+ // If we can't find it ourselves then display an error to the
+ // user
+ if (content == null) {
riFound = false;
- PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
- public void run() {
- pageBook.showPage(riNotFoundLabel());
- }
- });
+ PlatformUI.getWorkbench().getDisplay().asyncExec(
+ new Runnable() {
+ public void run() {
+ pageBook.showPage(riNotFoundLabel());
+ }
+ });
return;
}
-
- try {
- List<String> args = getArgList();
- args.add(0, file.getAbsolutePath());
- ProcessBuilder builder = new ProcessBuilder();
- builder.command(args);
- builder.redirectErrorStream(true);
- Process p = builder.start();
- handleOutput(p);
- } catch (IOException e) {
- // message of RuntimeException will be displayed in the RI View
- throw new RuntimeException(e.getMessage(), e);
- }
+ handleOutput(content);
}
+
+ private String getFastRiServerPath() {
+ File file = LaunchingPlugin.getFileInPlugin(new Path("ruby/fastri-server"));
+ if (file == null || !file.exists() || !file.isFile()) return null;
+ return file.getAbsolutePath();
+ }
+ private String execAndReadOutput(String file, List<String> commands) {
+ if (file == null) return null;
+ StringBuffer buffer;
+ try {
+ List<String> line = new ArrayList<String>();
+ IVMInstall vm = RubyRuntime.getDefaultVMInstall();
+ if (vm == null) return "";
+ File executable = StandardVMType.findRubyExecutable(vm.getInstallLocation());
+ line.add(executable.getAbsolutePath());
+ line.add(file);
+ for (String command : commands) {
+ line.add(command);
+ }
+ File workingDirectory = new File(file).getParentFile();
+ String[] cmdLine = new String[line.size()];
+ cmdLine = line.toArray(cmdLine);
+ Process p = DebugPlugin.exec(cmdLine, workingDirectory);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String liner = null;
+ buffer = new StringBuffer();
+ while ((liner = reader.readLine()) != null) {
+ buffer.append(liner);
+ buffer.append("\n");
+ if (!reader.ready()) {
+ Thread.yield();
+ }
+ }
+ } catch (CoreException e) {
+ AptanaRDTPlugin.log(e);
+ return "";
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ return "";
+ }
+ buffer.deleteCharAt(buffer.length() - 1); // remove last \n
+ return buffer.toString();
+ }
+
+ private String getFastRiPath() {
+ File file = LaunchingPlugin.getFileInPlugin(new Path("ruby/fri"));
+ if (file == null || !file.exists() || !file.isFile()) return null;
+ return file.getAbsolutePath();
+ }
}
private class RIDescriptionUpdater extends RubyInvoker {
@@ -284,8 +404,6 @@
protected List<String> getArgList() {
List<String> args = new ArrayList<String>();
args.add("--no-pager");
- args.add("-f");
- args.add("html");
args.add(searchValue);
return args;
}
@@ -294,26 +412,13 @@
searchResult.setText(InfoViewMessages.RubyInformation_please_wait);
}
- void addToBuffer(int position, final String line) {
- if (position < 0) position = 0;
- StringBuffer modifiedLine = new StringBuffer(line);
- if (!line.endsWith(">")) modifiedLine.append("<br/>");
- modifiedLine.append("\r\n");
- buffer.insert(position, modifiedLine.toString());
- }
- protected void handleOutput(final Process process) {
- if (process == null)
+ protected void handleOutput(final String content) {
+ if (content == null)
return;
- try {
+// try {
buffer = new StringBuffer();
- InputStreamReader isr = new InputStreamReader(process.getInputStream());
- BufferedReader br = new BufferedReader(isr);
- // Insert all the text
- String line = null; // FIXME What do we do if this process hits an error?
- while ((line = br.readLine()) != null) {
- addToBuffer(buffer.length() - 1, line);
- }
+ buffer.append(content.replace("\n", "<br/>"));
buffer.insert(0, HEADER); // Put the header before all the contents
buffer.append(TAIL); // Put the body and html close tags at end
final String text = buffer.toString();
@@ -322,9 +427,9 @@
searchResult.setText(text);
}
});
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
+// } catch (IOException ioe) {
+// ioe.printStackTrace();
+// }
}
}
@@ -351,40 +456,58 @@
}
@Override
- protected void handleOutput(Process process) {
- if (process == null) return;
+ protected void handleOutput(String content) {
+ if (content == null) return;
view.riFound = false;
- BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ BufferedReader reader = new BufferedReader(new StringReader(content));
String line = null;
- fgPossibleMatches = new ArrayList<String>();
- try {
- while ((line = reader.readLine()) != null) {
- fgPossibleMatches.add(line.trim());
- }
- // if no matches were found display an error message
- if( fgPossibleMatches.size() == 0 ){
- view.riNotFound();
- } else {
- view.riFound = true;
- }
- }
- catch (IOException e) {
- RubyPlugin.log(e);
- }
- final Display display = Display.getDefault();
- display.asyncExec (new Runnable () {
+ fgPossibleMatches = read(new StringReader(content));
+ // if no matches were found display an error message
+ if (fgPossibleMatches.isEmpty()){
+ view.riNotFound();
+ } else {
+ view.riFound = true;
+ cacheListings(content);
+ }
+ Display.getDefault().asyncExec(new Runnable () {
public void run () {
filterSearchList();
if (riFound) pageBook.showPage(form);
}
});
}
+
+ private void cacheListings(String content) {
+ File file = getCachedIndex();
+ FileWriter writer = null;
+ try {
+ file.createNewFile();
+ writer = new FileWriter(file);
+ writer.write(content);
+ } catch (IOException e) {
+ RubyPlugin.log(e);
+ } finally {
+ try {
+ if (writer != null)
+ writer.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
}
void riNotFound() {
riFound = false;
- pageBook.showPage( riNotFoundLabel() );
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ pageBook.showPage( riNotFoundLabel() );
+ }
+
+ });
+
}
protected Label riNotFoundLabel() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 19:01:17
|
Revision: 2905
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2905&view=rev
Author: cawilliams
Date: 2007-07-31 12:01:16 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
Modified: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java 2007-07-31 19:01:11 UTC (rev 2904)
+++ trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java 2007-07-31 19:01:16 UTC (rev 2905)
@@ -9,6 +9,8 @@
public class TC_RubyAutoIndentStrategy extends TestCase {
+ private IDocument d;
+
public void testInsertsIndentAndEndAfterClassDefinitionLine() throws Exception {
DocumentCommand c = addNewline("class Chris");
assertEquals(15, c.caretOffset);
@@ -22,16 +24,62 @@
assertEquals(false, c.shiftsCaret);
assertEquals("\r\n \r\nend", c.text);
}
+
+ public void testHandlesReturnAfterEndOfClosedCaseWithProperIndents() throws Exception {
+ DocumentCommand c = addNewline("class Chris\r\n" +
+" case condition\r\n" +
+" when comparison1\r\n" +
+" comparison1_body\r\n" +
+" when comparison2\r\n" +
+" comparison2_body\r\n" +
+" end\r\n" +
+"end", 128);
+ assertEquals("\r\n ", c.text);
+ assertEquals("class Chris\r\n" +
+ " case condition\r\n" +
+ " when comparison1\r\n" +
+ " comparison1_body\r\n" +
+ " when comparison2\r\n" +
+ " comparison2_body\r\n" +
+ " end\r\n" +
+ " \r\n" +
+ "end", d.get());
+ }
+
+ public void testHandlesReturnAfterEndOfClosedCaseWithBadEndIndent() throws Exception {
+ DocumentCommand c = addNewline("class Chris\r\n" +
+" case condition\r\n" +
+" when comparison1\r\n" +
+" comparison1_body\r\n" +
+" when comparison2\r\n" +
+" comparison2_body\r\n" +
+" end\r\n" +
+"end", 132);
+ assertEquals("\r\n ", c.text);
+ assertEquals("class Chris\r\n" +
+ " case condition\r\n" +
+ " when comparison1\r\n" +
+ " comparison1_body\r\n" +
+ " when comparison2\r\n" +
+ " comparison2_body\r\n" +
+ " end\r\n" +
+ " \r\n" +
+ "end", d.get());
+ }
- private DocumentCommand addNewline(String source) {
+ private DocumentCommand addNewline(String source, int offset) {
RubyAutoIndentStrategy strategy = new RubyAutoIndentStrategy(null, null);
- DocumentCommand c = createDocumentCommand(source.length());
- IDocument d = new Document(source);
+ DocumentCommand c = createNewLineCommandAt(offset);
+ d = new Document(source);
strategy.customizeDocumentCommand(d, c);
return c;
}
- private DocumentCommand createDocumentCommand(int offset) {
+ private DocumentCommand addNewline(String source) {
+ return addNewline(source, source.length());
+ }
+
+ private DocumentCommand createNewLineCommandAt(int offset) {
DocumentCommand c = new TestDocumentCommand();
c.text = "\r\n";
c.length = 0;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 19:01:12
|
Revision: 2904
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2904&view=rev
Author: cawilliams
Date: 2007-07-31 12:01:11 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-07-31 17:29:22 UTC (rev 2903)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyAutoIndentStrategy.java 2007-07-31 19:01:11 UTC (rev 2904)
@@ -103,14 +103,14 @@
String unindented = "";
if (length > 0) {
unindented = previousIndent.substring(0, length);
- }
- if (!unindented.equals(indent.toString())) {
- d.replace(start, c.offset - start, unindented + trimmed);
+ } // FIXME Deindenting 'end' of case that has indented 'when's comes out incorrectly
+ if (length < indent.length()) { // if calculated indent length is less than indent we currently have queued up...
+ d.replace(start, c.offset - start, unindented + trimmed); // fix indent of this line
int shift = previousIndent.length() - unindented.length();
- c.offset = c.offset - shift;
+ c.offset = c.offset - shift; // change where we're adding the newline
if (trimmed.equals(BLOCK_CLOSER)) // if we're closing the block, remove an indent unit
buf.delete(buf.length() - shift, buf.length());
- }
+ }
}
// If we're hitting return at the end of the line of a new block, add indent
if (atStartOfBlock(trimmed)) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-31 17:29:54
|
Revision: 2903
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2903&view=rev
Author: cawilliams
Date: 2007-07-31 10:29:22 -0700 (Tue, 31 Jul 2007)
Log Message:
-----------
add some basic tests for the auto indent strategy
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/TestDocumentCommand.java
trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
Added: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/TestDocumentCommand.java
===================================================================
--- trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/TestDocumentCommand.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/TestDocumentCommand.java 2007-07-31 17:29:22 UTC (rev 2903)
@@ -0,0 +1,10 @@
+package org.rubypeople.rdt.internal.ui.text;
+
+import org.eclipse.jface.text.DocumentCommand;
+
+public class TestDocumentCommand extends DocumentCommand {
+
+ public TestDocumentCommand() {
+ super();
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/TestDocumentCommand.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
===================================================================
--- trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java 2007-07-31 17:29:22 UTC (rev 2903)
@@ -0,0 +1,45 @@
+package org.rubypeople.rdt.internal.ui.text.ruby;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.rubypeople.rdt.internal.ui.text.TestDocumentCommand;
+
+public class TC_RubyAutoIndentStrategy extends TestCase {
+
+ public void testInsertsIndentAndEndAfterClassDefinitionLine() throws Exception {
+ DocumentCommand c = addNewline("class Chris");
+ assertEquals(15, c.caretOffset);
+ assertEquals(false, c.shiftsCaret);
+ assertEquals("\r\n \r\nend", c.text);
+ }
+
+ public void testInsertsIndentAndEndAfterMethodDefinitionLine() throws Exception {
+ DocumentCommand c = addNewline("def bob");
+ assertEquals(11, c.caretOffset);
+ assertEquals(false, c.shiftsCaret);
+ assertEquals("\r\n \r\nend", c.text);
+ }
+
+ private DocumentCommand addNewline(String source) {
+ RubyAutoIndentStrategy strategy = new RubyAutoIndentStrategy(null, null);
+ DocumentCommand c = createDocumentCommand(source.length());
+ IDocument d = new Document(source);
+ strategy.customizeDocumentCommand(d, c);
+ return c;
+ }
+
+ private DocumentCommand createDocumentCommand(int offset) {
+ DocumentCommand c = new TestDocumentCommand();
+ c.text = "\r\n";
+ c.length = 0;
+ c.doit = true;
+ c.caretOffset = -1;
+ c.offset = offset;
+ c.shiftsCaret = true;
+ return c;
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.ui.tests/src/org/rubypeople/rdt/internal/ui/text/ruby/TC_RubyAutoIndentStrategy.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-30 18:52:17
|
Revision: 2902
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2902&view=rev
Author: cawilliams
Date: 2007-07-30 11:52:14 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
if we hit class_eval, grab receiver and act like it's another declaration of the receiver. (so when Rails performs class_eval on ActiveRecord::Base to mixin modules, we should catch it now)
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/SourceElementParser.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/SourceElementParser.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/SourceElementParser.java 2007-07-30 18:48:50 UTC (rev 2901)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/SourceElementParser.java 2007-07-30 18:52:14 UTC (rev 2902)
@@ -52,6 +52,7 @@
import org.jruby.ast.IterNode;
import org.jruby.ast.LocalAsgnNode;
import org.jruby.ast.ModuleNode;
+import org.jruby.ast.NewlineNode;
import org.jruby.ast.Node;
import org.jruby.ast.RootNode;
import org.jruby.ast.SClassNode;
@@ -74,7 +75,7 @@
* @author Chris
*
*/
-public class SourceElementParser extends InOrderVisitor { // TODO Rename to SourceElementParser
+public class SourceElementParser extends InOrderVisitor {
private static final String MODULE_FUNCTION = "module_function";
private static final String EMPTY_STRING = "";
@@ -473,6 +474,9 @@
if (mixinNameNode instanceof ConstNode) {
mixins.add(((ConstNode) mixinNameNode).getName());
}
+ if (mixinNameNode instanceof Colon2Node) {
+ mixins.add(ASTUtil.getFullyQualifiedName((Colon2Node) mixinNameNode));
+ }
}
for (String string : mixins) {
requestor.acceptMixin(string);
@@ -523,6 +527,39 @@
for (String methodName : arguments) {
requestor.acceptModuleFunction(methodName);
}
+ } else if (name.equals("class_eval")) {
+ Node receiver = iVisited.getReceiverNode();
+ if (receiver instanceof ConstNode || receiver instanceof Colon2Node) {
+ String receiverName = null;
+ if (receiver instanceof Colon2Node) {
+ receiverName = ASTUtil
+ .getFullyQualifiedName((Colon2Node) receiver);
+ } else {
+ receiverName = ASTUtil.getNameReflectively(receiver);
+ }
+ requestor.acceptMethodReference(name, arguments.size(),
+ iVisited.getPosition().getStartOffset());
+
+ pushVisibility(Visibility.PUBLIC);
+
+ TypeInfo typeInfo = new TypeInfo();
+ typeInfo.name = receiverName;
+ typeInfo.declarationStart = iVisited.getPosition()
+ .getStartOffset();
+ typeInfo.nameSourceStart = receiver.getPosition()
+ .getStartOffset();
+ typeInfo.nameSourceEnd = receiver.getPosition().getEndOffset() - 1;
+ typeInfo.isModule = false;
+ typeInfo.modules = new String[0];
+ typeInfo.secondary = false;
+ requestor.enterType(typeInfo);
+
+ Instruction ins = super.visitCallNode(iVisited);
+ popVisibility();
+ requestor.exitType(iVisited.getPosition().getEndOffset() - 2);
+
+ return ins;
+ }
}
requestor.acceptMethodReference(name, arguments.size(), iVisited.getPosition().getStartOffset());
return super.visitCallNode(iVisited);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-30 18:49:02
|
Revision: 2901
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2901&view=rev
Author: cawilliams
Date: 2007-07-30 11:48:50 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
when resolving a method, if we can't find the method up the type hierarchy, then do a global search for exact matches of the name.
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-07-30 13:18:48 UTC (rev 2900)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-07-30 18:48:50 UTC (rev 2901)
@@ -59,8 +59,6 @@
import org.rubypeople.rdt.internal.ti.util.INodeAcceptor;
import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator;
-import com.sun.corba.se.impl.io.FVDCodeBaseImpl;
-
public class SelectionEngine {
private HashSet<IType> fVisitedTypes;
@@ -156,11 +154,33 @@
if (method.getElementName().equals(methodName))
possible.add(method);
}
- }
+ }
+ if (possible.isEmpty()) {
+ // do a global search for method declarations matching this name
+ try {
+ List<SearchMatch> results = search(IRubyElement.METHOD, methodName, IRubySearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH);
+ for (SearchMatch match : results) {
+ IRubyElement element = (IRubyElement) match.getElement();
+ possible.add(element);
+ }
+ } catch (CoreException e) {
+ RubyCore.log(e);
+ }
+ }
return possible.toArray(new IRubyElement[possible.size()]);
}
return new IRubyElement[0];
}
+
+ private List<SearchMatch> search(int type, String patternString, int limitTo, int matchRule) throws CoreException {
+ SearchEngine engine = new SearchEngine();
+ SearchPattern pattern = SearchPattern.createPattern(type, patternString, limitTo, matchRule);
+ SearchParticipant[] participants = new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()};
+ CollectingSearchRequestor requestor = new CollectingSearchRequestor();
+ IRubySearchScope scope = SearchEngine.createWorkspaceScope();
+ engine.search(pattern, participants, scope, requestor, null);
+ return requestor.getResults();
+ }
private IType[] getReceiver(IRubyScript script, String source, Node selected, Node root, int start) {
List<IType> types = new ArrayList<IType>();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-30 13:18:52
|
Revision: 2900
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2900&view=rev
Author: cawilliams
Date: 2007-07-30 06:18:48 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
fix #5384 - Launch configurations don't allow external files as targets, even though infrastructure is fine for it
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/launcher/RubyEntryPointTab.java
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/launcher/RubyEntryPointTab.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/launcher/RubyEntryPointTab.java 2007-07-30 13:18:40 UTC (rev 2899)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/launcher/RubyEntryPointTab.java 2007-07-30 13:18:48 UTC (rev 2900)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.internal.debug.ui.launcher;
-import org.eclipse.core.resources.IFile;
+import java.io.File;
+
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
@@ -21,14 +22,14 @@
import org.rubypeople.rdt.internal.debug.ui.RdtDebugUiPlugin;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
-import org.rubypeople.rdt.internal.ui.util.RubyFileSelector;
+import org.rubypeople.rdt.internal.ui.util.FileSelector;
import org.rubypeople.rdt.internal.ui.util.RubyProjectSelector;
import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants;
public class RubyEntryPointTab extends AbstractLaunchConfigurationTab {
protected String originalFileName, originalProjectName;
protected RubyProjectSelector projectSelector;
- protected RubyFileSelector fileSelector;
+ protected FileSelector fileSelector;
public RubyEntryPointTab() {
super();
@@ -48,7 +49,7 @@
});
new Label(composite, SWT.NONE).setText(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_fileLabel);
- fileSelector = new RubyFileSelector(composite, projectSelector);
+ fileSelector = new FileSelector(composite);
fileSelector.setBrowseDialogMessage(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_fileSelectorMessage);
fileSelector.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fileSelector.addModifyListener(new ModifyListener() {
@@ -89,8 +90,8 @@
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(IRubyLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectSelector.getSelectionText());
- IFile file = fileSelector.getSelection();
- configuration.setAttribute(IRubyLaunchConfigurationConstants.ATTR_FILE_NAME, file == null ? "" : file.getProjectRelativePath().toString());
+ File file = fileSelector.getSelection();
+ configuration.setAttribute(IRubyLaunchConfigurationConstants.ATTR_FILE_NAME, file == null ? "" : file.getAbsolutePath());
}
protected Composite createPageRoot(Composite parent) {
@@ -108,21 +109,16 @@
}
public boolean isValid(ILaunchConfiguration launchConfig) {
- try {
-
- String projectName = launchConfig.getAttribute(IRubyLaunchConfigurationConstants.ATTR_PROJECT_NAME, "");
- if (projectName.length() == 0) {
- setErrorMessage(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_invalidProjectSelectionMessage);
- return false;
- }
+ String projectName = projectSelector.getSelectionText();
+ if (projectName.length() == 0) {
+ setErrorMessage(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_invalidProjectSelectionMessage);
+ return false;
+ }
- String fileName = launchConfig.getAttribute(IRubyLaunchConfigurationConstants.ATTR_FILE_NAME, "");
- if (fileName.length() == 0) {
- setErrorMessage(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_invalidFileSelectionMessage);
- return false;
- }
- } catch (CoreException e) {
- log(e);
+ String fileName = fileSelector.getSelectionText();
+ if (fileName.length() == 0) {
+ setErrorMessage(RdtDebugUiMessages.LaunchConfigurationTab_RubyEntryPoint_invalidFileSelectionMessage);
+ return false;
}
setErrorMessage(null);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-30 13:18:48
|
Revision: 2899
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2899&view=rev
Author: cawilliams
Date: 2007-07-30 06:18:40 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
fix #5384 - Launch configurations don't allow external files as targets, even though infrastructure is fine for it
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/FileSelector.java
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/FileSelector.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/FileSelector.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/FileSelector.java 2007-07-30 13:18:40 UTC (rev 2899)
@@ -0,0 +1,46 @@
+package org.rubypeople.rdt.internal.ui.util;
+
+import java.io.File;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+
+public class FileSelector extends ResourceSelector {
+
+ public FileSelector(Composite parent) {
+ super(parent);
+ }
+
+ @Override
+ protected void handleBrowseSelected() {
+ FileDialog dialog = new FileDialog(getShell());
+ dialog.setText(browseDialogMessage);
+ String currentWorkingDir = textField.getText();
+ if (!currentWorkingDir.trim().equals("")) {
+ File path = new File(currentWorkingDir);
+ if (path.exists()) {
+ dialog.setFilterPath(currentWorkingDir);
+ }
+ }
+
+ String selectedDirectory = dialog.open();
+ if (selectedDirectory != null) {
+ textField.setText(selectedDirectory);
+ }
+
+ }
+
+ @Override
+ protected String validateResourceSelection() {
+ String directory = textField.getText();
+ File directoryFile = new File(directory);
+ if (directoryFile.exists() && directoryFile.isFile())
+ return directory;
+ return EMPTY_STRING;
+ }
+
+ public File getSelection() {
+ return new File(getSelectionText());
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/util/FileSelector.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <caw...@us...> - 2007-07-27 20:27:14
|
Revision: 2898
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=2898&view=rev
Author: cawilliams
Date: 2007-07-27 13:27:13 -0700 (Fri, 27 Jul 2007)
Log Message:
-----------
bump up the disk index version - hopefully this invalidates older indices on disk
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/index/DiskIndex.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/index/DiskIndex.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/index/DiskIndex.java 2007-07-27 19:33:50 UTC (rev 2897)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/index/DiskIndex.java 2007-07-27 20:27:13 UTC (rev 2898)
@@ -48,7 +48,7 @@
private HashtableOfObject categoryTables; // category name -> HashtableOfObject(words -> int[] of document #'s) or offset if not read yet
private char[] cachedCategoryName;
-public static final String SIGNATURE= "INDEX VERSION 1.115"; //$NON-NLS-1$
+public static final String SIGNATURE= "INDEX VERSION 1.116"; //$NON-NLS-1$
public static boolean DEBUG = false;
private static final int RE_INDEXED = -1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|