Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 315732

Summary: [formatter] NullPointerException (always) on inserting a custom template proposal into java code when "Use code formatter" is on
Product: [Eclipse Project] JDT Reporter: Age Mooy <age.mooy>
Component: CoreAssignee: Frederic Fusier <frederic_fusier>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: P3 CC: amj87.iitr, d.m, daniel_megert, jarthana, markus.kell.r, Olivier_Thomann, satyam.kandula, srikanth_sankaran
Version: 3.6   
Target Milestone: 3.6.1   
Hardware: All   
OS: All   
Whiteboard:
Attachments:
Description Flags
Proposed patch none

Description Age Mooy CLA 2010-06-04 04:15:50 EDT
Build Identifier: 20100527-0614

I have some custom templates and whenever I try to insert one of them, I get an unhandled nullpointer exception. I looked at the definition and noticed the "Use code formatter" checkbox. When I turn that off, the exception no longer occurs

See event details pasted below.

The text of my custom template (a seperator comment) is:

// ============================================================================
// ${cursor}
// ============================================================================



Full details:

eclipse.buildId=I20100520-1744
java.version=1.6.0_20
java.vendor=Apple Inc.
BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US
Framework arguments:  -product org.eclipse.epp.package.java.product -keyring /Users/age/.eclipse_keyring -showlocation
Command-line arguments:  -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.java.product -keyring /Users/age/.eclipse_keyring -showlocation


Error
Fri Jun 04 09:54:53 CEST 2010
Unhandled event loop exception

java.lang.NullPointerException
at org.eclipse.jdt.internal.formatter.Scribe.getCurrentIndentation(Scribe.java:878)
at org.eclipse.jdt.internal.formatter.Scribe.printLineComment(Scribe.java:2672)
at org.eclipse.jdt.internal.formatter.Scribe.printComment(Scribe.java:2512)
at org.eclipse.jdt.internal.formatter.Scribe.printComment(Scribe.java:2349)
at org.eclipse.jdt.internal.formatter.CodeFormatterVisitor.visit(CodeFormatterVisitor.java:3088)
at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.traverse(CompilationUnitDeclaration.java:658)
at org.eclipse.jdt.internal.formatter.CodeFormatterVisitor.format(CodeFormatterVisitor.java:811)
at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.formatCompilationUnit(DefaultCodeFormatter.java:241)
at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.probeFormatting(DefaultCodeFormatter.java:458)
at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.format(DefaultCodeFormatter.java:169)
at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.format(DefaultCodeFormatter.java:146)
at org.eclipse.jdt.internal.corext.util.CodeFormatterUtil.format2(CodeFormatterUtil.java:227)
at org.eclipse.jdt.internal.corext.util.CodeFormatterUtil.format2(CodeFormatterUtil.java:254)
at org.eclipse.jdt.internal.corext.template.java.JavaFormatter.format(JavaFormatter.java:349)
at org.eclipse.jdt.internal.corext.template.java.JavaFormatter.internalFormat(JavaFormatter.java:283)
at org.eclipse.jdt.internal.corext.template.java.JavaFormatter.format(JavaFormatter.java:263)
at org.eclipse.jdt.internal.corext.template.java.JavaContext.evaluate(JavaContext.java:193)
at org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateProposal.apply(TemplateProposal.java:201)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertProposal(CompletionProposalPopup.java:928)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertSelectedProposalWithMask(CompletionProposalPopup.java:879)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.verifyKey(CompletionProposalPopup.java:1305)
at org.eclipse.jface.text.contentassist.ContentAssistant$InternalListener.verifyKey(ContentAssistant.java:806)
at org.eclipse.jface.text.TextViewer$VerifyKeyListenersManager.verifyKey(TextViewer.java:489)
at org.eclipse.swt.custom.StyledTextListener.handleEvent(StyledTextListener.java:65)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3764)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1343)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1366)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1351)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1163)
at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5945)
at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5644)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3764)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1343)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1366)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1351)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1380)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1376)
at org.eclipse.swt.widgets.Canvas.sendKeyEvent(Canvas.java:416)
at org.eclipse.swt.widgets.Control.doCommandBySelector(Control.java:938)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:5054)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
at org.eclipse.swt.internal.cocoa.NSResponder.interpretKeyEvents(NSResponder.java:56)
at org.eclipse.swt.widgets.Composite.keyDown(Composite.java:560)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4964)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
at org.eclipse.swt.widgets.Widget.callSuper(Widget.java:220)
at org.eclipse.swt.widgets.Widget.windowSendEvent(Widget.java:1919)
at org.eclipse.swt.widgets.Shell.windowSendEvent(Shell.java:2008)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:5026)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
at org.eclipse.swt.widgets.Display.applicationSendEvent(Display.java:4568)
at org.eclipse.swt.widgets.Display.applicationProc(Display.java:4645)
at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
at org.eclipse.swt.internal.cocoa.NSApplication.sendEvent(NSApplication.java:115)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3262)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)


