Bug 430195: [1.8][model][api] Lambda IType API problems (isLambda(); getElementName() returns "")
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
index 24e2c84..2235841 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -525,8 +525,15 @@
 				this.line.append(":");
 			}
 			String typeName = type.getElementName();
-			if (typeName.length() == 0) {
+			boolean anonymous = false;
+			try {
+				anonymous = type.isAnonymous();
+			} catch(JavaModelException jme) {
+			}
+			if (anonymous) {
 				this.line.append("<anonymous>");
+			} else if (type.isLambda()) {
+				((LambdaExpression) type).toStringName(this.line);
 			} else {
 				this.line.append(typeName);
 			}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElement8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElement8Tests.java
index 8d681ba..541b982 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElement8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElement8Tests.java
@@ -517,7 +517,7 @@
 			assertEquals("Incorrect java element", IJavaElement.LOCAL_VARIABLE, elements[0].getElementType());
 			IType lambda = (IType) elements[0].getParent().getParent();
 			String mem = lambda.getHandleIdentifier();
-			String expected = "=\\(\\[Bug430136\\])/src<{X.java[MyFunction~compose~QMyFunction\\<-QV;+QT;>;=)Lambda\\(MyFunction)=\"LMyFunction\\<TV;TR;>;!148!174!151=&apply!1=\"TV;=\"v=\"TR;=\"LX\\~MyFunction\\<LX\\~MyFunction;:1TV;LX\\~MyFunction;:TR;>;.apply\\(TV;)TR;@v!148!148!148!148!Ljava\\/lang\\/Object;!0!true=)";
+			String expected = "=\\(\\[Bug430136\\])/src<{X.java[MyFunction~compose~QMyFunction\\<-QV;+QT;>;=)MyFunction=\"LMyFunction\\<TV;TR;>;!148!174!151=&apply!1=\"TV;=\"v=\"TR;=\"LX\\~MyFunction\\<LX\\~MyFunction;:1TV;LX\\~MyFunction;:TR;>;.apply\\(TV;)TR;@v!148!148!148!148!Ljava\\/lang\\/Object;!0!true=)";
 			assertEquals("Incorrect memento", expected, mem);
 			IJavaElement result = JavaCore.create(expected);
 			assertEquals("Incorrect element created", lambda, result);
@@ -560,4 +560,31 @@
 			deleteProject(projectName);
 		}
 	}
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430195
+	public void test430195() throws CoreException {
+		String projectName = "Bug430195";
+		try {
+			IJavaProject project = createJavaProject(projectName, new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "1.8");
+			project.open(null);
+			String fileContent = 
+					"interface MyFunction<T, R> {\n" +
+					"    R apply(T t);\n" +
+					"    default <V> MyFunction<V, R> compose(MyFunction<? super V, ? extends T> before) {\n" +
+					"        return v -> apply(before.apply(v));\n" +
+					"    }\n" +
+					"}\n";
+			String fileName = "/" + projectName + "/src/X.java";
+			createFile(fileName, fileContent);
+			
+			ICompilationUnit unit = getCompilationUnit(fileName);
+			int start = fileContent.indexOf("v");
+			IJavaElement[] elements = unit.codeSelect(start, 1);
+			assertEquals("Incorrect java element", IJavaElement.LOCAL_VARIABLE, elements[0].getElementType());
+			IType lambda = (IType) elements[0].getParent().getParent();
+			assertEquals("Incorrect qualified type name", "MyFunction$1", lambda.getTypeQualifiedName());
+		}
+		finally {
+			deleteProject(projectName);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
index 51e9012..9fe3b20 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
@@ -2422,14 +2422,14 @@
 	IMethod lambda = (IMethod) elements[0].getParent();
 	String memento = lambda.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&", 
 			memento);
 	IJavaElement result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", lambda, result);
 	LambdaExpression expression = (LambdaExpression) lambda.getParent();
 	memento = expression.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=)", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=)", 
 			memento);
 	result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", expression, result);
@@ -2439,14 +2439,14 @@
 	lambda = (IMethod) elements[0].getParent();
 	memento = lambda.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!180!197!188=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!181!181!181!181!Ljava\\/util\\/List;!0!true@i!184!184!184!184!I!0!true=&", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!180!197!188=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!181!181!181!181!Ljava\\/util\\/List;!0!true@i!184!184!184!184!I!0!true=&", 
 			memento);
 	result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", lambda, result);
 	expression = (LambdaExpression) lambda.getParent();
 	memento = expression.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!180!197!188=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!181!181!181!181!Ljava\\/util\\/List;!0!true@i!184!184!184!184!I!0!true=)", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!180!197!188=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!181!181!181!181!Ljava\\/util\\/List;!0!true@i!184!184!184!184!I!0!true=)", 
 			memento);
 	result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", expression, result);
