Bug 87852 - ASTParser fails when called from another program
Summary: ASTParser fails when called from another program
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal with 7 votes (vote)
Target Milestone: 3.2 M6   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 93948 97444 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-03-11 23:08 EST by Thomas Feng CLA
Modified: 2007-10-24 10:29 EDT (History)
18 users (show)

See Also:


Attachments
Patch allows use of ASTParser to generate bindings outside of Eclipse environment (7.98 KB, text/plain)
2007-09-16 19:33 EDT, Alexei Svitkine CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Feng CLA 2005-03-11 23:08:21 EST
ASTParser in 3.0 can be used in another standalone program to create Eclipse
ASTs without actually running Eclipse. As the documentation says:

  char[] source = ...;
  ASTParser parser = ASTParser.newParser(AST.JLS2);  // handles JLS2 (J2SE 1.4)
  parser.setSource(source);
  CompilationUnit result = (CompilationUnit) parser.createAST(null);

But this doesn't work in 3.1 because ASTParser always gets the plugin object,
and when it is null (in the case of a standalone program), a null pointer
exception is raised.

Please look at JavaCore.getOptions(). In 3.0, it tests if the result of
getPlugin() is null; in 3.1, the test disappears, hence causing the problem.
Comment 1 Olivier Thomann CLA 2005-03-12 10:59:43 EST
You need at least a headless Eclipse. The JDT/Core plugin needs to be initialized.
Comment 2 Olivier Thomann CLA 2005-03-12 11:42:10 EST
Looking at the doc I don't find a reference saying that DOM/AST should work in a
stand-alone application.
Comment 3 Thomas Feng CLA 2005-03-12 17:26:01 EST
I'm just thinking, if the parser CAN work without being called in a plugin, why
it SHOULDN'T? A simple test is easy to add to it, and the fix makes it backward
compatible with 3.0.
Comment 4 Olivier Thomann CLA 2005-03-16 14:56:10 EST
With the new bridging method between the java element and the dom nodes, the
java model needs to be initialized. This means that the JDT/Core plugin needs to
be initialized.
Comment 5 Curtis Cooley CLA 2005-03-31 20:37:21 EST
So is this not going to be fixed? We like to write tests for our parsing code
outside of the environment. We use JUnit and FitNesse. Both sets of tests fail
when we upgrade to 3.1.