Reproducible: Always

Steps to Reproduce:
1. type the letters linked to my custom template
2.type Ctrl-Space
3.boom
Comment 1 Dani Megert CLA 2010-06-04 04:35:10 EDT
This works in 3.5.2.

Please investigate which kind of templates are affected by this and how risky a fix would be.
Comment 2 Ayushman Jain CLA 2010-06-04 04:43:42 EDT
Frederic, can you have a look at why the NPE is being thrown? Thanks.
Comment 3 Frederic Fusier CLA 2010-06-04 07:02:46 EDT
Created attachment 171084 [details]
Proposed patch

This is a really peculiar test case which cannot occurs while formatting a compilation unit or a selection in the editor. Only direct callers of CodeFormatter.format(...) API method are concerned when the given source only contains several (at least 2) contiguous line comments. Hence concerned templates are only those containing this kind of code snippet...

As you can see, the fix is really safe as it just adds a null check in the getCurrentIndentation(char[], int) method.
Comment 4 Olivier Thomann CLA 2010-06-04 08:21:03 EDT
Patch looks good.
Comment 5 Frederic Fusier CLA 2010-06-04 10:14:56 EDT
Here are some additional info:
1) the bug was introduced between 3.6M3 and 3.6M4 while fixing bug 293300
2) there's a possible workaround. Add one or several whitespace(s) characters at 
   the beginning of each line comment in the template, e.g.
 // ============================================================================
 // ${cursor}
 // ============================================================================
   And then the NPE won't occur anymore without changing the output while 
   inserting it...
Comment 6 Frederic Fusier CLA 2010-06-04 10:21:35 EDT
(In reply to comment #5)
> Here are some additional info:
> 1) the bug was introduced between 3.6M3 and 3.6M4 while fixing bug 293300
> 2) there's a possible workaround. Add one or several whitespace(s) characters
> at 
>    the beginning of each line comment in the template, e.g.
>  //
> ============================================================================
>  // ${cursor}
>  //
> ============================================================================
>    And then the NPE won't occur anymore without changing the output while 
>    inserting it...

Let's say one '=' less to have a pretty output:
 // ===========================================================================
 // ${cursor}
 // ===========================================================================
Comment 7 Olivier Thomann CLA 2010-06-04 10:35:42 EDT
Too late for 3.6.
There is a workaround and this only fails using snippets and not during page formatting or on save.

The patch looks good and will be released for 3.6.1.
Comment 8 Age Mooy CLA 2010-06-04 11:10:43 EDT
Thanks for the workaround. I changed my template and the problem is sufficiently solved for me. I'm totally impressed by your response time, thanks !
Comment 9 Frederic Fusier CLA 2010-06-22 10:21:14 EDT
(In reply to comment #3)
> Created an attachment (id=171084) [details]
> Proposed patch
> 
Released for 3.6.1 in R3_6_maintenance stream.
Released for 3.7M1 in HEAD stream.
Comment 10 Dani Megert CLA 2010-08-19 07:06:12 EDT
*** Bug 317836 has been marked as a duplicate of this bug. ***
Comment 11 Jay Arthanareeswaran CLA 2010-08-27 01:12:16 EDT
Verified for 3.6.1 RC2 using build M20100825-0800.
Comment 12 Satyam Kandula CLA 2010-09-14 06:47:40 EDT
Verified for 3.7M2 using build I20100909-1700