@@ -2474,7 +2474,7 @@
 	ILocalVariable local = (ILocalVariable) elements[0];
 	String memento = local.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&@x!145!145!145!145!Ljava.util.List\\<LU;>;!0!true", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&@x!145!145!145!145!Ljava.util.List\\<LU;>;!0!true", 
 			memento);
 	IJavaElement result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", local, result);
@@ -2484,7 +2484,7 @@
 	IMethod lambda = (IMethod) elements[0].getParent();
 	memento = lambda.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=&", 
 			memento);
 	result = JavaCore.create(memento);
 	assertEquals("Java elements should be equal", lambda, result);
@@ -2492,7 +2492,7 @@
 	LambdaExpression expression = (LambdaExpression) lambda.getParent();
 	memento = expression.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Lambda\\(Getter)=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=)", 
+			"=Resolve/src<{X.java[X~foo~QList\\<QU;>;=)Getter=\"LGetter\\<TU;>;!144!161!152=&get!2=\"Ljava.util.List\\<TU;>;=\"x=\"I=\"i=\"TU;=\"LX\\~Getter\\<LX;:TU;>;.get\\(Ljava\\/util\\/List\\<TU;>;I)TU;@x!145!145!145!145!Ljava\\/util\\/List;!0!true@i!148!148!148!148!I!0!true=)", 
 			memento);
 	LambdaExpression recreatedType = (LambdaExpression) JavaCore.create(memento);
 	assertEquals("Java elements should be equal", expression, recreatedType);
@@ -2524,9 +2524,9 @@
 	String memento = local.getHandleIdentifier();
 		assertEquals(
 				"Incorrect memento string",
-				"=Resolve/src<{X.java[X~main~\\[QString;=)Lambda\\(I)=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
-				+ "LI;@pqr!104!106!104!106!LI;!0!true=&=)Lambda\\(I)=\"LI;!124!164!131=&doit!1=\"LI;=\"xyz=\"LI;=\"LX\\~I;.doit\\(LI;)"
-				+ "LI;@xyz!125!127!125!127!LI;!0!true=&=)Lambda\\(I)=\"LI;!146!157!153=&doit!1=\"LI;=\"abc=\"LI;=\"LX\\~I;.doit\\(LI;)"
+				"=Resolve/src<{X.java[X~main~\\[QString;=)I=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
+				+ "LI;@pqr!104!106!104!106!LI;!0!true=&=)I=\"LI;!124!164!131=&doit!1=\"LI;=\"xyz=\"LI;=\"LX\\~I;.doit\\(LI;)"
+				+ "LI;@xyz!125!127!125!127!LI;!0!true=&=)I=\"LI;!146!157!153=&doit!1=\"LI;=\"abc=\"LI;=\"LX\\~I;.doit\\(LI;)"
 				+ "LI;@abc!147!149!147!149!LI;!0!true=&@abc!147!149!147!149!LI;!0!true",
 				memento);
 	IJavaElement result = JavaCore.create(memento);
@@ -2543,8 +2543,8 @@
 	local = (ILocalVariable) elements[0];
 	memento = local.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~main~\\[QString;=)Lambda\\(I)=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
-			+ "LI;@pqr!104!106!104!106!LI;!0!true=&=)Lambda\\(I)=\"LI;!124!164!131=&doit!1=\"LI;=\"xyz=\"LI;=\"LX\\~I;.doit\\(LI;)"
+			"=Resolve/src<{X.java[X~main~\\[QString;=)I=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
+			+ "LI;@pqr!104!106!104!106!LI;!0!true=&=)I=\"LI;!124!164!131=&doit!1=\"LI;=\"xyz=\"LI;=\"LX\\~I;.doit\\(LI;)"
 			+ "LI;@xyz!125!127!125!127!LI;!0!true=&@xyz!125!127!125!127!LI;!0!true", 
 			memento);
 	result = JavaCore.create(memento);
