Bug 403028 - EmptyStackExceptions from detail formatter
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 4ec4e6c..166a1ae 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
@@ -366,6 +366,7 @@
 				cfgs.add(createLaunchConfiguration(jp, "a.b.c.StepIntoSelectionWithGenerics"));
 				cfgs.add(createLaunchConfiguration(jp, "a.b.c.ConditionalsNearGenerics"));
 				cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug329294WithGenerics"));
+				cfgs.add(createLaunchConfiguration(jp, "a.b.c.bug403028"));
 				loaded15 = true;
 				waitForBuild();
 	        }
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 59ec565..cbc900c 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -115,6 +115,7 @@
 import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests;
 import org.eclipse.jdt.debug.tests.ui.ViewManagementTests;
 import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests;
+import org.eclipse.jdt.debug.tests.variables.DetailFormatterTests;
 import org.eclipse.jdt.debug.tests.variables.TestAnonymousInspect;
 import org.eclipse.jdt.debug.tests.variables.TestInstanceRetrieval;
 import org.eclipse.jdt.debug.tests.variables.TestIntegerAccessUnboxing15;
@@ -187,6 +188,7 @@
 			addTest(new TestSuite(StepIntoSelectionWithGenerics.class));
 			addTest(new TestSuite(ConditionalBreakpointsWithGenerics.class));
 			addTest(new TestSuite(GenericsEvalTests.class));
+			addTest(new TestSuite(DetailFormatterTests.class));
 		}
 		
 	//Sourcelookup tests
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsWithGenerics.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsWithGenerics.java
index 0527bdc..6d35d83 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsWithGenerics.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsWithGenerics.java
@@ -236,4 +236,39 @@
 			removeAllBreakpoints();
 		}
 	}
