package org.rubypeople.rdt.internal.codeassist; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.rubypeople.rdt.core.CompletionProposal; import org.rubypeople.rdt.core.CompletionRequestor; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.tests.ModifyingResourceTest; public class CompletionEngineTest extends ModifyingResourceTest { private IRubyProject rubyProject; private TestCompletionRequestor requestor; public CompletionEngineTest(String name) { super(name); } @Override protected void setUp() throws Exception { super.setUp(); rubyProject = createRubyProject("completion"); requestor = new TestCompletionRequestor(); } @Override protected void tearDown() throws Exception { super.tearDown(); deleteProject(rubyProject.getElementName()); rubyProject = null; } public void testArrayLiteral() throws Exception { createFile(rubyProject.getPath().append("array.rb").toPortableString(), "class Array\n def at\n end\nend\n"); final boolean[] isDone = new boolean[1]; IProgressMonitor monitor = new NullProgressMonitor() { @Override public void done() { isDone[0] = true; super.done(); } }; rubyProject.getProject().build(IncrementalProjectBuilder.CLEAN_BUILD, monitor); String src = "[1, 2, 3]."; IRubyScript script = createScript(src); long start = System.currentTimeMillis(); while (!isDone[0]) { Thread.yield(); if (System.currentTimeMillis() > start + 60000) fail("Timed out waiting for indexer on project"); } script.codeComplete(9, requestor); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "Array", "at")); } public void testUserClass() throws Exception { String src = "class MyClass\n" + " def aMethod( var )\n" + " end\n" + "\n" + " def anotherMethod\n" + " end\n" + "end\n" + "\n" + "myob = MyClass.new\n" + "\n" + "myob."; IRubyScript script = createScript(src); script.codeComplete(src.length() - 1, requestor); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "MyClass", "aMethod")); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "MyClass", "anotherMethod")); } public void testSuggestsConstructorForExplicitMethodInvokationOnConstant() throws Exception { String src = "class User\n" + "end\n" + "\n" + "@user = User."; IRubyScript script = createScript(src); script.codeComplete(src.length() - 1, requestor); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "User", "new")); } public void testClassIncludesModules() throws Exception { String src = "module M1; def m1_method; end; end\n" + "module M2; def m2_method; end; end\n" + "module M3\n" + " class C\n" + " include M1\n" + " include M2\n" + " def c_method\n" + " end\n" + " end\n" + "end\n" + "\n" + "ob = M3::C.new\n" + "ob."; IRubyScript script = createScript(src); script.codeComplete(src.length() - 1, requestor); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "M3::C", "c_method")); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "M1", "m1_method")); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "M2", "m2_method")); } public void testConstantInBrokenScript() throws Exception { String src = "class X\n" + " class Y\n" + " class Z\n" + " def self.z1; \"z1\"; end\n" + " def z2; \"z2\"; end\n" + " end\n" + " def self.y1; \"y1\"; end\n" + " def y2; \"y2\"; end\n" + " end\n" + " def self.x1; \"x1\"; end\n" + " def x2; \"x2\"; end\n" + " def p; end\n" + " def q; return 'q'; end\n" + "end\n" + "X::"; IRubyScript script = createScript(src); script.codeComplete(src.length() - 1, requestor); assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "X", "x1")); // assertTrue(requestor.containsProposal(CompletionProposal.METHOD_REF, "X", "new")); assertTrue(requestor.containsProposal(CompletionProposal.CONSTANT_REF, "X", "Y")); } private IRubyScript createScript(String src) throws CoreException { IFile file = createFile(rubyProject.getPath().append("chris.rb").toPortableString(), src); IRubyScript script = RubyCore.create(file); return script; } public void testSuggestInstanceVariablesDefinedInAttrMethodCalls() throws Exception { String src = "class User\n" + " attr :variable\n" + " def thing\n" + " \n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(44, requestor); assertTrue(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@variable")); } public void testSuggestInstanceVariablesDefinedInAttrMethodCallsWithPrefix() throws Exception { String src = "class User\n" + " attr :variable\n" + " def thing\n" + " @\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(44, requestor); assertTrue(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@variable")); } public void testSuggestClassVariablesDefinedInAttrMethodCalls() throws Exception { String src = "class User\n" + " cattr :variable\n" + " def thing\n" + " \n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(45, requestor); assertTrue(requestor.containsProposal(CompletionProposal.CLASS_VARIABLE_REF, null, "@@variable")); } public void testSuggestClassVariablesDefinedInAttrMethodCallsWithPrefix() throws Exception { String src = "class User\n" + " cattr :variable\n" + " def thing\n" + " @@\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(46, requestor); assertTrue(requestor.containsProposal(CompletionProposal.CLASS_VARIABLE_REF, null, "@@variable")); } public void testDontSuggestVariableWereCurrentlyTyping() throws Exception { String src = "class User\n" + " attr :variable\n" + " def thing\n" + " @v\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(45, requestor); assertTrue(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@variable")); assertFalse(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@v")); } public void testDoesSuggestVariableWereCurrentlyTypingIfPreviouslyDefined() throws Exception { String src = "class User\n" + " attr :variable\n" + " def thing\n" + " @v = 1\n" + " @v\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(56, requestor); assertTrue(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@variable")); assertTrue(requestor.containsProposal(CompletionProposal.INSTANCE_VARIABLE_REF, null, "@v")); } public void testDontSuggestClassVariableWereCurrentlyTyping() throws Exception { String src = "class User\n" + " cattr :variable\n" + " def thing\n" + " @@v\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(47, requestor); assertTrue(requestor.containsProposal(CompletionProposal.CLASS_VARIABLE_REF, null, "@@variable")); assertFalse(requestor.containsProposal(CompletionProposal.CLASS_VARIABLE_REF, null, "@@v")); } public void testDontSuggestLocalVariableWereCurrentlyTyping() throws Exception { String src = "class User\n" + " def thing\n" + " variable = 1\n" + " v\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(44, requestor); assertTrue(requestor.containsProposal(CompletionProposal.LOCAL_VARIABLE_REF, null, "variable")); assertFalse(requestor.containsProposal(CompletionProposal.LOCAL_VARIABLE_REF, null, "v")); } public void testConstant() throws Exception { String src = "class User\n" + " CONSTANT_NAME = 1\n" + " def thing\n" + " CON\n" + " end\n" + "end"; IRubyScript script = createScript(src); script.codeComplete(44, requestor); assertTrue(requestor.containsProposal(CompletionProposal.CONSTANT_REF, null, "CONSTANT_NAME")); } private static class TestCompletionRequestor extends CompletionRequestor { private List<CompletionProposal> proposals = new ArrayList<CompletionProposal>(); @Override public void accept(CompletionProposal proposal) { proposals.add(proposal); } public boolean containsProposal(int completionType, String declaringType, String name) { for (CompletionProposal proposal : proposals) { if (proposal.getKind() != completionType) continue; if (!proposal.getName().equals(name)) continue; if (declaringType == null && proposal.getDeclaringType().length() > 0) continue; if (declaringType != null && !declaringType.equals(proposal.getDeclaringType())) continue; return true; } return false; } public int proposalCount() { return proposals.size(); } }; }