210799 [expressions] ExpressionInfo to collect property names
diff --git a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionInfo.java b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionInfo.java
index b2207c4..d209edc 100644
--- a/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionInfo.java
+++ b/bundles/org.eclipse.core.expressions/src/org/eclipse/core/expressions/ExpressionInfo.java
@@ -166,6 +166,7 @@
 		mergeSystemPropertyAccess(other);
 		
 		mergeAccessedVariableNames(other);
+		mergeAccessedPropertyNames(other);
 		mergeMisbehavingExpressionTypes(other);
 	}
 
@@ -179,6 +180,7 @@
 		mergeSystemPropertyAccess(other);
 		
 		mergeAccessedVariableNames(other);
+		mergeAccessedPropertyNames(other);
 		mergeMisbehavingExpressionTypes(other);
 	}
 	
@@ -220,6 +222,22 @@
 	}
 
 	/**
+	 * Merges only the accessed property names.
+	 * 
+	 * @param other the information to merge with
+	 * @since 3.4
+	 */
+	private void mergeAccessedPropertyNames(ExpressionInfo other) {
+		if (fAccessedPropertyNames == null) {
+			fAccessedPropertyNames= other.fAccessedPropertyNames;
+		} else {
+			if (other.fAccessedPropertyNames != null) {
+				fAccessedPropertyNames.addAll(other.fAccessedPropertyNames);
+			}
+		}
+	}
+
+	/**
 	 * Merges only the misbehaving expression types.
 	 * 
 	 * @param other the information to merge with
diff --git a/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionInfoTests.java b/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionInfoTests.java
index 9b13179..f40786d 100644
--- a/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionInfoTests.java
+++ b/tests/org.eclipse.core.expressions.tests/src/org/eclipse/core/internal/expressions/tests/ExpressionInfoTests.java
@@ -123,6 +123,36 @@
 		assertVariableAccess(info, new String[] {"variable_one", "variable_two"});
 	}
 	
+	public void testMergePropertyNames() {
+		ExpressionInfo info;
+		ExpressionInfo other;
+
+		info = new ExpressionInfo();
+		info.addAccessedPropertyName("property");
+		info.merge(new ExpressionInfo());
+		assertPropertyAccess(info, "property", false);
+
+		info = new ExpressionInfo();
+		other = new ExpressionInfo();
+		other.addAccessedPropertyName("property");
+		info.merge(other);
+		assertPropertyAccess(info, "property", false);
+
+		info = new ExpressionInfo();
+		other = new ExpressionInfo();
+		info.addAccessedPropertyName("property");
+		other.addAccessedPropertyName("property");
+		info.merge(other);
+		assertPropertyAccess(info, "property", false);
+
+		info = new ExpressionInfo();
+		other = new ExpressionInfo();
+		info.addAccessedPropertyName("prop1");
+		other.addAccessedPropertyName("prop2");
+		info.merge(other);
+		assertPropertyAccess(info, new String[] { "prop1", "prop2" }, false);
+	}
+	
 	public void testMergeMisbehavingExpressionTypes() {
 		ExpressionInfo info;
 		ExpressionInfo other;
@@ -176,7 +206,8 @@
 	}
 	
 	public void testTestExpression() {
-		assertDefaultAccessOnly((new TestExpression("namespace", "property", null, new Object())).computeExpressionInfo());
+		assertPropertyAccess((new TestExpression("namespace", "property", null,
+				new Object())).computeExpressionInfo(), "namespace.property", true);
 	}
 	
 	// ---- composite expressions ---------------------------------------------------------
@@ -215,6 +246,7 @@
 		assertFalse("Doesn't accesses system property", info.hasSystemPropertyAccess());
 		assertTrue("No variable accesses", info.getAccessedVariableNames().length == 0);
 		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
 	}
 
 	private void assertSystemPropertyOnly(ExpressionInfo info) {
@@ -222,6 +254,7 @@
 		assertTrue("Accesses system property", info.hasSystemPropertyAccess());
 		assertTrue("No variable accesses", info.getAccessedVariableNames().length == 0);
 		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
 	}
 	
 	private void assertNoAccess(ExpressionInfo info) {
@@ -229,6 +262,7 @@
 		assertFalse("Doesn't accesses system property", info.hasSystemPropertyAccess());
 		assertTrue("No variable accesses", info.getAccessedVariableNames().length == 0);
 		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
 	}
 	
 	private void assertVariableAccess(ExpressionInfo info, String variable) {
@@ -238,6 +272,7 @@
 		assertEquals("One variable accessed", 1, accessedVariableNames.length);
 		assertEquals("Variable accessed", variable, accessedVariableNames[0]);
 		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
 	}
 	
 	private void assertVariableAccess(ExpressionInfo info, String[] variables) {
@@ -249,12 +284,36 @@
 			assertTrue("Variable accessed", accessedVariableNames.contains(variables[i]));
 		}
 		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
+	}
+	
+	private void assertPropertyAccess(ExpressionInfo info, String property, boolean defaultVariable) {
+		assertEquals("Accesses default variable", defaultVariable, info.hasDefaultVariableAccess());
+		assertFalse("Doesn't accesses system property", info.hasSystemPropertyAccess());
+		String[] accessedPropertyNames= info.getAccessedPropertyNames();
+		assertEquals("One property accessed", 1, accessedPropertyNames.length);
+		assertEquals("Property accessed", property, accessedPropertyNames[0]);
+		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No variable accesses", 0, info.getAccessedVariableNames().length);
+	}
+	
+	private void assertPropertyAccess(ExpressionInfo info, String[] properties, boolean defaultVariable) {
+		assertEquals("Accesses default variable", defaultVariable, info.hasDefaultVariableAccess());
+		assertFalse("Doesn't accesses system property", info.hasSystemPropertyAccess());
+		Set accessedPropertyNames= new HashSet(Arrays.asList(info.getAccessedPropertyNames()));
+		assertEquals("All properties accessed", properties.length, accessedPropertyNames.size());
+		for (int i= 0; i < properties.length; i++) {
+			assertTrue("Property accessed", accessedPropertyNames.contains(properties[i]));
+		}
+		assertNull("No misbehaving expression types", info.getMisbehavingExpressionTypes());
+		assertEquals("No variable accesses", 0, info.getAccessedVariableNames().length);
 	}
 	
 	private void assertMisbehavedExpressionTypes(ExpressionInfo info, Class[] types) {
 		assertFalse("Doesn't accesses default variable", info.hasDefaultVariableAccess());
 		assertFalse("Doesn't accesses system property", info.hasSystemPropertyAccess());
 		assertTrue("No variable accesses", info.getAccessedVariableNames().length == 0);
+		assertEquals("No properties accessed", 0, info.getAccessedPropertyNames().length);
 		Set misbehavedTypes= new HashSet(Arrays.asList(info.getMisbehavingExpressionTypes()));
 		assertEquals("All types accessed", types.length, misbehavedTypes.size());
 		for (int i= 0; i < types.length; i++) {