3.5 maintenance - Fix for 288211
diff --git a/org.eclipse.jdt.apt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.apt.core/META-INF/MANIFEST.MF
index 1cea906..c999d1e 100644
--- a/org.eclipse.jdt.apt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.apt.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.apt.core; singleton:=true
-Bundle-Version: 3.3.201.qualifier
+Bundle-Version: 3.3.302.qualifier
 Bundle-Localization: plugin
 Export-Package: com.sun.mirror.apt,
  com.sun.mirror.declaration,
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
index 59bbb25..8e86472 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 BEA Systems Inc. and others
+ * Copyright (c) 2005, 2009 BEA Systems Inc. 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
@@ -498,6 +498,7 @@
 		parser.setResolveBindings(true);
 		parser.setBindingsRecovery(true);
 		parser.setProject(_javaProject);
+		parser.setIgnoreMethodBodies(true);
 		ICompilationUnit[] units = unit == null ? NO_UNIT : new ICompilationUnit[]{unit};
 		parser.createASTs(units, new String[]{key}, requestor, null);
 		final IBinding result = requestor._result;
@@ -708,6 +709,7 @@
         		parser.setBindingsRecovery(true);
                 parser.setSource(unit);
 				parser.setFocalPosition(0);
+				parser.setIgnoreMethodBodies(true);
                 CompilationUnit resultUnit = (CompilationUnit)parser.createAST(null);
                 _modelCompUnit2astCompUnit.put(unit, resultUnit);
                 return resultUnit;
@@ -853,6 +855,7 @@
 		p.setBindingsRecovery(true);
 		p.setProject( javaProject );
 		p.setKind( ASTParser.K_COMPILATION_UNIT );
+		p.setIgnoreMethodBodies(true);
 		p.createASTs( parseUnits, keys,  requestor, null);
 	}
 	
@@ -881,6 +884,7 @@
 		p.setBindingsRecovery(true);
 		p.setProject( javaProject );
 		p.setKind( ASTParser.K_COMPILATION_UNIT );