Is there a workaround we can use to get our tests running again?
Comment 6 Rodrigo Kumpera CLA 2005-05-27 09:17:25 EDT
(In reply to comment #4)
> With the new bridging method between the java element and the dom nodes, the
> java model needs to be initialized. This means that the JDT/Core plugin needs 
to
> be initialized.

What about making all bridging method return null when JDT/Core is not 
initialized?
Comment 7 Olivier Thomann CLA 2005-06-07 12:57:05 EDT
Close as WONTFIX.
DOM API are designed to work within a headless Eclipse.
Comment 8 Olivier Thomann CLA 2005-09-23 14:45:25 EDT
You need to define your code within a plugin and run your JUnit tests as JUnit
plugin tests. Your plugin would have org.eclipse.jdt.core as a requirement.
Comment 9 Philippe Ombredanne CLA 2005-10-19 22:18:59 EDT
Olivier
I understand this is a hard pb.
I really think this should re-considered though.
Coudl you at least tempora
There is a wealth of treasure available in the JDT core code whic is ready to be
re-used outside of Eclipse.
That would be really sad if none could benefit from it.
In the last week i have talkedd to at least three person that asked about it.
Comment 10 Philippe Ombredanne CLA 2005-10-19 22:19:46 EDT
Could you talk with the team about it?
Comment 11 Mark Proctor CLA 2005-10-19 22:24:02 EDT
I think having ASTParser working outside of eclipse and without the need for all
the dependencies to run a headless eclipse is important. The JDT compiler is
starting to be used outside of eclipse, Tomcat, and we are looking to use it
with Drools, http://drools.org, so it's only natural that projects like these
would like to have access to a powerful tool like ASTParser. I fully understand
that at this time its not practical, but I think this should be marked as a
future item, not as a WONT FIX.
Comment 12 Philippe Ombredanne CLA 2005-10-20 00:45:09 EDT
Sorry but my comments was cut mid-way.
I was asking if you could at least re-open that bug?
Comment 13 Philipe Mulet CLA 2005-10-20 08:30:29 EDT
Reopening. Olivier if the change is small, then we may be able to do it. If not,
keep it for Later.
Comment 14 Sung Kim CLA 2005-12-27 15:12:13 EST
(In reply to comment #13)
> Reopening. Olivier if the change is small, then we may be able to do it. If
> not,
> keep it for Later.
> 

I just added two lines of code to use JDT as a stand alone Java parser.
This might be a quick and dirty fix, but you folks can make it better.

Sung <hunkim@gmail.com>

Index: JavaCore.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v
retrieving revision 1.517
diff -u -r1.517 JavaCore.java
--- JavaCore.java       14 Dec 2005 14:59:11 -0000      1.517
+++ JavaCore.java       27 Dec 2005 20:06:49 -0000
@@ -2569,6 +2569,9 @@
         * @see JavaCorePreferenceInitializer for changing default settings
         */
        public static Hashtable getOptions() {
+               if (getPlugin() == null) {
+                       return new Hashtable();
+               }
                return JavaModelManager.getJavaModelManager().getOptions();
        }
Comment 15 Olivier Thomann CLA 2006-01-17 14:56:42 EST
We need to do two things to fix this PR properly.
1) Access to the options when JDT/Core is not initialized.
2) Provide a name environment in order to be able to get bindings. The bridge methods would not work (since the Java model doesn't exist), but we must expose the bindings. Right now this assumes that a java project is available. If JDT/Core is not initialized, there is no java project.
If someone has an API to propose to fix the second point, please speak up.
Comment 16 Olivier Thomann CLA 2006-03-09 10:59:10 EST
*** Bug 93948 has been marked as a duplicate of this bug. ***
Comment 17 Olivier Thomann CLA 2006-03-09 20:08:59 EST
For M6 we can target a solution that would allow the creation of the AST, but no binding would be available.
Comment 18 Olivier Thomann CLA 2006-03-13 20:43:14 EST
Fixed and released in HEAD.
Martin,

Could you please try the next integration build? I could use the ASTParser without running the platform.
Comment 19 Philippe Ombredanne CLA 2006-03-14 17:42:28 EST
Olivier, thanks!
Comment 20 Martin Smolny CLA 2006-03-15 05:33:28 EST
(In reply to comment #18)
> Fixed and released in HEAD.
> Martin,
> 
> Could you please try the next integration build? I could use the ASTParser
> without running the platform.
> 
Yes, it works for me well. Thanks for the quick solution, it helps us very much!
Comment 21 Craig Setera CLA 2006-03-15 08:52:28 EST
Can anyone summarize what will and will not be available due to the lack of bindings when running outside of Eclipse?  I'm somewhat of a newbie on the AST Parser, so I'm not sure what function is included in the bindings.
Comment 22 Olivier Thomann CLA 2006-03-15 09:19:51 EST
Bindings contains the resolved information.
For example if you have a method header like this:

String foo() {
...
}

Then the IMethodBinding for the method foo will tell you that the return type is java.lang.String. Without the bindings, it is impossible to know that String comes from the java.lang package. You could have defined your own class String.

The reason why no bindings are available when used outside of Eclipse is that there is no context to resolve the bindings. Within Eclipse, the java project provides the context.
In order to resolve bindings, we would need to provide a new API that could allow the user to give the context in which the bindings will be resolved. But this is beyond the scope of this bug report.
Comment 23 Jerome Lanneluc CLA 2006-03-28 08:33:06 EST
Verified for 3.2 M6 using build I20060328-0010
Comment 24 Olivier Thomann CLA 2006-03-31 13:34:26 EST
*** Bug 97444 has been marked as a duplicate of this bug. ***
Comment 25 Hitesh CLA 2007-01-15 05:53:31 EST
I m trying to create and parse AST using the following code.  I use eclipse IDE to do so.  I have tried both eclipse 3.1 and 3.2.  When I went through the forum I found few others are also facing the same problem, and reply posted to them was that they may be running it outside eclipse.  In my case I am running it in the eclipse environment.  Pls help.....

Errors that I got:

Exception in thread "main" java.lang.ExceptionInInitializerError
at org.eclipse.jdt.core.JavaCore.getOptions(JavaCore.java:2401)
at org.eclipse.jdt.core.dom.ASTParser.initializeDefaults(ASTParser.java:222)
at org.eclipse.jdt.core.dom.ASTParser.<init>(ASTParser.java:204)
at org.eclipse.jdt.core.dom.ASTParser.newParser(ASTParser.java:109)
at provaCompilatore.parse(provaCompilatore.java:21)
at provaCompilatore.main(provaCompilatore.java:46)
Caused by: java.lang.NullPointerException
at org.eclipse.jdt.internal.core.search.indexing.IndexManager.getJavaPluginWorkingLocation(IndexManager.java:284)
at org.eclipse.jdt.internal.core.search.indexing.IndexManager.<init>(IndexManager.java:50)
at org.eclipse.jdt.internal.core.JavaModelManager.<init>(JavaModelManager.java:671)
at org.eclipse.jdt.internal.core.JavaModelManager.<clinit>(JavaModelManager.java:649)
... 6 more
--------------------------------------


Here my code:
------------------------------


import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;


public class provaCompilatore {
		
	provaCompilatore(){		
	}
		
	public void parse(){
		
		ASTParser parser = ASTParser.newParser(AST.JLS3);		
	}


	public static void main(String[] args) {


		provaCompilatore prova = new provaCompilatore();
		prova.parse();		
	}
}
----------------------------


here the jars I added:


org.eclipse.core.resources_3.1.0.jar
org.eclipse.core.runtime_3.1.1.jar
org.eclipse.jdt.core_3.1.1.jar


Comment 26 Alexei Svitkine CLA 2007-09-16 13:21:38 EDT
Is there another bug open for the issue with setResolveBindings not working in the standalone version of the ASTParser?
Comment 27 Alexei Svitkine CLA 2007-09-16 15:13:14 EDT
From looking at the code, I think the way to solve this problem would be something like:

In CompilationUnitResolver, create an overloaded resolve() method with the new signature:

	public static void resolve(
		ICompilationUnit[] compilationUnits,
		String[] bindingKeys,
		ASTRequestor requestor,
		int apiLevel,
		Map options,
		CancelableNameEnvironment env,
		int flags,
		IProgressMonitor monitor)

Note: The IJavaProject and WorkingCopyOwner parameters have been replaced with a CancelableNameEnvironment parameter. This is fine, since the existing resolve() already creates a CancelableNameEnvironment parameter from those two arguments - so this is an easy change.

Then, add code to create a CancelableNameEnvironment that does not depend on a JavaProject or WorkingCopyOwner. This is the hardest change. It may be necessary to abstract the CancelableNameEnvironment behind an interface.

Finally, change the internalCreateAST() method in ASTParser to generate the CancelableNameEnvironment in the above way, if the project and/or owner wasn't specified. This is an easy change also.

So the bulk of the work, it seems to me, would be adding functionality to create a CancelableNameEnvironment (or something equivalent that would share the same interface) without a project or working copy owner.
Comment 28 Alexei Svitkine CLA 2007-09-16 15:32:46 EDT
Actually...

We don't need a new way to create the environment.

Users of the class can create their own instance of INameEnvironment. The ASTParser could take it as a parameter and would use it when calling the new overloaded resolve() method.

There's already a class that implements INameEnvironment without needing a Project or anything:

org.eclipse.jdt.internal.compiler.batch.FileSystem.java

So users of the ASTParser would just create an instance of FileSystem with the right parameters, and pass it as an INameEnvironment to the ASTParser. This would allow the ASTParser to pass the environment to the CompilationUnitResolver, without needing a project or a working copy.
Comment 29 Alexei Svitkine CLA 2007-09-16 19:33:55 EDT
Created attachment 78520 [details]
Patch allows use of ASTParser to generate bindings outside of Eclipse environment
Comment 30 Alexei Svitkine CLA 2007-09-16 19:36:17 EDT
The above patch implements what I'm talking about.

By allowing the user of an ASTParser to specify the INameEnvironment to use (which does not have to be coming from an eclipse project... see FileSystem class that implements INameEnvironment), setResolveBindings can now work without needing to be part of an active Eclipse environment.
Comment 31 Alexei Svitkine CLA 2007-10-15 17:37:13 EDT
I have opened a new bug for the binding resolution issue:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=87852
Comment 32 Alexei Svitkine CLA 2007-10-15 17:38:44 EDT
Oops, the correct new bug URL is:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=206391
Comment 33 Aaron Jones CLA 2007-10-23 15:48:37 EDT
I am running Eclipse 3.3.0 build I20070625-1500 and it would appear that this fix did not make it into that code base as I continue to receive the java.lang.NoClassDefFoundError: org/eclipse/core/runtime/Plugin error.  Would this fix not have been merged into the 3.3 branch?
Comment 34 Olivier Thomann CLA 2007-10-23 18:20:48 EDT
You still need to provide a bunch of jars on the classpath, but the JavaCore doesn't need to be initialized.
Comment 35 Aaron Jones CLA 2007-10-24 10:29:28 EDT
Thanks for the comment Oliver, that got me on the right track.  The jar's required appear to be as follows:
org.eclipse.core.contenttype_3.*version*.jar
org.eclipse.core.jobs_3.*version*.jar
org.eclipse.core.resources_3.*version*.jar
org.eclipse.core.runtime_3.*version*.jar
org.eclipse.equinox.common_3.*version*.jar
org.eclipse.equinox.preferences_3.*version*.jar
org.eclipse.jdt.core_3.*version*.jar
org.eclipse.osgi.services_3.*version*.jar
org.eclipse.osgi_3.*version*.jar
org.eclipse.text_3.*version*.jar