@@ -2561,7 +2561,7 @@
 	local = (ILocalVariable) elements[0];
 	memento = local.getHandleIdentifier();
 	assertEquals("Incorrect memento string", 
-			"=Resolve/src<{X.java[X~main~\\[QString;=)Lambda\\(I)=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
+			"=Resolve/src<{X.java[X~main~\\[QString;=)I=\"LI;!103!169!110=&doit!1=\"LI;=\"pqr=\"LI;=\"LX\\~I;.doit\\(LI;)"
 			+ "LI;@pqr!104!106!104!106!LI;!0!true=&@pqr!104!106!104!106!LI;!0!true", 
 			memento);
 	result = JavaCore.create(memento);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
index f10a187..d413dc7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
@@ -87,4 +87,9 @@
  * Answer the names of the receiver's type parameters.
  */
 char[][] getTypeParameterNames();
+
+/**
+ * Answer whether the receiver type is anonymous
+ */
+boolean isAnonymous();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index 7f12435..df0b898 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -17,11 +17,15 @@
 
 /**
  * Represents either a source type in a compilation unit (either a top-level
- * type, a member type, a local type or an anonymous type)
+ * type, a member type, a local type, an anonymous type or a lambda expression)
  * or a binary type in a class file. Enumeration classes and annotation
  * types are subkinds of classes and interfaces, respectively.
  * <p>
- * Note that the element name of an anonymous source type is always empty.
+ * Note that the element name of an anonymous source type and lambda expressions
+ * is always empty. Types representing lambda expressions are pseudo-elements 
+ * and not included in the children of their parent. Lambda expressions are created 
+ * as the result of a <code>ICodeAssist.codeSelect(...)</code>. For more information 
+ * on such pseudo-elements, see <code>ILocalVariable</code>.
  * </p><p>
  * If a binary type cannot be parsed, its structure remains unknown.
  * Use <code>IJavaElement.isStructureKnown</code> to determine whether this
@@ -486,6 +490,9 @@
 	/**
 	 * Returns the simple name of this type, unqualified by package or enclosing type.
 	 * This is a handle-only method.
+	 * 
+	 * Note that the element name of an anonymous source type and lambda expressions
+	 * is always empty.
 	 *
 	 * @return the simple name of this type
 	 */
@@ -1205,4 +1212,12 @@
 	 * @since 3.0
 	 */
 	String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException;
+	
+	/**
+	 * Returns whether this type represents a lambda expression.
+	 *
+	 * @return true if this type represents a lambda expression, false otherwise
+	 * @since 3.10
+	 */
+	public boolean isLambda();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index de21d04..2206781 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -1042,4 +1042,8 @@
 	}
 	return javadocContents;
 }