+		p.setIgnoreMethodBodies(true);
 		p.createASTs( new ICompilationUnit[]{compilationUnit}, NO_KEYS,  requestor, null);
 		if( AptPlugin.DEBUG ){
 			AptPlugin.trace("created DOM AST for " + compilationUnit.getElementName() ); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.apt.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.apt.tests/META-INF/MANIFEST.MF
index 7d020cf..d76a6b4 100644
--- a/org.eclipse.jdt.apt.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.apt.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.apt.tests; singleton:=true
-Bundle-Version: 3.3.200.qualifier
+Bundle-Version: 3.3.302.qualifier
 Bundle-ClassPath: apt.jar,
  aptext.jar
 Bundle-Activator: org.eclipse.jdt.apt.tests.plugin.AptTestsPlugin
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
index a64e9ba..6e3cc24 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 BEA Systems, Inc. 
+ * Copyright (c) 2005, 2009 BEA Systems, Inc. 
  * 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
@@ -371,8 +371,8 @@
 		// parse the source, parsing runs through the compiler, and this registers the 
 		// file a second time with the Compiler#DebugRequestor 
 		//
-		expectingCompiledClasses(new String[]{"p1.p2.p3.p4.C", "p1.p2.p3.p4.A", "p1.p2.p3.p4.A"}); //$NON-NLS-1$ //$NON-NLS-2$
-		expectingCompilingOrder(new String[]{"p1.p2.p3.p4.C", "p1.p2.p3.p4.A", "p1.p2.p3.p4.A"}); //$NON-NLS-1$ //$NON-NLS-2$
+		expectingCompiledClasses(new String[]{"p1.p2.p3.p4.C", "p1.p2.p3.p4.A"}); //$NON-NLS-1$ //$NON-NLS-2$
+		expectingCompilingOrder(new String[]{"p1.p2.p3.p4.C", "p1.p2.p3.p4.A"}); //$NON-NLS-1$ //$NON-NLS-2$
 		
 		//
 		// now make sure that p1.p2.p3.p4.C is not compiled when A uses NoOp Annotation
@@ -448,14 +448,14 @@
 		
 		fullBuild( project.getFullPath() );
 		expectingNoProblems();
-		expectingCompiledClasses(new String[] {"p1.A", "p1.A", "generatedfilepackage.GeneratedFileTest"}); //$NON-NLS-1 //$NON_NLS-2$
+		expectingCompiledClasses(new String[] {"p1.A", "generatedfilepackage.GeneratedFileTest"}); //$NON-NLS-1 //$NON_NLS-2$
 		
 		// touch A - make sure its public shape changes.
 		env.addClass( srcRoot, "p1", "A", //$NON-NLS-1$ //$NON-NLS-2$
 			modifiedCode );
 		incrementalBuild( project.getFullPath() );
 		expectingNoProblems();
-		expectingCompiledClasses(new String[]{"p1.A", "p1.A"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		expectingCompiledClasses(new String[]{"p1.A"}); //$NON-NLS-1$
 	}
 
 	/**
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
index 7da3d6d..e35498e 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * Copyright (c) 2005, 2009 BEA Systems, Inc.
  * 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
@@ -188,6 +188,7 @@
 		final ASTParser parser = ASTParser.newParser(AST.JLS3);
 		parser.setResolveBindings(true);
 		parser.setProject(javaProj);
+		parser.setIgnoreMethodBodies(true);
 		parser.createASTs(NO_UNIT, new String[]{key}, requestor, null);
 		return requestor._result;
 	}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
index ba8d693..2b7e06c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
@@ -10397,4 +10397,75 @@
 		CompilationUnit unit = (CompilationUnit) root;
 		assertTrue("No problem reported", unit.getProblems().length != 0);
 	}
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=288211
+	 */
+	public void test0715() throws JavaModelException {
+		final char[] source = ("System.out.println()\nint i;\n").toCharArray();
+		ASTParser parser = ASTParser.newParser(AST.JLS3);
+		parser.setKind(ASTParser.K_STATEMENTS);
+		parser.setStatementsRecovery(true);
+		parser.setIgnoreMethodBodies(true);
+		parser.setSource(source);
+		ASTNode root = parser.createAST(null);
+		assertEquals("Not a block", ASTNode.BLOCK, root.getNodeType());
+		Block block = (Block) root;
+		List statements = block.statements();
+		assertEquals("Wrong size", 2, statements.size());
+	}
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=288211
+	 */
+	public void test0716() {
+		String src = "switch (state) {case 4:double M0,M1;}";
+		char[] source = src.toCharArray();
+		ASTParser parser = ASTParser.newParser(AST.JLS3);
+		parser.setKind (ASTParser.K_STATEMENTS);
+		parser.setIgnoreMethodBodies(true);
+		parser.setSource (source);
+		ASTNode result = parser.createAST (null);
+		assertNotNull("no result", result);
+		assertEquals("Wrong type", ASTNode.BLOCK, result.getNodeType());
+		Block block = (Block) result;
+		List statements = block.statements();
+		assertNotNull("No statements", statements);
+		assertEquals("Wrong size", 1, statements.size());
+		final ASTNode node = (ASTNode) statements.get(0);
+		assertEquals("Not a switch statement", ASTNode.SWITCH_STATEMENT, node.getNodeType());
+		SwitchStatement statement = (SwitchStatement) node;
+		statements = statement.statements();
+		assertEquals("wrong size", 2, statements.size());
+		assertEquals("Not a switch case", ASTNode.SWITCH_CASE, ((ASTNode) statements.get(0)).getNodeType());
+		assertEquals("Not a variable declaration statement", ASTNode.VARIABLE_DECLARATION_STATEMENT, ((ASTNode) statements.get(1)).getNodeType());
+	}
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=288211
+	 */
+	public void test0717() throws JavaModelException {
+		final char[] source = ("  class MyCommand extends CompoundCommand\n" + 
+				"  {\n" + 
+				"    public void execute()\n" + 
+				"    {\n" + 
+				"      // ...\n" + 
+				"      appendAndExecute(new AddCommand());\n" + 
+				"      if (condition) appendAndExecute(new AddCommand());\n" + 
+				"    }\n" + 
+				"  }").toCharArray();
+		ASTParser parser = ASTParser.newParser(AST.JLS3);
+		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
+		parser.setStatementsRecovery(false);
+		parser.setIgnoreMethodBodies(true);
+		parser.setSource(source);
+		ASTNode root = parser.createAST(null);
+		assertEquals("Not a type declaration", ASTNode.TYPE_DECLARATION, root.getNodeType());
+		TypeDeclaration typeDeclaration = (TypeDeclaration) root;
+		typeDeclaration.accept(new ASTVisitor() {
+			public boolean visit(MethodDeclaration node) {
+				Block body = node.getBody();
+				assertNotNull(body);
+				assertTrue(body.statements().size() == 0);
+				return true;
+			}
+		});
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BatchASTCreationTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BatchASTCreationTests.java
index 8d30c9d..69c8da0 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BatchASTCreationTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BatchASTCreationTests.java
@@ -2208,4 +2208,71 @@
 			},
 			"LA~B<LC;:1TV;LC;:1TE;>;");
 	}
