Skip to content

Commit

Permalink
Fix for issue #545: set name range of static method call expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Mar 27, 2018
1 parent 6620bc9 commit c8070b8
Show file tree
Hide file tree
Showing 4 changed files with 360 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast.expr;

import groovy.lang.MetaMethod;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GroovyCodeVisitor;

/**
* A static method call on a class
*
* @author <a href="mailto:[email protected]">James Strachan</a>
*/
public class StaticMethodCallExpression extends Expression implements MethodCall {

private ClassNode ownerType;
private String method;
private Expression arguments;
private MetaMethod metaMethod = null;

public StaticMethodCallExpression(ClassNode type, String method, Expression arguments) {
ownerType = type;
this.method = method;
this.arguments = arguments;
}

public void visit(GroovyCodeVisitor visitor) {
visitor.visitStaticMethodCallExpression(this);
}

public Expression transformExpression(ExpressionTransformer transformer) {
Expression ret = new StaticMethodCallExpression(getOwnerType(), method, transformer.transform(arguments));
ret.setSourcePosition(this);
ret.copyNodeMetaData(this);
return ret;
}

public ASTNode getReceiver() {
return ownerType;
}

public String getMethodAsString() {
return method;
}

public Expression getArguments() {
return arguments;
}

public String getMethod() {
return method;
}

public String getText() {
return getOwnerType().getName() + "." + method + arguments.getText();
}

public String toString() {
return super.toString() + "[" + getOwnerType().getName() + "#" + method + " arguments: " + arguments + "]";
}

public ClassNode getOwnerType() {
return ownerType;
}

public void setOwnerType(ClassNode ownerType) {
this.ownerType = ownerType;
}

public void setMetaMethod(MetaMethod metaMethod) {
this.metaMethod = metaMethod;
}

public MetaMethod getMetaMethod() {
return metaMethod;
}

// GRECLIPSE add
public void setSourcePosition(ASTNode node) {
super.setSourcePosition(node);
if (getNameEnd() < 1 && node.getEnd() > 0) {
if (node instanceof MethodCallExpression) {
node = ((MethodCallExpression) node).getMethod();
} else if (node instanceof BinaryExpression) {
// likely "import static foo.Bar.setBaz; baz = null"
node = ((BinaryExpression) node).getLeftExpression();
}/* else if (node instanceof VariableExpression) {
// likely "import static foo.Bar.getBaz; def x = baz"
}*/
setNameStart(node.getStart());
setNameEnd((node instanceof StaticMethodCallExpression ?
((StaticMethodCallExpression) node).getMethod().length() : node.getEnd()) - 1);
}
}
// GRECLIPSE end
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast.expr;

import groovy.lang.MetaMethod;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GroovyCodeVisitor;

/**
* A static method call on a class
*
* @author <a href="mailto:[email protected]">James Strachan</a>
*/
public class StaticMethodCallExpression extends Expression implements MethodCall {

private ClassNode ownerType;
private final String method;
private final Expression arguments;
private MetaMethod metaMethod = null;

public StaticMethodCallExpression(ClassNode type, String method, Expression arguments) {
ownerType = type;
this.method = method;
this.arguments = arguments;
}

public void visit(GroovyCodeVisitor visitor) {
visitor.visitStaticMethodCallExpression(this);
}

public Expression transformExpression(ExpressionTransformer transformer) {
Expression ret = new StaticMethodCallExpression(getOwnerType(), method, transformer.transform(arguments));
ret.setSourcePosition(this);
ret.copyNodeMetaData(this);
return ret;
}

public ASTNode getReceiver() {
return ownerType;
}

public String getMethodAsString() {
return method;
}

public Expression getArguments() {
return arguments;
}

public String getMethod() {
return method;
}

public String getText() {
return getOwnerType().getName() + "." + method + arguments.getText();
}

public String toString() {
return super.toString() + "[" + getOwnerType().getName() + "#" + method + " arguments: " + arguments + "]";
}

public ClassNode getOwnerType() {
return ownerType;
}

public void setOwnerType(ClassNode ownerType) {
this.ownerType = ownerType;
}

public void setMetaMethod(MetaMethod metaMethod) {
this.metaMethod = metaMethod;
}

public MetaMethod getMetaMethod() {
return metaMethod;
}

// GRECLIPSE add
public void setSourcePosition(ASTNode node) {
super.setSourcePosition(node);
if (getNameEnd() < 1 && node.getEnd() > 0) {
if (node instanceof MethodCallExpression) {
node = ((MethodCallExpression) node).getMethod();
} else if (node instanceof BinaryExpression) {
// likely "import static foo.Bar.setBaz; baz = null"
node = ((BinaryExpression) node).getLeftExpression();
}/* else if (node instanceof VariableExpression) {
// likely "import static foo.Bar.getBaz; def x = baz"
}*/
setNameStart(node.getStart());
setNameEnd((node instanceof StaticMethodCallExpression ?
((StaticMethodCallExpression) node).getMethod().length() : node.getEnd()) - 1);
}
}
// GRECLIPSE end
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast.expr;

import groovy.lang.MetaMethod;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GroovyCodeVisitor;

/**
* A static method call on a class
*
* @author <a href="mailto:[email protected]">James Strachan</a>
*/
public class StaticMethodCallExpression extends Expression implements MethodCall {

private ClassNode ownerType;
private final String method;
private final Expression arguments;
private MetaMethod metaMethod = null;

public StaticMethodCallExpression(ClassNode type, String method, Expression arguments) {
ownerType = type;
this.method = method;
this.arguments = arguments;
}

public void visit(GroovyCodeVisitor visitor) {
visitor.visitStaticMethodCallExpression(this);
}

public Expression transformExpression(ExpressionTransformer transformer) {
Expression ret = new StaticMethodCallExpression(getOwnerType(), method, transformer.transform(arguments));
ret.setSourcePosition(this);
ret.copyNodeMetaData(this);
return ret;
}

public ASTNode getReceiver() {
return ownerType;
}

public String getMethodAsString() {
return method;
}

public Expression getArguments() {
return arguments;
}

public String getMethod() {
return method;
}

public String getText() {
return getOwnerType().getName() + "." + method + arguments.getText();
}

public String toString() {
return super.toString() + "[" + getOwnerType().getName() + "#" + method + " arguments: " + arguments + "]";
}

public ClassNode getOwnerType() {
return ownerType;
}

public void setOwnerType(ClassNode ownerType) {
this.ownerType = ownerType;
}

public void setMetaMethod(MetaMethod metaMethod) {
this.metaMethod = metaMethod;
}

public MetaMethod getMetaMethod() {
return metaMethod;
}

// GRECLIPSE add
public void setSourcePosition(ASTNode node) {
super.setSourcePosition(node);
if (getNameEnd() < 1 && node.getEnd() > 0) {
if (node instanceof MethodCallExpression) {
node = ((MethodCallExpression) node).getMethod();
} else if (node instanceof BinaryExpression) {
// likely "import static foo.Bar.setBaz; baz = null"
node = ((BinaryExpression) node).getLeftExpression();
}/* else if (node instanceof VariableExpression) {
// likely "import static foo.Bar.getBaz; def x = baz"
}*/
setNameStart(node.getStart());
setNameEnd((node instanceof StaticMethodCallExpression ?
((StaticMethodCallExpression) node).getMethod().length() : node.getEnd()) - 1);
}
}
// GRECLIPSE end
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,27 @@ final class SemanticHighlightingTests extends GroovyEclipseTestSuite {
new HighlightedTypedPosition(contents.lastIndexOf('valueOf'), 'valueOf'.length(), STATIC_CALL))
}

@Test // https://github.com/groovy/groovy-eclipse/issues/545
void testStaticMethods5() {
addGroovySource '''\
class Util {
static def getSomething() { value }
static void setSomething(value) { }
}
''', 'Util', 'pack'

String contents = '''\
import static pack.Util.*
def thing = something
something = null
'''.stripIndent()

assertHighlighting(contents,
new HighlightedTypedPosition(contents.indexOf('thing'), 'thing'.length(), VARIABLE),
new HighlightedTypedPosition(contents.indexOf('something'), 'something'.length(), STATIC_CALL),
new HighlightedTypedPosition(contents.lastIndexOf('something'), 'something'.length(), STATIC_CALL))
}

@Test // GRECLIPSE-1138
void testMultipleStaticMethods() {
String contents = '''\
Expand Down

0 comments on commit c8070b8

Please sign in to comment.