Search code examples
eclipsepluginseclipse-plugineclipse-cdtabstract-syntax-tree

Eclipse CDT ASTRewrite NPE


I am developing a Eclipse plugin which should rewrite some .c source files. I am using the Eclipse CDT AST parser, but I am facing a NPE when trying to save the adjustments to the AST. I obtain the IFile(_file) to parse from a project of the active workspace. When executing the code below I am facing a NPE below. NPE is thrown at: Change c = rw.rewriteAST();

Map<String, String> definedSymbols = new HashMap<String, String>();
String[] includePaths = new String[0];
IScannerInfo info = new ScannerInfo(definedSymbols, includePaths);
IParserLogService log = new DefaultLogService();
IncludeFileContentProvider emptyIncludes = IncludeFileContentProvider.getEmptyFilesProvider();
int opts = 8;
            
final IASTTranslationUnit tu =  GCCLanguage.getDefault().getASTTranslationUnit(FileContent.create(_file), info, emptyIncludes, null, opts, log);
final ASTRewrite rw = ASTRewrite.create(tu);
tu.accept(new ASTVisitor(true){
                
        @Override
        public int visit(IASTStatement statement){
            if(test) {
                test = false;
                rw.insertBefore(statement.getParent(), statement, rw.createLiteralNode("int i = 3;"), null);
            }
            return PROCESS_CONTINUE;
        }
});

Change c = rw.rewriteAST();
c.perform(new NullProgressMonitor());

java.lang.NullPointerException at org.eclipse.cdt.internal.formatter.ChangeFormatter.formatChangedCode(ChangeFormatter.java:95) at org.eclipse.cdt.internal.core.dom.rewrite.changegenerator.ChangeGenerator.generateChange(ChangeGenerator.java:119) at org.eclipse.cdt.internal.core.dom.rewrite.changegenerator.ChangeGenerator.generateChange(ChangeGenerator.java:107) at org.eclipse.cdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.rewriteAST(ASTRewriteAnalyzer.java:29) at org.eclipse.cdt.core.dom.rewrite.ASTRewrite.rewriteAST(ASTRewrite.java:213) at sheaperdexecuter.AstParser.parse(AstParser.java:155) at sheaperdexecuter.parts.SheaperdView$3.mouseDown(SheaperdView.java:140) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:196) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4209) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1043) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4026) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3626) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1157) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046) at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155) at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:644) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:653) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590) at org.eclipse.equinox.launcher.Main.run(Main.java:1461) at org.eclipse.equinox.launcher.Main.main(Main.java:1434)

A nearly identical problem is mention here: Eclipse CDT ASTRewrite not working The answer to that question is to make sure that the program is running on an osgi framework. In my case the program is a eclipse plugin but I am still facing this NPE.

Can there by a problem with CDT? I am adding CDT via jar (org.eclipse.cdt.core_6.9.0.201909091953.jar) using the Runtime configuration tab of the plugin. (I would have added it to the Dependencies tab, but it is not available there)

//EDIT:

I have researched further in the CDT source code and in my case the CCorePlugin seems to not be initialized. If I call CCorePlugin.getDefault(); I get null returned. I think this causes the exception mentioned above. Do I need to bootstrap the CCorePlugin in any way?


Solution

  • The problem was due to the fact that I added CDT via .jar using the Runtime configuration tab of the plugin.

    My calls to the CDT environment (CCorePlugin, CoreModel, etc.) ended up not being related to the CDT running in the executing eclipse. Therefore I got NPE's on CoreModel and stuff.

    I solved the problem by cloning the CDT source repo (https://git.eclipse.org/r/cdt/org.eclipse.cdt.git) and importing the projects to my Eclipse Committers IDE. (As explained here: https://wiki.eclipse.org/Getting_started_with_CDT_development#Setting_up_the_Sources)

    Afterwards I was able to add CDT to the Dependencies configuration tab of the plugin: Eclipse plugin CDT dependency

    After the dependency has been added the NPE's were gone and I could access the correct Instances of the workspace related models etc..

    I hope this helps someone as it took me some hours to get the Eclipse plugin with CDT bootstrapped.