+	
+	public void testIgnoreMethodBodies1() throws CoreException {
+		this.workingCopies = createWorkingCopies(new String[] {
+				"/P/p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"  public int foo() {\n" +
+				"    int i = 0;\n" + 
+				"  }\n" +
+				"  public int bar() {\n" +
+				"    int i = 0;\n" + 
+				"    new X() /*start*/{\n" +
+				"    }/*end*/;" +
+				"  }\n" +
+				"}",
+			});
+			TestASTRequestor requestor = new TestASTRequestor();
+			ASTParser parser = ASTParser.newParser(AST.JLS3);
+			parser.setIgnoreMethodBodies(true);
+			parser.createASTs(this.workingCopies, new String[] {}, requestor, null);
+			// statement declaring i should not be in the AST
+			assertASTNodesEqual(
+					"package p1;\n" +
+					"public class X {\n" +
+					"  public int foo(){\n" +
+					"  }\n" +
+					"  public int bar(){\n" +
+					"  }\n" +
+					"}\n" +
+					"\n",
+					requestor.asts
+				);
+	}
+	public void testIgnoreMethodBodies2() throws CoreException {
+		this.workingCopies = createWorkingCopies(new String[] {
+				"/P/p1/X.java",
+				"package p1;\n" +
+				"public class X {\n" +
+				"  public int foo() {\n" +
+				"    int i = 0;\n" + 
+				"  }\n" +
+				"  public int bar() {\n" +
+				"    int i = 0;\n" + 
+				"    new X() /*start*/{\n" +
+				"    }/*end*/;" +
+				"  }\n" +
+				"}",
+			});
+			TestASTRequestor requestor = new TestASTRequestor();
+			ASTParser parser = ASTParser.newParser(AST.JLS3);
+			parser.setIgnoreMethodBodies(true);
+			parser.setResolveBindings(true);
+			parser.setProject(getJavaProject("P"));
+			parser.createASTs(this.workingCopies, new String[] {}, requestor, null);
+			// statement declaring i should not be in the AST
+			assertASTNodesEqual(
+					"package p1;\n" +
+					"public class X {\n" +
+					"  public int foo(){\n" +
+					"  }\n" +
+					"  public int bar(){\n" +
+					"  }\n" +
+					"}\n" +
+					"\n",
+					requestor.asts
+				);
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
index a978a27..2e66b4b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
@@ -97,7 +97,7 @@
 //	JavaModelManager.VERBOSE = true;
 //	org.eclipse.jdt.internal.core.search.BasicSearchEngine.VERBOSE = true;
 //	TESTS_PREFIX = "testIgnoreIfBetterNonAccessibleRule";
-//	TESTS_NAMES = new String[] { "testRawUsage" };
+//	TESTS_NAMES = new String[] { "testIgnoreMethodBodies1", "testIgnoreMethodBodies2" };
 //	TESTS_NUMBERS = new int[] { 118823 };
 //	TESTS_RANGE = new int[] { 16, -1 };
 }
@@ -4323,4 +4323,67 @@
 		deleteProject("P1");
 	}
 }
