more fixes for prototype 
Now the getDirectChildren(), getDirectChild(name) of a LocalType will
return also everything of the prototype chain.

Added various test for validation and code completion.
diff --git a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/ElementValue.java b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/ElementValue.java
index 4f099d3..d0d6c3c 100644
--- a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/ElementValue.java
+++ b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/ElementValue.java
@@ -141,7 +141,8 @@
 				if (!selection.isEmpty()) {
 					if (selection.size() == 1) {
 						final IRMember selected = selection.get(0);
-						if ("prototype".equals(selected.getName())
+						if (IRLocalType.PROTOTYPE_PROPERTY.equals(selected
+								.getName())
 								&& selected instanceof IRProperty) {
 							if (t != null) {
 								return new PrototypePropertyValue(
diff --git a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/TypeInferencerVisitor.java b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/TypeInferencerVisitor.java
index 2585112..949ffd6 100644
--- a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/TypeInferencerVisitor.java
+++ b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/ti/TypeInferencerVisitor.java
@@ -123,6 +123,7 @@
 import org.eclipse.dltk.javascript.typeinfo.IRLocalType;
 import org.eclipse.dltk.javascript.typeinfo.IRMapType;
 import org.eclipse.dltk.javascript.typeinfo.IRMethod;
+import org.eclipse.dltk.javascript.typeinfo.IRProperty;
 import org.eclipse.dltk.javascript.typeinfo.IRRecordMember;
 import org.eclipse.dltk.javascript.typeinfo.IRSimpleType;
 import org.eclipse.dltk.javascript.typeinfo.IRType;
@@ -448,6 +449,21 @@
 									&& !declaredType.isJavaScriptObject()) {
 								// skip assignment
 								return right;
+							} else {
+								// if the assignment is done on the prototype property
+								// then make sure it is not IRProperty (the one from Object itself)
+								// replace that with a AnonymousValue
+								Object attribute = leftParent
+										.getAttribute(IReferenceAttributes.ELEMENT);
+								if (attribute instanceof IRProperty
+										&& ((IRProperty) attribute).getName()
+												.equals(IRLocalType.PROTOTYPE_PROPERTY)) {
+									leftParent.getParent()
+											.createChild(
+													IRLocalType.PROTOTYPE_PROPERTY)
+											.setValue(new AnonymousValue());
+								}
+
 							}
 						}
 					}
@@ -873,7 +889,8 @@
 					.getExtendsType());
 			thisValue.setDeclaredType(thisType);
 			if (thisType instanceof IRLocalType) {
-				IValueReference prototype = result.createChild("prototype");
+				IValueReference prototype = result
+						.createChild(IRLocalType.PROTOTYPE_PROPERTY);
 				prototype.setDeclaredType(context.getType(ITypeNames.OBJECT)
 						.toRType(context));
 				Set<String> directChildren = ((IRLocalType) thisType)
diff --git a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/IRLocalType.java b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/IRLocalType.java
index 5137b30..5bd242d 100644
--- a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/IRLocalType.java
+++ b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/IRLocalType.java
@@ -21,6 +21,8 @@
  * @author jcompagner

  */

 public interface IRLocalType extends IRType, IRTypeExtension {

+	public static final String PROTOTYPE_PROPERTY = "prototype";

+

 	public IValueReference getValue();

 

 	@Nullable

diff --git a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/RLocalType.java b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/RLocalType.java
index bace625..c81c57e 100644
--- a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/RLocalType.java
+++ b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/RLocalType.java
@@ -48,15 +48,7 @@
 	}

 

 	public IValueReference getDirectChild(String name) {

-		final IValueReference value = getValue();

-		if (value.getDirectChildren(IValue.NO_LOCAL_TYPES).contains(name)) {

-			return value.getChild(name);

-		} else {

-			JSTypeSet declaredTypes = getValue().getDeclaredTypes();

-			HashSet<IRType> set = new HashSet<IRType>();

-			set.add(this);

-			return getChildFromDeclaredTypes(name, declaredTypes, set);

-		}

+		return getChild(this, name, new HashSet<IRType>());

 	}

 

 	/**

@@ -67,38 +59,64 @@
 	private IValueReference getChildFromDeclaredTypes(String name,

 			JSTypeSet declaredTypes, HashSet<IRType> set) {

 		for (IRType irType : declaredTypes) {

-			if (irType instanceof RLocalType && set.add(irType)) {

-				IValueReference declaredValue = ((RLocalType) irType)

-						.getValue();

-				if (declaredValue.getDirectChildren(IValue.NO_LOCAL_TYPES)

-						.contains(name)) {

-					return declaredValue.getChild(name);

-				}

-				IValueReference fromChild = getChildFromDeclaredTypes(name,

-						declaredValue.getDeclaredTypes(), set);

-				if (fromChild != null)

-					return fromChild;

+			if (irType instanceof RLocalType) {

+				IValueReference child = getChild((RLocalType) irType, name, set);

+				if (child != null)

+					return child;

 			}

 		}

 		return null;

 	}

 

+	private IValueReference getChild(RLocalType irType, String name,

+			HashSet<IRType> set) {

+		if (set.add(irType)) {

+			IValueReference declaredValue = irType.getValue();

+			if (declaredValue.getDirectChildren(IValue.NO_LOCAL_TYPES)

+					.contains(name)) {

+				return declaredValue.getChild(name);

+			}

+			IValueReference fromChild = getChildFromDeclaredTypes(name,

+					declaredValue.getDeclaredTypes(), set);

+			if (fromChild == null) {

+				IValueReference prototype = irType.functionValue

+						.getChild(PROTOTYPE_PROPERTY);

+				if (prototype.getDirectChildren().contains(name)) {

+					return prototype.getChild(name);

+				}

+			}

+			return fromChild;

+		}

+		return null;

+	}

+

 	public Set<String> getDirectChildren() {

-		Set<String> children = getValue().getDirectChildren(

-				IValue.NO_LOCAL_TYPES);

-		JSTypeSet declaredTypes = getValue().getDeclaredTypes();

-		HashSet<IRType> set = new HashSet<IRType>();

-		set.add(this);

-		fillDeclaredLocalTypesChildren(children, declaredTypes, set);

+		Set<String> children = new HashSet<String>();

+		fillChildren(this, children, new HashSet<IRType>());

 		return children;

 	}

 

+	private static void fillChildren(RLocalType rLocalType,

+			Set<String> children,

+			HashSet<IRType> set) {

+		if (set.add(rLocalType)) {

+			IValueReference value = rLocalType.getValue();

+			children.addAll(value.getDirectChildren(

+					IValue.NO_LOCAL_TYPES));

+			IValueReference prototype = rLocalType.functionValue

+					.getChild(PROTOTYPE_PROPERTY);

+			children.addAll(prototype.getDirectChildren());

+			fillDeclaredLocalTypesChildren(children, value

+					.getDeclaredTypes(), set);

+		}

+	}

+

 	/**

 	 * @param children

 	 * @param declaredTypes

 	 * @param set

 	 */

-	private void fillDeclaredLocalTypesChildren(Set<String> children,

+	private static void fillDeclaredLocalTypesChildren(Set<String> children,

 			JSTypeSet declaredTypes, HashSet<IRType> set) {

 		for (IRType irType : declaredTypes) {

 			if (irType instanceof RLocalType && set.add(irType)) {

diff --git a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/contentassist/CodeCompletion.java b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/contentassist/CodeCompletion.java
index 29bfc1e..63030a4 100644
--- a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/contentassist/CodeCompletion.java
+++ b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/contentassist/CodeCompletion.java
@@ -949,4 +949,42 @@
 		}
 		assertEquals(true, found);
 	}
+	
+	public void testPrototypeFunctionWith2Extends() {
+		final StringList code = new StringList();
+		code.add("function A() {}");
+		code.add("A.prototype.afunction = function(){ }");
+		code.add("/**");
+		code.add(" * @extends {A}");
+		code.add(" */");
+		code.add("function B() {}");
+		code.add("B.prototype = new A();");
+		code.add("B.prototype.bfunction = function(){ }");
+		code.add("/**");
+		code.add(" * @extends {B}");
+		code.add(" */");
+		code.add("function C() {}");
+		code.add("C.prototype = new B();");
+		code.add("C.prototype.testDirectAssignment = function(){ }");
+		code.add("var x = new C();");
+		code.add("x.");
+		final IModuleSource module = new TestModule(code.toString());
+		final List<CompletionProposal> results = new ArrayList<CompletionProposal>();
+		final ICompletionEngine completionEngine = createEngine(results,
+				JSCompletionEngine.OPTION_KEYWORDS);
+		completionEngine.complete(module, lastPositionInFile(".", module), 0);
+		int found = 0;
+		for (CompletionProposal completionProposal : results) {
+			if (completionProposal.getName().equals("testDirectAssignment")) {
+				found++;
+			}
+			if (completionProposal.getName().equals("bfunction")) {
+				found++;
+			}
+			if (completionProposal.getName().equals("afunction")) {
+				found++;
+			}
+		}
+		assertEquals(3, found);
+	}
 }
diff --git a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/TypeInfoValidationTests.java b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/TypeInfoValidationTests.java
index 1836472..329cd39 100644
--- a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/TypeInfoValidationTests.java
+++ b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/TypeInfoValidationTests.java
@@ -3644,5 +3644,53 @@
 		final List<IProblem> problems = validate(code.toString());
 		assertEquals(problems.toString(), 0, problems.size());
 	}
+	
+	public void testPrototypeFunction() {
+		final StringList code = new StringList();
+		code.add("function A() {}");
+		code.add("A.prototype.testDirectAssignment = function(){ }");
+		code.add("var x = new A();");
+		code.add("x.testDirectAssignment();");
+		final List<IProblem> problems = validate(code.toString());
+		assertEquals(problems.toString(), 0, problems.size());
+	}
 
+	public void testPrototypeFunctionWithExtends() {
+		final StringList code = new StringList();
+		code.add("function A() {}");
+		code.add("/**");
+		code.add(" * @extends {A}");
+		code.add(" */");
+		code.add("function B() {}");
+		code.add("B.prototype = new A();");
+		code.add("B.prototype.testDirectAssignment = function(){ }");
+		code.add("var x = new B();");
+		code.add("x.testDirectAssignment();");
+		final List<IProblem> problems = validate(code.toString());
+		assertEquals(problems.toString(), 0, problems.size());
+	}
+	
+	public void testPrototypeFunctionWith2Extends() {
+		final StringList code = new StringList();
+		code.add("function A() {}");
+		code.add("A.prototype.afunction = function(){ }");
+		code.add("/**");
+		code.add(" * @extends {A}");
+		code.add(" */");
+		code.add("function B() {}");
+		code.add("B.prototype = new A();");
+		code.add("B.prototype.bfunction = function(){ }");
+		code.add("/**");
+		code.add(" * @extends {B}");
+		code.add(" */");
+		code.add("function C() {}");
+		code.add("C.prototype = new B();");
+		code.add("C.prototype.testDirectAssignment = function(){ }");
+		code.add("var x = new C();");
+		code.add("x.testDirectAssignment();");
+		code.add("x.bfunction();");
+		code.add("x.afunction();");
+		final List<IProblem> problems = validate(code.toString());
+		assertEquals(problems.toString(), 0, problems.size());
+	}
 }