Bug 549394 - Debugger variable hover does not work in static initializer

JavaDebugHover.getHoverInfo2(ITextViewer, IRegion) must consider
IInitializer as possible parent scope (not only IMethod).

Change-Id: Icbfda472721c0fba1867cb9f6d20d5888ceea9de
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug549394.java b/org.eclipse.jdt.debug.tests/java8/Bug549394.java
new file mode 100644
index 0000000..b471f9c
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug549394.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ *  Copyright (c) 2019 Andrey Loskutov and others.
+ *
+ *  This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License 2.0
+ *  which accompanies this distribution, and is available at
+ *  https://www.eclipse.org/legal/epl-2.0/
+ *
+ *  SPDX-License-Identifier: EPL-2.0
+ *
+ *  Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+public class Bug549394 {
+
+	static {
+		String local = "v0";
+		System.out.println(local);
+	}
+
+	public static void main(String[] args) {
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
index f0db582..3086de1 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
@@ -472,6 +472,7 @@
 	    		cfgs.add(createLaunchConfiguration(jp, "EvalTestIntf18"));
 				cfgs.add(createLaunchConfiguration(jp, "EvalIntfSuperDefault"));
 				cfgs.add(createLaunchConfiguration(jp, "DebugHoverTest18"));
+				cfgs.add(createLaunchConfiguration(jp, "Bug549394"));
 				cfgs.add(createLaunchConfiguration(jp, "Bug541110"));
 				cfgs.add(createLaunchConfiguration(jp, "ClosureVariableTest_Bug542989"));
 				cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointInLocalClass"));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
index ac271dd..1abb501 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
@@ -146,6 +146,41 @@
 		}
 	}
 
+	public void testResolveInStaticInit() throws Exception {
+		final String typeName = "Bug549394";
+		final String expectedMethod1 = "<clinit>";
+		final int framesNumber1 = 1;
+		final int bpLine1 = 18;
+
+		IJavaBreakpoint bp1 = createLineBreakpoint(bpLine1, "", typeName + ".java", typeName);
+		bp1.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		IFile file = (IFile) bp1.getMarker().getResource();
+		assertEquals(typeName + ".java", file.getName());
+
+		IJavaThread thread = null;
+		try {
+			thread = launchToBreakpoint(typeName);
+			CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod1, framesNumber1, file, thread);
+
+			JavaDebugHover hover = new JavaDebugHover();
+			hover.setEditor(part);
+
+			Map<String, Region> offsets = new LinkedHashMap<>();
+			offsets.put("local", new Region(657, "local".length()));
+
+			Set<Entry<String, Region>> entrySet = offsets.entrySet();
+			int startLine = bpLine1;
+			int valueIndex = 0;
+			for (Entry<String, Region> varData : entrySet) {
+				// select variables and validate the hover, going backwards from the breakpoint
+				validateLine(startLine--, valueIndex++, part, hover, varData);
+			}
+		} finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+
 	private CompilationUnitEditor openEditorAndValidateStack(final String expectedMethod, final int expectedFramesNumber, IFile file, IJavaThread thread) throws Exception, DebugException {
 		// Let now all pending jobs proceed, ignore console jobs
 		sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
index 8fd5d6f..a6144d9 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
@@ -25,6 +25,7 @@
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICodeAssist;
 import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.ILocalVariable;
 import org.eclipse.jdt.core.IMethod;
@@ -386,9 +387,13 @@
             		if (javaElement instanceof ILocalVariable) {
             		    ILocalVariable var = (ILocalVariable)javaElement;
             		    IJavaElement parent = var.getParent();
-            		    while (!(parent instanceof IMethod) && parent != null) {
+						while (!(parent instanceof IMethod) && !(parent instanceof IInitializer) && parent != null) {
             		    	parent = parent.getParent();
             		    }
+						if (parent instanceof IInitializer && "()V".equals(frame.getSignature()) //$NON-NLS-1$
+								&& "<clinit>".equals(frame.getMethodName())) { //$NON-NLS-1$
+							return findLocalVariable(frame, var.getElementName());
+						}
             		    if (parent instanceof IMethod) {
             				IMethod method = (IMethod) parent;
             				boolean equal = false;