+/*
+ * Ensure that the option ICompilationUnit.IGNORE_METHOD_BODIES is honored
+ */
+public void testIgnoreMethodBodies1() throws CoreException {	
+	setWorkingCopyContents(
+		"package p1;\n" +
+		"import p2.*;" +
+		"public class X {\n" +
+		"  public int foo() {\n" + // force an error by not returning
+		"    int i = 0;\n" + 
+		"  }\n" +
+		"}");
+	org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(AST.JLS3, ICompilationUnit.IGNORE_METHOD_BODIES, null, null);
+	// X.foo() not returning any value should not be reported
+	assertProblems("Working copy should have problems:",
+			"----------\n" +
+			"1. WARNING in /Reconciler/src/p1/X.java (at line 2)\n"+
+			"	import p2.*;public class X {\n" +
+			"	       ^^\n" +
+			"The import p2 is never used\n"+
+			"----------\n"
+		);
+	// statement declaring i should not be in the AST
+	assertASTNodeEquals(
+			"Unexpected participant ast",
+			"package p1;\n" +
+			"import p2.*;\n" +
+			"public class X {\n" +
+			"  public int foo(){\n" +
+			"  }\n" +
+			"}\n",
+			ast
+		);
+}
+public void testIgnoreMethodBodies2() throws CoreException {	
+	setWorkingCopyContents(
+		"package p1;\n" +
+		"import p2.*;" +
+		"public class X {\n" +
+		"  public void foo() {\n" +
+		"    int i = 0;\n" + 
+		"  }\n" +
+		"  public int bar() {\n" +
+		"    int i = 0;\n" + 
+		"    new X() /*start*/{\n" +
+		"    }/*end*/;" +
+		"  }\n" +
+		"}");
+	org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(AST.JLS3, ICompilationUnit.IGNORE_METHOD_BODIES, null, null);
+	// methods with anonymous classes should have their statements intact
+	assertASTNodeEquals(
+			"Unexpected ast",
+			"package p1;\n" +
+			"import p2.*;\n" +
+			"public class X {\n" +
+			"  public void foo(){\n" +
+			"  }\n" +
+			"  public int bar(){\n" +
+			"  }\n" +
+			"}\n",
+			ast
+		);
+}
 }
diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters
index 3855e63..a9fe599 100644
--- a/org.eclipse.jdt.core/.settings/.api_filters
+++ b/org.eclipse.jdt.core/.settings/.api_filters
@@ -1,5 +1,21 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jdt.core" version="2">
+    <resource path="dom/org/eclipse/jdt/core/dom/ASTParser.java" type="org.eclipse.jdt.core.dom.ASTParser">
+        <filter id="1142947843">
+            <message_arguments>
+                <message_argument value="3.5.2"/>
+                <message_argument value="setIgnoreMethodBodies(boolean)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="model/org/eclipse/jdt/core/ICompilationUnit.java" type="org.eclipse.jdt.core.ICompilationUnit">
+        <filter id="1210056707">
+            <message_arguments>
+                <message_argument value="3.5.2"/>
+                <message_argument value="IGNORE_METHOD_BODIES"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="model/org/eclipse/jdt/core/ITypeRoot.java" type="org.eclipse.jdt.core.ITypeRoot">
         <filter id="403853384">
             <message_arguments>
@@ -7,14 +23,6 @@
             </message_arguments>
         </filter>
     </resource>
-    <resource path="search/org/eclipse/jdt/core/search/ReferenceMatch.java" type="org.eclipse.jdt.core.search.ReferenceMatch">
-        <filter id="338792546">
-            <message_arguments>
-                <message_argument value="org.eclipse.jdt.core.search.ReferenceMatch"/>
-                <message_argument value="localElement()"/>
-            </message_arguments>
-        </filter>
-    </resource>
     <resource path="model/org/eclipse/jdt/core/compiler/CompilationParticipant.java" type="org.eclipse.jdt.core.compiler.CompilationParticipant">
         <filter id="388100214">
             <message_arguments>