+@Override
+public boolean isLambda() {
+	return false;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index fad6d39..d656423 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -728,7 +728,7 @@
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=342393
 	// For anonymous source types, the occurrence count should be in the context
 	// of the enclosing type.
-	if (handle instanceof SourceType && handle.getElementName().length() == 0) {
+	if (handle instanceof SourceType && ((SourceType) handle).isAnonymous()) {
 		Object key = handle.getParent().getAncestor(IJavaElement.TYPE);
 		occurenceCount = this.localOccurrenceCounts.get(key);
 		if (occurenceCount == -1)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
index 9c0772b..8930995 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
@@ -32,11 +32,13 @@
 	protected int sourceEnd;
 	protected int arrowPosition;
 	protected String interphase;
+	String resolvedTypeName;
 	
 	
 	// Construction from AST node
 	public LambdaExpression(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
-		super(parent, new String("Lambda(") + new String(lambdaExpression.resolvedType.sourceName()) + ')'); //$NON-NLS-1$
+		super(parent, new String(CharOperation.NO_CHAR));
+		this.resolvedTypeName = new String(lambdaExpression.resolvedType.sourceName());
 		this.sourceStart = lambdaExpression.sourceStart;
 		this.sourceEnd = lambdaExpression.sourceEnd;
 		this.arrowPosition = lambdaExpression.arrowPosition;
@@ -47,8 +49,9 @@
 	}
 	
 	// Construction from memento
-	public LambdaExpression(JavaElement parent, String name, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
-		super(parent, name);
+	public LambdaExpression(JavaElement parent, String resolvedTypeName, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
+		super(parent, new String(CharOperation.NO_CHAR));
+		this.resolvedTypeName = resolvedTypeName;
 		this.sourceStart = sourceStart;
 		this.sourceEnd = sourceEnd;
 		this.arrowPosition = arrowPosition;
@@ -58,8 +61,9 @@
 	}
 	
 	// Construction from subtypes.
-	public LambdaExpression(JavaElement parent, String name, String interphase, int sourceStart, int sourceEnd, int arrowPosition, LambdaMethod lambdaMethod) {
-		super(parent, name);
+	public LambdaExpression(JavaElement parent, String resolvedTypeName, String interphase, int sourceStart, int sourceEnd, int arrowPosition, LambdaMethod lambdaMethod) {
+		super(parent, new String(CharOperation.NO_CHAR));
+		this.resolvedTypeName = resolvedTypeName;
 		this.sourceStart = sourceStart;
 		this.sourceEnd = sourceEnd;
 		this.arrowPosition = arrowPosition;
@@ -136,7 +140,7 @@
 		if (serializeParent) 
 			((JavaElement)getParent()).getHandleMemento(buff);
 		appendEscapedDelimiter(buff, getHandleMementoDelimiter());
-		escapeMementoName(buff, this.name);
+		escapeMementoName(buff, this.resolvedTypeName);
 		appendEscapedDelimiter(buff, JEM_STRING);
 		escapeMementoName(buff, this.interphase);
 		buff.append(JEM_COUNT);
@@ -210,6 +214,27 @@
 	}
 	
 	@Override
+	public boolean isLambda() {
+		return true;
+	}
+
+	@Override
+	public boolean isAnonymous() {
+		return false;
+	}
+
+	public void toStringName(StringBuffer buffer) {
+		super.toStringName(buffer);
+		buffer.append("Lambda("); //$NON-NLS-1$
+		buffer.append(this.resolvedTypeName);
+		buffer.append(')');
+		if (this.occurrenceCount > 1) {
+			buffer.append("#"); //$NON-NLS-1$
+			buffer.append(this.occurrenceCount);
+		}
+	}
+
+	@Override
 	public IJavaElement getPrimaryElement(boolean checkOwner) {
 		if (checkOwner) {
 			CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index 38e4c04..504ce79 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -174,7 +174,7 @@
 			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
 		case JEM_LAMBDA_EXPRESSION:
 			if (!memento.hasMoreTokens()) return this;
-			String name = memento.nextToken();
+			String resolvedType = memento.nextToken();
 			if (!memento.hasMoreTokens() || memento.nextToken() != MementoTokenizer.STRING)
 				return this;
 			if (!memento.hasMoreTokens()) return this;
@@ -188,7 +188,7 @@
 			if (!memento.hasMoreTokens() || memento.nextToken() != MementoTokenizer.COUNT) 
 				return this;
 			int arrowPosition = Integer.parseInt(memento.nextToken());
-			LambdaExpression expression = new LambdaExpression(this, name, interphase, sourceStart, sourceEnd, arrowPosition);
+			LambdaExpression expression = new LambdaExpression(this, resolvedType, interphase, sourceStart, sourceEnd, arrowPosition);
 			if (!memento.hasMoreTokens() || (token = memento.nextToken()) != MementoTokenizer.LAMBDA_METHOD) 
 				return expression;
 			return expression.getHandleFromMemento(token, memento, workingCopyOwner);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
index a687dc5..8475492 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
@@ -18,7 +18,7 @@
 	LambdaExpression unresolved;
 
 	public ResolvedLambdaExpression(JavaElement parent, LambdaExpression unresolved, String uniqueKey) {
-		super(parent, unresolved.name, unresolved.interphase, unresolved.sourceStart, unresolved.sourceEnd, unresolved.arrowPosition, unresolved.lambdaMethod);
+		super(parent, unresolved.resolvedTypeName, unresolved.interphase, unresolved.sourceStart, unresolved.sourceEnd, unresolved.arrowPosition, unresolved.lambdaMethod);
 		this.uniqueKey = uniqueKey;
 		this.unresolved = unresolved;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index 7947315..d00f35f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -841,8 +841,7 @@
 protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
 	buffer.append(tabString(tab));
 	if (info == null) {
-		String elementName = getElementName();
-		if (elementName.length() == 0) {
+		if (isAnonymous()) {
 			buffer.append("<anonymous #"); //$NON-NLS-1$
 			buffer.append(this.occurrenceCount);
 			buffer.append(">"); //$NON-NLS-1$
@@ -851,8 +850,7 @@
 		}
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
-		String elementName = getElementName();
-		if (elementName.length() == 0) {
+		if (isAnonymous()) {
 			buffer.append("<anonymous #"); //$NON-NLS-1$
 			buffer.append(this.occurrenceCount);
 			buffer.append(">"); //$NON-NLS-1$
@@ -870,8 +868,7 @@
 			} else {
 				buffer.append("class "); //$NON-NLS-1$
 			}
-			String elementName = getElementName();
-			if (elementName.length() == 0) {
+			if (isAnonymous()) {
 				buffer.append("<anonymous #"); //$NON-NLS-1$
 				buffer.append(this.occurrenceCount);
 				buffer.append(">"); //$NON-NLS-1$
@@ -883,4 +880,8 @@
 		}
 	}
 }
+@Override
+public boolean isLambda() {
+	return false;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
index b29bfff..87929f5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
@@ -170,7 +170,7 @@
  * @see ISourceType
  */
 public char[][] getInterfaceNames() {
-	if (this.handle.getElementName().length() == 0) { // if anonymous type
+	if (isAnonymous()) { // if anonymous type
 		return null;
 	}
 	return this.superInterfaceNames;
@@ -251,7 +251,7 @@
  * @see ISourceType
  */
 public char[] getSuperclassName() {
-	if (this.handle.getElementName().length() == 0) { // if anonymous type
+	if (isAnonymous()) { // if anonymous type
 		char[][] interfaceNames = this.superInterfaceNames;
 		if (interfaceNames != null && interfaceNames.length > 0) {
 			return interfaceNames[0];
@@ -287,6 +287,15 @@
 public boolean isBinaryType() {
 	return false;
 }
+
+@Override
+public boolean isAnonymous() {
+	try {
+		return this.handle.isAnonymous();
+	} catch (JavaModelException e) {
+		return false;
+	}
+}
 /*
  * Returns whether the source type is an anonymous type of a member type.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 37c881b..09df4a7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -231,7 +231,7 @@
 		separator = '/';
 	} else if (type instanceof ISourceType) {
 		ISourceType sourceType = (ISourceType)type;
-		if (sourceType.getName().length == 0) { // if anonymous type
+		if (sourceType.isAnonymous()) { // if anonymous type
 			if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
 				superInterfaceNames = new char[][] {sourceType.getSuperclassName()};
 			} else {
@@ -246,7 +246,7 @@
 		separator = '.';
 	} else if (type instanceof HierarchyType) {
 		HierarchyType hierarchyType = (HierarchyType)type;
-		if (hierarchyType.name.length == 0) { // if anonymous type
+		if (hierarchyType.isAnonymous()) { // if anonymous type
 			if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
 				superInterfaceNames = new char[][] {hierarchyType.superclassName};
 			} else {
@@ -404,7 +404,12 @@
 		}
 	} else {
 		if (typeBinding == null) return;
-
+		boolean isAnonymous = false;
+		try {
+			isAnonymous = type.isAnonymous();
+		} catch(JavaModelException jme) {
+			// Ignore
+		}
 		if (typeBinding instanceof SourceTypeBinding) {
 			TypeDeclaration typeDeclaration = ((SourceTypeBinding)typeBinding).scope.referenceType();
 
@@ -439,7 +444,8 @@
 					typeDeclaration.name,
 					typeDeclaration.binding.modifiers,
 					superclassName,
-					superInterfaceNames);
+					superInterfaceNames,
+					isAnonymous);
 			remember(hierarchyType, typeDeclaration.binding);
 		} else {
 			HierarchyType hierarchyType = new HierarchyType(
@@ -447,7 +453,8 @@
 					typeBinding.sourceName(),
 					typeBinding.modifiers,
 					typeBinding.superclass().sourceName(),
-					new char [][] { typeBinding.superInterfaces()[0].sourceName() });
+					new char [][] { typeBinding.superInterfaces()[0].sourceName() },
+					isAnonymous);
 			remember(hierarchyType, typeBinding);
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
index ef674ae..87effe1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
@@ -25,19 +25,22 @@
 	public int modifiers;
 	public char[] superclassName;
 	public char[][] superInterfaceNames;
+	public boolean anonymous;
 
 public HierarchyType(
 	IType typeHandle,
 	char[] name,
 	int modifiers,
 	char[] superclassName,
-	char[][] superInterfaceNames) {
+	char[][] superInterfaceNames,
+	boolean anonymous) {
 
 	this.typeHandle = typeHandle;
 	this.name = name;
 	this.modifiers = modifiers;
 	this.superclassName = superclassName;
 	this.superInterfaceNames = superInterfaceNames;
+	this.anonymous = anonymous;
 }
 /**
  * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
@@ -60,4 +63,10 @@
 public boolean isBinaryType() {
 	return false;
 }
+/** 
+ * Answer whether the receiver is an anonymous type
+ */
+public boolean isAnonymous() {
+	return this.anonymous;
+}
 }