I am trying to expose a expression engine built on top of groovy for end users. I have some excel style keywords and user can use variables within those keywords (which need to be substituted at runtime) for evaluation.
example, static keyword FIRSTCHAR(varName) will return the first character of a string. I have got this to work in a way.
Current Implementation
I have overridden the groovy class loader to create a compilation unit with an overridden PrimaryClassNodeOperation something like
class MyGroovyClassLoader extends GroovyClassLoader {
protected CompilationUnit createCompilationUnit(
CompilerConfiguration config, CodeSource source) {
CompilationUnit cu = super.createCompilationUnit(config, source);
cu.addPhaseOperation(new PrimaryClassNodeOperation(){
#Override
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
throws CompilationFailedException {
source.getAST().getStatementBlock().visit(visitor);
}
}, Phases.SEMANTIC_ANALYSIS);
return cu;
}
}
The visitor then recognizes the static expression and variable expression. However, using this approach I am having difficulties in
1) Supporting variable names with dot (.) since dot is considered a property expression. Can I during this phase keep the property expression as variable expression.
2) Also, for an expression like (left(name,1)=='S' && right(name,1)=='n') [first character in name is s and last is n] - I want the equal to check to be single equals rather than double equals, and/AND instead of && or .and() so something like (left(name,1)='S' and right(name,1)='n')
What's the best way to achieve such customizations?
The best approach would be to use a custom parser (since you dont want your users to write any groovy) and then use groovy to actually implement the back-end
eg: Very indicative, your implementation can vary
(left(name,1)='S')
For the snipet above, tokens could be method:left, args:((var:name),(val:1)), exp:EQUALS, val:'S'
Have a map at the back which equates your tokens to groovy equivalents
You could then be fire your parsed tokens against a groovy class, of course the methods and arguments dont exist, use some groovy tricks to translate it to your actual implementation 1
Related
Antlr4 creates methods inside extends Parser, which have names the same as rules. For example, if I have rule named "program" in my grammar, it will create method program(). I can call this method, to do parsing.
But what if I wish to select starting rule at runtime?
I looked at implementation and found the beginning
public final ProgramContext program() throws RecognitionException {
ProgramContext _localctx = new ProgramContext(_ctx, getState());
enterRule(_localctx, 0, RULE_program);
it implies, that I can't select rule by name or index, because I need two things simultaneously: ProgramContext class and RULE_program constant.
Is it possible in fact?
Can I define some default rule and call it automatically?
All parser grammar rules are implemented by methods in the generated parser. If your grammar defines
program : .... ;
statemt : .... ;
the grammar will have methods
public final ProgramContext program() throws RecognitionException ....
public final StatemtContext statemt() throws RecognitionException ....
Either can be called as the start rule for evaluating a token stream.
See this answer suggesting a way to programmatically identify parser rules.
No, this is not possible with the generated parser. However, look in the ParserInterpreter class (which allows to specify the start rule index). This class emulates the real parser but works differently than that and is probably not what you want, but maybe it gives you an idea.
As I understand you can choose any starting rule via reflection. I suggest the following code on Java as an example:
Method startMethod = parser.getClass().getMethod("customStartRule", new Class[] {});
ParserRuleContext ast = (ParserRuleContext)startMethod.invoke(parser, new Object[] {});
All start rules you can find in ruleNames array in generated parser.
C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.
If I have a class like this:
class MyClass
{
public SomeOtherClass MyProperty { get; set; }
public void MyMethod()
{
var aLocalVariable = 12;
}
}
I can use the operator like this:
// with class name:
var s = nameof(MyClass); // s == "MyClass"
// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"
// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"
// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".
This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.
Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?
It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.
See this library: https://github.com/strangeway-org/nameof
The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/
Usage example:
public class NameOfTest {
#Test
public void direct() {
assertEquals("name", $$(Person.class, Person::getName));
}
#Test
public void properties() {
assertEquals("summary", Person.$(Person::getSummary));
}
}
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
You can't.
You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.
The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.
As for local variables, it's not possible at all.
You can't.
If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.
I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof
You can simply use it like this:
Name.of(MyClass.class, MyClass::getProperty)
which would just return the String
"property"
It's also on , so you can add it to your project like this:
<dependency>
<groupId>de.mobiuscode.nameof</groupId>
<artifactId>nameof</artifactId>
<version>1.0</version>
</dependency>
or for Gradle:
implementation 'de.mobiuscode.nameof:nameof:1.0'
I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.
I also created a blog post about the library with more details.
Lombok has an experimental feature #FieldNameConstants
After adding annotation you get inner type Fields with field names.
#FieldNameConstants
class MyClass {
String myProperty;
}
...
String s = MyClass.Fields.myProperty; // s == "myProperty"
I would like to access the usual reflection properties of a specific method without relying on Strings.
Is there any way to get from the method-Identifier to its reflection properties, like parameter types?
void run() {
java.lang.reflect.Method m = myMethod.getMethod(); // how?
Class<?>[] argClasses = m.getParameterTypes();
}
int myMethod(String arg) {
// ...
}
The piece myMethod.getMethod() is not valid. It is my way of saying "get from the method-identifier to the java.lang.reflect.Method object".
The string-way I do not want to use would be similar to m = getClass().getDeclaredMethod("myMethod", ...)
I use myMethod like a regular identifier and not as a String, i.e. "myMethod". I think this would be beneficial for refactoring, where someone renames myMethod to hisMethod -- the relation via the String-name would break, where the relation via the identifier would be refactored as well.
In java methods aren't first class citizens, so there is no solutions in Java for this problem.
Yet I had a similar problem and forged a small tool named picklock for this purpose.
I'm aware that it is possible to use Java defined static methods in Lua, due to the section "Libraries of Java Functions" on http://luaj.org/luaj/README.html.
However I am struggling to find out how I can use the same for instance methods, I have a shortened example here:
private static class CallbackStore {
public void test(final String test) {
}
}
(I am aware that I can use a static method here as well, but it is not possible with the real life scenario)
I am using the following Lua code:
-- Always name this function "initCallbacks"
function initCallbacks(callbackStore)
callbackStore.test("test")
end
Which does not work as it is expecting userdata back, but I give it a string.
And I call the Lua code like this:
globals.load(new StringReader(codeTextArea.getText()), "interopTest").call();
CallbackStore callbackStore = new CallbackStore();
LuaValue initCallbacks = globals.get("initCallbacks");
initCallbacks.invoke(CoerceJavaToLua.coerce(callbackStore));
where the Lua code is returned by codeTextArea.getText()
Bottom line of my question is, how do I make my code running with test as an instance method?
When accessing member functions (in Lua objects in general, not just luaj) you have to provide the this argument manually as the first argument like so:
callbackStore.test(callbackStore,"test")
Or, you can use the shorthand notation for the same thing:
callbackStore:test("test")
I am trying to do a regular expression in python that matches every method signature in a java file with the preceding comments (if comments exist). But at the same time, I dont want it to match class attribute declaration.
my code is:
st:'''
/**
class attribute comments
*/
private Type class_attribute1;
private Type class_attribute2;
/**
* method1 comments.
*/
public Returnvalue method1(arguments OR no arguments) {
method1 body
}
private Returnvalue method2(arguments OR no arguments) {
method2 body
}'''
import re
print re.findall(r"([/][*].*?[*][/].*?(public|private|protected).*?{|\s(public|private|protected).*?{)", st, re.DOTALL)
but it also print the class attribute comments and declaration!
any help would be appreciated
1) Your regex (public|private|protected).* is too broad - it can't distinguish between class attributes (which end in ; and cannot contain [(){}]) and method prototypes (which must contain parentheses (..) and then a body {...} and cannot end in ; )
So just write a better regex.
2) Also, your regex will need capture groups. Then don't use re.findall, use a match object and only extract the group you want, i.e. the actual declaration