@@ -29,4 +37,12 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="search/org/eclipse/jdt/core/search/ReferenceMatch.java" type="org.eclipse.jdt.core.search.ReferenceMatch">
+        <filter id="338792546">
+            <message_arguments>
+                <message_argument value="org.eclipse.jdt.core.search.ReferenceMatch"/>
+                <message_argument value="localElement()"/>
+            </message_arguments>
+        </filter>
+    </resource>
 </component>
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index 92fc6e1..8cf1a19 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -49,7 +49,9 @@
 <h2>What's new in this drop</h2>
 
 <h3>Problem Reports Fixed</h3>
-<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643">277643</a>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=288211">288211</a>
+APT uses a lot of memory
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643">277643</a>
 Generics compile error
 
 <a name="v_978_R35x"></a>
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 7cacbb8..c4341db 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -760,16 +760,15 @@
 
 		long analyzeStart = System.currentTimeMillis();
 		this.stats.resolveTime += analyzeStart - resolveStart;
-
-		// flow analysis
-		unit.analyseCode();
+		
+		// no need to analyse or generate code if statements are not required
+		if (!this.options.ignoreMethodBodies) unit.analyseCode(); // flow analysis
 
 		long generateStart = System.currentTimeMillis();
 		this.stats.analyzeTime += generateStart - analyzeStart;
-
-		// code generation
-		unit.generateCode();
-
+	
+		if (!this.options.ignoreMethodBodies) unit.generateCode(); // code generation
+		
 		// reference info
 		if (this.options.produceReferenceInfo && unit.scope != null)
 			unit.scope.storeDependencyInfo();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 652c0d9..a7cd80b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -331,6 +331,8 @@
 	public boolean storeAnnotations;
 	/** Indicate if annotation processing generates classfiles */
 	public boolean generateClassFiles;
+	/** Indicate if method bodies should be ignored */
+	public boolean ignoreMethodBodies;
 
 
 	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
@@ -1040,6 +1042,8 @@
 		// dead code detection
 		this.reportDeadCodeInTrivialIfStatement = false;
 
+		// ignore method bodies
+		this.ignoreMethodBodies = false;
 	}
 
 	public void set(Map optionsMap) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index b56d01f..6316bf6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -2545,23 +2545,25 @@
 	Statement[] statements = null;
 	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
 		this.astPtr -= length;
-		if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) {
-			//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
-			System.arraycopy(
-				this.astStack,
-				this.astPtr + 2,
-				statements = new Statement[length - 1],
-				0,
-				length - 1);
-			constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
-		} else { //need to add explicitly the super();
-			System.arraycopy(
-				this.astStack,
-				this.astPtr + 1,
-				statements = new Statement[length],
-				0,
-				length);
-			constructorCall = SuperReference.implicitSuperConstructorCall();
+		if (!this.options.ignoreMethodBodies) {
+			if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) {
+				//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+				System.arraycopy(
+					this.astStack,
+					this.astPtr + 2,
+					statements = new Statement[length - 1],
+					0,
+					length - 1);
+				constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
+			} else { //need to add explicitly the super();
+				System.arraycopy(
+					this.astStack,
+					this.astPtr + 1,
+					statements = new Statement[length],
+					0,
+					length);
+				constructorCall = SuperReference.implicitSuperConstructorCall();
+			}
 		}
 	} else {
 		boolean insideFieldInitializer = false;
@@ -4316,12 +4318,16 @@
 		//statements
 		explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
 		if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
-			System.arraycopy(
-				this.astStack,
-				(this.astPtr -= length) + 1,
-				statements = new Statement[length],
-				0,
-				length);
+			if (this.options.ignoreMethodBodies) {
+				this.astPtr -= length;
+			} else {
+				System.arraycopy(
+					this.astStack,
+					(this.astPtr -= length) + 1,
+					statements = new Statement[length],
+					0,
+					length);
+			}
 		}
 	}
 
