Skip to content

Commit

Permalink
improve get-at/spread-dot of iterator(), entrySet(), Matcher and Reader
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Nov 18, 2018
1 parent 3dcbe2b commit a744860
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package org.eclipse.jdt.core.groovy.tests.search;

import static org.eclipse.jdt.groovy.core.tests.GroovyBundle.isAtLeastGroovy;
import static org.junit.Assume.assumeFalse;

import java.util.Comparator;
import java.util.List;

Expand Down Expand Up @@ -64,9 +67,7 @@ public void testNumber5() {

@Test
public void testNumber6() {
String contents = "(x <=> y).intValue()";
int offset = contents.indexOf("intValue");
assertType(contents, offset, offset + "intValue".length(), "java.lang.Integer");
assertExprType("(x <=> y).intValue()", "intValue", "java.lang.Integer");
}

@Test
Expand All @@ -81,8 +82,7 @@ public void testString2() {

@Test
public void testString3() {
String contents = "def x = '10'";
assertExprType(contents, "'10'", "java.lang.String");
assertExprType("def x = '10'", "'10'", "java.lang.String");
}

@Test
Expand Down Expand Up @@ -592,6 +592,32 @@ public void testSpread14() {
assertExprType(contents, "result", "java.util.List<java.util.List<E extends java.lang.Object>>");
}

@Test // CommandRegistry.iterator() lacks generics
public void testSpread15() {
String contents =
"import org.codehaus.groovy.tools.shell.CommandRegistry\n" +
"def registry = new CommandRegistry()\n" +
"def result = registry*.with {it}\n";
assertExprType(contents, "result", "java.util.List<java.lang.Object>");
}

@Test
public void testSpread16() {
String contents =
"import java.util.regex.Matcher\n" +
"Matcher matcher = ('abc' =~ /./)\n" +
"def result = matcher*.with {it}\n";
assertExprType(contents, "result", "java.util.List<java.lang.Object>");
}

@Test
public void testSpread17() {
String contents =
"Reader reader = null\n" +
"def result = reader*.with {it}\n";
assertExprType(contents, "result", "java.util.List<java.lang.String>");
}

@Test
public void testMapLiteral() {
assertType("[:]", "java.util.Map<java.lang.Object,java.lang.Object>");
Expand Down Expand Up @@ -1595,6 +1621,26 @@ public void testGetAt7() {
assertDeclaringType(contents, start, end, "A");
}

@Test // CommandRegistry.commands() returns List<Command>
public void testGetAt8() {
assumeFalse(isAtLeastGroovy(25));
String contents =
"import org.codehaus.groovy.tools.shell.CommandRegistry\n" +
"def registry = new CommandRegistry()\n" +
"def result = registry.commands()[0]\n";
assertExprType(contents, "result", "org.codehaus.groovy.tools.shell.Command");
}

@Test // CommandRegistry.iterator() returns Iterator
public void testGetAt9() {
assumeFalse(isAtLeastGroovy(25));
String contents =
"import org.codehaus.groovy.tools.shell.CommandRegistry\n" +
"def registry = new CommandRegistry()\n" +
"def result = registry.iterator()[0]\n";
assertExprType(contents, "result", "java.lang.Object");
}

@Test
public void testListSort1() {
String contents = "def list = []; list.sort()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression;

import java.beans.Introspector;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -72,6 +68,7 @@
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.tools.GeneralUtils;
import org.codehaus.groovy.ast.tools.GenericsUtils;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
Expand Down Expand Up @@ -101,6 +98,7 @@ public class VariableScope implements Iterable<VariableScope.VariableInfo> {
public static final ClassNode ITERATOR_CLASS_NODE = ClassHelper.Iterator_TYPE;
public static final ClassNode LIST_CLASS_NODE = ClassHelper.LIST_TYPE;
public static final ClassNode MAP_CLASS_NODE = ClassHelper.MAP_TYPE;
public static final ClassNode ENTRY_CLASS_NODE = ClassHelper.make(Map.Entry.class);
public static final ClassNode RANGE_CLASS_NODE = ClassHelper.RANGE_TYPE;
public static final ClassNode TUPLE_CLASS_NODE = ClassHelper.make(Tuple.class);
public static final ClassNode STRING_CLASS_NODE = ClassHelper.STRING_TYPE;
Expand All @@ -112,15 +110,11 @@ public class VariableScope implements Iterable<VariableScope.VariableInfo> {
public static final ClassNode MATCHER_CLASS_NODE = ClassHelper.make(Matcher.class);

public static final ClassNode FILE_CLASS_NODE = ClassHelper.make(File.class);
public static final ClassNode INPUT_STREAM_CLASS = ClassHelper.make(InputStream.class);
public static final ClassNode OUTPUT_STREAM_CLASS = ClassHelper.make(OutputStream.class);
public static final ClassNode DATA_INPUT_STREAM_CLASS = ClassHelper.make(DataInputStream.class);
public static final ClassNode DATA_OUTPUT_STREAM_CLASS = ClassHelper.make(DataOutputStream.class);
public static final ClassNode OBJECT_OUTPUT_STREAM = ClassHelper.make(ObjectOutputStream.class);
public static final ClassNode OBJECT_INPUT_STREAM = ClassHelper.make(ObjectInputStream.class);
public static final ClassNode BUFFERED_READER_CLASS_NODE = ClassHelper.make(BufferedReader.class);
public static final ClassNode BUFFERED_WRITER_CLASS_NODE = ClassHelper.make(BufferedWriter.class);
public static final ClassNode PRINT_WRITER_CLASS_NODE = ClassHelper.make(PrintWriter.class);
public static final ClassNode READER_CLASS_NODE = ClassHelper.make(Reader.class);
public static final ClassNode INPUT_STREAM_CLASS_NODE = ClassHelper.make(InputStream.class);
public static final ClassNode OUTPUT_STREAM_CLASS_NODE = ClassHelper.make(OutputStream.class);
public static final ClassNode DATA_INPUT_STREAM_CLASS_NODE = ClassHelper.make(DataInputStream.class);
public static final ClassNode DATA_OUTPUT_STREAM_CLASS_NODE = ClassHelper.make(DataOutputStream.class);

// present in Groovy 2.1+
public static final ClassNode DELEGATES_TO = ClassHelper.make(DelegatesTo.class);
Expand Down Expand Up @@ -1241,30 +1235,45 @@ public static ClassNode extractElementType(ClassNode type) {
}
}
if (method != null) {
GenericsMapper mapper = GenericsMapper.gatherGenerics(type, method.getDeclaringClass());
GenericsMapper mapper = GenericsMapper.gatherGenerics(Collections.EMPTY_LIST, type, method);
ClassNode returnType = resolveTypeParameterization(mapper, clone(method.getReturnType()));
GenericsType[] generics = GroovyUtils.getGenericsTypes(returnType);
switch (method.getName()) {
case "iterator":
if (GeneralUtils.isOrImplements(type, ITERABLE_CLASS_NODE)) {
GenericsType[] generics = GroovyUtils.getGenericsTypes(returnType);
if (generics.length == 1) return generics[0].getType();
return OBJECT_CLASS_NODE;
}
// TODO: Is this right for general iterator()?
return extractElementType(returnType);
case "entrySet":
if (generics.length == 1) return generics[0].getType();
return ClassHelper.make(Map.Entry.class);
{
GenericsType[] generics = GroovyUtils.getGenericsTypes(returnType);
if (generics.length == 1) return generics[0].getType();
return GenericsUtils.nonGeneric(ENTRY_CLASS_NODE);
}
default:
if (GroovyUtils.getBaseType(returnType).isGenericsPlaceHolder()) {
return GenericsUtils.nonGeneric(returnType);
}
return returnType;
}
}

// this is hardcoded from DGM
if (GeneralUtils.isOrImplements(type, INPUT_STREAM_CLASS) ||
GeneralUtils.isOrImplements(type, DATA_INPUT_STREAM_CLASS)) {
// TODO: Can DGM iterator() method lookup be generalized?

// IOGroovyMethods.iterator(T) overloads
if (GeneralUtils.isOrImplements(type, INPUT_STREAM_CLASS_NODE) ||
GeneralUtils.isOrImplements(type, DATA_INPUT_STREAM_CLASS_NODE)) {
return BYTE_CLASS_NODE;
} else if (GeneralUtils.isOrImplements(type, READER_CLASS_NODE)) {
return STRING_CLASS_NODE;
}
// StringGroovyMethods.iterator(Matcher) returns String or List<String>
if (MATCHER_CLASS_NODE.equals(type)) {
return OBJECT_CLASS_NODE;
}
//XmlGroovyMethods.iterator(NodeList): Iterator<Node>

// String->String, otherwise assume non-aggregate type
return type;
Expand Down

0 comments on commit a744860

Please sign in to comment.