+	
+	/**
+	 * Tests a breakpoint with a condition that includes generics from nested classes
+	 * 
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testBreakpointWithGenericCondition4() throws Exception {
+		String type = "a.b.c.bug403028";
+		try {
+			String condition = "StringBuffer buf = new StringBuffer();"
+					+ "buf.append(\"{\");"
+					+ "Iterator i = this.entrySet().iterator();"
+					+ "boolean hasNext = i.hasNext();"
+					+ "while (hasNext) {"
+					+ "    Entry e = (Entry) (i.next());"
+					+ "    Object key = e.getKey();"
+					+ "    Object value = e.getValue();"
+					+ "    buf.append((key == this ?  \"(this Map)\" : key) + \"=\" + "
+					+ "            (value == this ? \"(this Map)\": value));"
+					+ "    hasNext = i.hasNext();"
+					+ "    if (hasNext)"
+					+ "        buf.append(\"\n,\");"
+					+ "}"
+					+ "buf.append(\"}\");"
+					+ "buf.toString();"
+					+ "return false;";
+			createConditionalLineBreakpoint(10, type, condition, false);
+			//should not suspend or throw an exception
+			launchToBreakpoint(type);
+		}
+		finally {
+			removeAllBreakpoints();
+		}
+	}
 }
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
index ccec22f..4c15a2b 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
@@ -381,4 +381,88 @@
 			terminateAndRemove(thread);
 		}
 	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=401270
+	 * @throws Exception
+	 */
+	public void testMultipleInfixEval14() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+			String snippet = "(true || !(true==true||true!=true&&true))";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of (true || !(true==true||true!=true&&true)) should be true", Boolean.parseBoolean(value.getValueString()));
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=401270
+	 * @throws Exception
+	 */
+	public void testMultipleInfixEval15() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+			String snippet = "(true && true || false || !(true==true||true!=true&&true))";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of (true && true || false || !(true==true||true!=true&&true)) should be true", Boolean.parseBoolean(value.getValueString()));
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=401270
+	 * @throws Exception
+	 */
+	public void testMultipleInfixEval16() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+			String snippet = "(true && true || !(false&&true) || !(true==true||true!=true&&true))";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of (true && true || !(false&&true) || !(true==true||true!=true&&true)) should be true", Boolean.parseBoolean(value.getValueString()));
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testCompoundCondition() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+			String snippet = "(true && true || !(false&&true) || !(true==true||true!=true&&true))";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of (true && true || !(false&&true) || !(true==true||true!=true&&true)) should be true", Boolean.parseBoolean(value.getValueString()));
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/DetailFormatterTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/DetailFormatterTests.java
new file mode 100644
index 0000000..402267b
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/DetailFormatterTests.java
@@ -0,0 +1,338 @@
+/*******************************************************************************
+ * Copyright (c) Mar 12, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.variables;
+
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.IValueDetailListener;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaValue;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.debug.ui.DetailFormatter;
+import org.eclipse.jdt.internal.debug.ui.JavaDetailFormattersManager;
+
+/**
+ * Tests detail formatters
+ * 
+ * @since 3.8.100
+ */
+public class DetailFormatterTests extends AbstractDebugTest {
+	
+	class TestListener implements IValueDetailListener {
+		IValue value;
+		String result;
+		
+		public void detailComputed(IValue value, String result) {
+			this.value = value;
+			this.result = result;
+		}
+		
+		void reset() {
+			value = null;
+			result = null;
+		}
+	}
+	
+	TestListener fListener = new TestListener();
+	
+	/**
+	 * @param name
+	 */
+	public DetailFormatterTests(String name) {
+		super(name);
+	}
+
+	@Override
+	protected IJavaProject getProjectContext() {
+		return get15Project();
+	}
+	
+	@Override
+	protected void tearDown() throws Exception {
+		fListener.reset();
+		super.tearDown();
+	}
+	
+	/**
+	 * Tests a detail formatter made from a large compound expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testCompoundDetails1() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "StringBuffer buf = new StringBuffer();\n"
+					+ "buf.append(\"{\");\n"
+					+ "Iterator i = this.entrySet().iterator();\n"
+					+ "boolean hasNext = i.hasNext();\n"
+					+ "while (hasNext) {\n"
+					+ "    Entry e = (Entry) (i.next());\n"
+					+ "    Object key = e.getKey();\n"
+					+ "    Object value = e.getValue();\n"
+					+ "    buf.append((key == this ?  \"(this Map)\" : key) + \"=\" + \n"
+					+ "            (value == this ? \"(this Map)\": value));\n"
+					+ "    hasNext = i.hasNext();\n"
+					+ "    if (hasNext)\n"
+					+ "        buf.append(\"\n,\");\n"
+					+ "}\n"
+					+ "buf.append(\"}\");\n"
+					+ "return buf.toString();";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from a small compound expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testCompoundDetails2() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "StringBuffer buf = new StringBuffer();\n"
+					+ "buf.append(this);\n"
+					+ "return buf.toString();";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from a small compound expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testSimpleDetails1() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "return toString();";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from a small compound expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testSimpleDetails2() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "return \"map test detail formatter [\" + toString() + \"]\";";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from an infix expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testInfixDetails1() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "return (true && true || !(false&&true) || !(true==true||true!=true&&true));";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+			assertTrue("The returned value from (true && true || !(false&&true) || !(true==true||true!=true&&true)) should be true", 
+					Boolean.parseBoolean(fListener.result));
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from an infix expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testInfixDetails2() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "return !true;";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+			assertFalse("The returned value from !true should be false", Boolean.parseBoolean(fListener.result));
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+	
+	/**
+	 * Tests a detail formatter made from an infix expression
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
+	 * @throws Exception
+	 */
+	public void testInfixDetails3() throws Exception {
+		IJavaThread thread = null;
+		DetailFormatter formatter = null;
+		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
+		try {
+			String typename = "a.b.c.bug403028";
+			createLineBreakpoint(10, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "return !(true==true||true!=true&&true);";
+			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
+			jdfm.setAssociatedDetailFormatter(formatter);
+			IJavaVariable var = thread.findVariable("map");
+			assertNotNull("the variable 'map' must exist in the frame", var);
+			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
+			long timeout = System.currentTimeMillis()+5000;
+			while(fListener.value == null && System.currentTimeMillis() < timeout) {
+				Thread.sleep(100);
+			}
+			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
+			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
+					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
+			assertNotNull("The computed value of the detail should not be null", fListener.result);
+			assertFalse("The returned value from !(true==true||true!=true&&true) should be false", Boolean.parseBoolean(fListener.result));
+		}
+		finally {
+			jdfm.removeAssociatedDetailFormatter(formatter);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug403028.java b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug403028.java
new file mode 100644
index 0000000..fc1b667
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug403028.java
@@ -0,0 +1,12 @@
+package a.b.c;
+import java.util.LinkedHashMap;
+import java.util.Map;
+public class bug403028 {
+	public static void main(String[] args) {
+		Map<String, Integer> map = new LinkedHashMap<String, Integer>();
+        map.put("one", 1);
+        map.put("two", 2);
+        map.put("three", 3);
+        System.out.println(map); // breakpoint here
+	}
+}
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
index 0b62a2f..3f18ea4 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
@@ -758,7 +758,9 @@
 	 */
 	@Override
 	public void endVisit(CompilationUnit node) {
-
+		while(!fStack.isEmpty()) {
+			storeInstruction();
+		}
 	}
 
 	/**
@@ -2724,16 +2726,10 @@
 		if (hasErrors()) {
 			return false;
 		}
-		//if we end up storing multiple known extended operands, push the last instruction
-		if(operatorNumber > 1) {
-			storeInstruction();
-		}
+		
 		iterator = extendedOperands.iterator();
 
-		if ((char0 == '&' && char1 == '&') || (char0 == '|' && char1 == '|')) { // and
-																				// and
-																				// operator
-
+		if ((char0 == '&' && char1 == '&') || (char0 == '|' && char1 == '|')) { 
 			boolean isOrOr = char0 == '|';
 
 			ConditionalJump[] conditionalJumps = new ConditionalJump[operatorNumber];