@@ -9447,35 +9453,40 @@
 	int length;
 	if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
 		this.astPtr -= length;
-		if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall)
-			//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
-			{
-			System.arraycopy(
-				this.astStack,
-				this.astPtr + 2,
-				cd.statements = new Statement[length - 1],
-				0,
-				length - 1);
-			cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
-		} else { //need to add explicitly the super();
-			System.arraycopy(
-				this.astStack,
-				this.astPtr + 1,
-				cd.statements = new Statement[length],
-				0,
-				length);
-			cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		if (!this.options.ignoreMethodBodies) {
+			if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall)
+				//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+				{
+				System.arraycopy(
+					this.astStack,
+					this.astPtr + 2,
+					cd.statements = new Statement[length - 1],
+					0,
+					length - 1);
+				cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
+			} else { //need to add explicitly the super();
+				System.arraycopy(
+					this.astStack,
+					this.astPtr + 1,
+					cd.statements = new Statement[length],
+					0,
+					length);
+				cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+			}
 		}
 	} else {
-		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		if (!this.options.ignoreMethodBodies) {
+			cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		}
 		if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
 			cd.bits |= ASTNode.UndocumentedEmptyBlock;
 		}
 	}
 
-	if (cd.constructorCall.sourceEnd == 0) {
-		cd.constructorCall.sourceEnd = cd.sourceEnd;
-		cd.constructorCall.sourceStart = cd.sourceStart;
+	ExplicitConstructorCall explicitConstructorCall = cd.constructorCall;
+	if (explicitConstructorCall != null && explicitConstructorCall.sourceEnd == 0) {
+		explicitConstructorCall.sourceEnd = cd.sourceEnd;
+		explicitConstructorCall.sourceStart = cd.sourceStart;
 	}
 }
 // A P I
