0

The problem in found = true; line

public boolean containsBlock(String nodeName, ASTNode node)
{
    boolean found = false;
    if(nodeName.equals("if"))
    {
        node.accept(new ASTVisitor()
        {
            public boolean visit(IfStatement s)
            {
                found = true;
                return false;
            }
        });
    }
    return found;
}

I know that I will be able to access this if I make found a class global variable, but I don't want to do this. Maybe there is another way? I just need to let the other code know that something was found

UPD: Is that code better and will return the right

public boolean containsBlock(Text nodeName, ASTNode node)
{
    final AtomicBoolean flag = new AtomicBoolean(false);
    Thread thread = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            if(nodeName.matches("if"))
            {
                node.accept(new ASTVisitor()
                {
                    public boolean visit(IfStatement s)
                    {
                        flag.set(true);
                        return false;
                    }
                });
            }
            else
                throw new RuntimeException("Unknown NodeName: " + nodeName);
        }
    });
    thread.start();
    try {
        thread.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return flag.get();
}
ivan
  • 287
  • 3
  • 14
  • I don't think this is possible. What are you actually trying to do? I'm feeling an XY problem. – markspace Jun 30 '15 at 08:10
  • @markspace, This is the method for parsing the source code. I'm trying to detect some elements in the `ASTNode` (if statements, cycle statements , block statements and etc). What will we look depends from `nodeName`. If something was found from this in the given part of source code, we should know about it and change flag variable and return the result – ivan Jun 30 '15 at 08:15
  • @ivan your flag is useless. If the code will get executed out-of-order (which is probably the case here, since I suspect either deferred or async call here), you'll get false returned virtually all of the time (unless you have ASTNode processing in another thread, plus it'd have to be *lightning fast*, mind me). If you want the flag to work, you have to e.g. make it a persistent data, by creating an external field for it, and skipping the `return` altogether. Non-linear code (even not multithreading one, visitor pattern included) doesn't work the way synchronous, linear one does. –  Jun 30 '15 at 08:24
  • @ivan it'd be better if you told us *what functionality do you expect the code to provide* and *what library do you use*. Your 2nd code makes no sense for the very same reason first doesn't - the Runnable will just complete instantly, adding the visitor to the node. If you're 100% sure this is the way to achieve what you want, you should wait (block) in containsBlock() method for the notification from visit() method after accept-ing it, and then process the node's tree in another thread to trigger the visit(). I suspect there's a lot easier way to do it, but without a lib ref... –  Jun 30 '15 at 08:52
  • @vaxquis, I got it. I use JDT and want to get all wanted statements (which are wanted depends from `nodeName`, it might be `if`, `for`, `while` or etc statement). But I'm not ready to create a lot of classes extending `ASTVisitor`, because there are a lot of methods which are using ASTVisitor in different purposes. My choice is anonymous classes, but how wait them? – ivan Jun 30 '15 at 09:09
  • @ivan http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait() for notify in one thread , then send the http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify() to the object from the other thread. –  Jun 30 '15 at 09:11
  • http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTVisitor.html See, `public abstract class ASTVisitor extends Object` it means that it processes synchronously? :) – ivan Jun 30 '15 at 09:36
  • @ivan method signature (e.g. `synchronized` keyword) only tells you if it's blocking for synchronous access by default or not; it doesn't say if it will process synchronously or not. IMO you should learn more about threading (at least https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html and other Oracle tutorials) before continuing this pursuit. –  Jul 01 '15 at 14:22
  • possible duplicate of [Why are only final variables accessible in anonymous class?](http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class) –  Jul 01 '15 at 14:24

1 Answers1

3

When you pass a ASTVisitor instance to the ASTNode instance (using the accept method), it doesn't execute your visit method immediately. Therefore, there's no point to attempt to change a local variable of your containsBlock method from within the visit method.

visit will most likely be executed after your containsBlock method has returned, at which point your local found variable will no longer be in the call stack.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Yup. This is exactly the point here IMO. Accessing outer scope for read is one thing - it can be done and is done routinely. Accessing it for write is useless unless the data can be referenced outside, which would constitute a field variable, which wouldn't need any special provisioning to be used inside anonymous. –  Jun 30 '15 at 08:21
  • Huh, but how to make it be executed immediately? – ivan Jun 30 '15 at 08:24
  • 1
    @ivan I'm not fimiliar with these classes, but from the Javadoc I found, `ASTNode` calls the `visit` method of the `ASTVisitor` that was passed to it when you reach the `ASTNode` instance while iterating over the tree. This is a standard visitor design pattern. – Eran Jun 30 '15 at 08:36