@@ -9688,12 +9699,17 @@
 	md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
 	int length;
 	if (this.astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
-		System.arraycopy(
-			this.astStack,
-			(this.astPtr -= length) + 1,
-			md.statements = new Statement[length],
-			0,
-			length);
+		if (this.options.ignoreMethodBodies) {
+			// ignore statements
+			this.astPtr -= length;
+		} else {
+			System.arraycopy(
+				this.astStack,
+				(this.astPtr -= length) + 1,
+				md.statements = new Statement[length],
+				0,
+				length);
+		}
 	} else {
 		if (!containsComment(md.bodyStart, md.bodyEnd)) {
 			md.bits |= ASTNode.UndocumentedEmptyBlock;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
index fc20b73..0929ed2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -149,6 +149,10 @@
 	private boolean statementsRecovery;
 
 	/**
+	 * Request to ignore parsing the method bodies. Defaults to <code>false</code>.
+     */
+	private boolean ignoreMethodBodies;
+	/**
      * Request for a bindings recovery. Defaults to <code>false</code>.
      */
     private boolean bindingsRecovery;
@@ -226,6 +230,7 @@
 		this.rawSource = null;
 		this.typeRoot = null;
 		this.resolveBindings = false;
+		this.ignoreMethodBodies = false;
 		this.sourceLength = -1;
 		this.sourceOffset = 0;
 		this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
@@ -564,6 +569,21 @@
 	public void setStatementsRecovery(boolean enabled) {
 		this.statementsRecovery = enabled;
 	}
+	
+	/**
+	 * Requests an abstract syntax tree without method bodies. 
+	 * 
+	 * <p>When ignore method bodies is enabled, all method bodies are discarded.
+	 * This has no impact on the binding resolution.</p>
+	 *
+	 * <p>This setting is not used if the kind used in {@link #setKind(int)} is either 
+	 * {@link #K_EXPRESSION} or {@link #K_STATEMENTS}.</p>
+	 *
+	 * @since 3.5.2
+	 */
+	public void setIgnoreMethodBodies(boolean enabled) {
+		this.ignoreMethodBodies = true;
+	}
 
     /**
      * Sets the working copy owner using when resolving bindings, where
@@ -730,6 +750,7 @@
 		try {
 			int flags = 0;
 			if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+			if (this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
 			if (this.resolveBindings) {
 				if (this.project == null)
 					throw new IllegalStateException("project not specified"); //$NON-NLS-1$
@@ -790,6 +811,7 @@
 			int flags = 0;
 			if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
 			if (this.bindingsRecovery)  flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+			if (this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
 			return CompilationUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
 		} finally {
 			// re-init defaults to allow reuse (and avoid leaking)
@@ -900,6 +922,7 @@
 					}
 					int flags = 0;
 					if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+					if (searcher == null && this.ignoreMethodBodies) flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
 					if (needToResolveBindings) {
 						if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
 						try {
@@ -1034,7 +1057,7 @@
 			ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
 		}
 		converter.setAST(ast);
-		CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
+		CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil(this.ignoreMethodBodies);
 		CompilationUnit compilationUnit = ast.newCompilationUnit();
 		if (this.sourceLength == -1) {
 			this.sourceLength = this.rawSource.length;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index 1c2f114..8e00cef 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -336,6 +336,7 @@
 	public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
 		try {
 			CompilerOptions compilerOptions = new CompilerOptions(options);
+			compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
 			Parser parser = new CommentRecorderParser(
 				new ProblemReporter(
 						DefaultErrorHandlingPolicies.proceedWithAllProblems(),
@@ -389,6 +390,7 @@
 		boolean statementsRecovery = (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
 		compilerOptions.performMethodsFullRecovery = statementsRecovery;
 		compilerOptions.performStatementsRecovery = statementsRecovery;
+		compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
 		Parser parser = new CommentRecorderParser(
 			new ProblemReporter(
 					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
@@ -462,15 +464,16 @@
 			}
 			environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
 			problemFactory = new CancelableProblemFactory(monitor);
+			CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+			compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
 			CompilationUnitResolver resolver =
 				new CompilationUnitResolver(
 					environment,
 					getHandlingPolicy(),
-					getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+					compilerOptions,
 					getRequestor(),
 					problemFactory,
 					monitor);
-
 			resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
 			if (NameLookup.VERBOSE) {
 				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
@@ -505,23 +508,26 @@
 		try {
 			environment = new CancelableNameEnvironment(((JavaProject)javaProject), owner, monitor);
 			problemFactory = new CancelableProblemFactory(monitor);
+			CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+			boolean ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+			compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
 			resolver =
 				new CompilationUnitResolver(
 					environment,
 					getHandlingPolicy(),
-					getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+					compilerOptions,
 					getRequestor(),
 					problemFactory,
 					monitor);
-
+			boolean analyzeAndGenerateCode = !ignoreMethodBodies;
 			unit =
 				resolver.resolve(
 					null, // no existing compilation unit declaration
 					sourceUnit,
 					nodeSearcher,
 					true, // method verification
-					true, // analyze code
-					true); // generate code
+					analyzeAndGenerateCode, // analyze code
+					analyzeAndGenerateCode); // generate code
 			if (resolver.hasCompilationAborted) {
 				// the bindings could not be resolved due to missing types in name environment
 				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index 7bfe7d6..ef78b3c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -63,6 +63,14 @@
 public static final int ENABLE_BINDINGS_RECOVERY = 0x04;
 
 /**
+ * Constant indicating that a reconcile operation could ignore to parse the method bodies.
+ * @see ASTParser#setIgnoreMethodBodies(boolean)
+ * @since 3.5.2
+ */
+public static final int IGNORE_METHOD_BODIES = 0x08;
+
+
+/**
  * Applies a text edit to the compilation unit's buffer.
  * <p>
  * Note that the edit is simply applied to the compilation unit's buffer.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
index 1b32a03..6fa7747 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 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
@@ -94,6 +94,7 @@
 		parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
 		parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
 		parser.setSource(this.workingCopy);
+		parser.setIgnoreMethodBodies((this.operation.reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
 		return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor);
 	}
 	return this.operation.makeConsistent(this.workingCopy);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 07e6ba3..f517b45 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -145,10 +145,12 @@
 		// disable task tags checking to speed up parsing
 		options.put(JavaCore.COMPILER_TASK_TAGS, ""); //$NON-NLS-1$
 	}
+	CompilerOptions compilerOptions = new CompilerOptions(options);
+	compilerOptions.ignoreMethodBodies = (reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
 	SourceElementParser parser = new SourceElementParser(
 		requestor,
 		problemFactory,
-		new CompilerOptions(options),
+		compilerOptions,
 		true/*report local declarations*/,
 		!createAST /*optimize string literals only if not creating a DOM AST*/);
 	parser.reportOnlyOneSyntaxError = !computeProblems;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index a754396..7e62a1b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2009 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
@@ -157,12 +157,16 @@
 		try {
 			environment = new CancelableNameEnvironment(project, workingCopyOwner, monitor);
 			problemFactory = new CancelableProblemFactory(monitor);
+			CompilerOptions compilerOptions = getCompilerOptions(project.getOptions(true), creatingAST, ((reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0));
+			boolean ignoreMethodBodies = (reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
+			compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
 			problemFinder = new CompilationUnitProblemFinder(
 				environment,
 				getHandlingPolicy(),
-				getCompilerOptions(project.getOptions(true), creatingAST, ((reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0)),
+				compilerOptions,
 				getRequestor(),
 				problemFactory);
+			boolean analyzeAndGenerateCode = !ignoreMethodBodies;
 			CompilationUnitDeclaration unit = null;
 			if (parser != null) {
 				problemFinder.parser = parser;
@@ -172,8 +176,8 @@
 						unit,
 						unitElement,
 						true, // verify methods
-						true, // analyze code
-						true); // generate code
+						analyzeAndGenerateCode, // analyze code
+						analyzeAndGenerateCode); // generate code
 				} catch (AbortCompilation e) {
 					problemFinder.handleInternalException(e, unit);
 				}
@@ -182,8 +186,8 @@
 					problemFinder.resolve(
 						unitElement,
 						true, // verify methods
-						true, // analyze code
-						true); // generate code
+						analyzeAndGenerateCode, // analyze code
+						analyzeAndGenerateCode); // generate code
 			}
 			CompilationResult unitResult = unit.compilationResult;
 			CategorizedProblem[] unitProblems = unitResult.getProblems();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
index a90f370..6115e3d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
@@ -32,6 +32,15 @@
 public class CodeSnippetParsingUtil {
 
 	public RecordedParsingInformation recordedParsingInformation;
+	public boolean ignoreMethodBodies;
+	
+	public CodeSnippetParsingUtil(boolean ignoreMethodBodies) {
+		this.ignoreMethodBodies = ignoreMethodBodies;
+	}
+
+	public CodeSnippetParsingUtil() {
+		this(false);
+	}
 
 	private RecordedParsingInformation getRecordedParsingInformation(CompilationResult compilationResult, int[][] commentPositions) {
 		int problemsCount = compilationResult.problemCount;
@@ -62,6 +71,7 @@
 			throw new IllegalArgumentException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		compilerOptions.ignoreMethodBodies = this.ignoreMethodBodies;
 		final ProblemReporter problemReporter = new ProblemReporter(
 					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
 					compilerOptions,
@@ -92,6 +102,7 @@
 			throw new IllegalArgumentException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		compilerOptions.ignoreMethodBodies = this.ignoreMethodBodies;
 		CommentRecorderParser parser =
 			new CommentRecorderParser(
 				new ProblemReporter(
@@ -144,6 +155,7 @@
 			throw new IllegalArgumentException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		// in this case we don't want to ignore method bodies since we are parsing only an expression
 		final ProblemReporter problemReporter = new ProblemReporter(
 					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
 					compilerOptions,
@@ -182,6 +194,7 @@
 			throw new IllegalArgumentException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		// in this case we don't want to ignore method bodies since we are parsing only statements
 		final ProblemReporter problemReporter = new ProblemReporter(
 					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
 					compilerOptions,