[516963] Diagnose unresolved AS proxies
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/PivotUtil.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/PivotUtil.java
index e3f5c13..228e9e0 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/PivotUtil.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/PivotUtil.java
@@ -29,6 +29,7 @@
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.emf.ecore.xmi.XMLResource;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
@@ -1374,7 +1375,11 @@
 			return ClassUtil.nonNullState(((PropertyCallExp)navigationCallExp).getReferredProperty());
 		}
 		else if (navigationCallExp instanceof OppositePropertyCallExp) {
-			return ClassUtil.nonNullState(((OppositePropertyCallExp)navigationCallExp).getReferredProperty().getOpposite());
+			Property referredProperty = ClassUtil.nonNullState(((OppositePropertyCallExp)navigationCallExp).getReferredProperty());
+			if (referredProperty.eIsProxy() ) {
+				throw new IllegalStateException("Unresolved referred property proxy '" + EcoreUtil.getURI(referredProperty) + "' at '" + EcoreUtil.getURI(navigationCallExp) + "'");
+			}
+			return ClassUtil.nonNullState(referredProperty.getOpposite());
 		}
 		else {
 			throw new IllegalStateException();
diff --git a/plugins/org.eclipse.ocl.xtext.base.ui/src/org/eclipse/ocl/xtext/base/ui/model/BaseCSorASDocumentProvider.java b/plugins/org.eclipse.ocl.xtext.base.ui/src/org/eclipse/ocl/xtext/base/ui/model/BaseCSorASDocumentProvider.java
index 084352e..fa7d3e7 100644
--- a/plugins/org.eclipse.ocl.xtext.base.ui/src/org/eclipse/ocl/xtext/base/ui/model/BaseCSorASDocumentProvider.java
+++ b/plugins/org.eclipse.ocl.xtext.base.ui/src/org/eclipse/ocl/xtext/base/ui/model/BaseCSorASDocumentProvider.java
@@ -19,6 +19,7 @@
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -51,6 +52,7 @@
 import org.eclipse.ocl.pivot.resource.CSResource;
 import org.eclipse.ocl.pivot.resource.CSResource.CSResourceExtension2;
 import org.eclipse.ocl.pivot.utilities.ClassUtil;
+import org.eclipse.ocl.pivot.utilities.TreeIterable;
 import org.eclipse.ocl.xtext.base.ui.BaseUiModule;
 import org.eclipse.ocl.xtext.base.ui.BaseUiPluginHelper;
 import org.eclipse.ui.IEditorInput;
@@ -67,6 +69,40 @@
  */
 public abstract class BaseCSorASDocumentProvider extends BaseDocumentProvider
 {
+	public class UnresolvedProxyDiagnostic implements Resource.Diagnostic
+	{
+		protected final @NonNull String message;
+
+		public UnresolvedProxyDiagnostic(@NonNull String message) {
+			this.message = message;
+		}
+
+		@Override
+		public int getColumn() {
+			return 0;
+		}
+
+		@Override
+		public int getLine() {
+			return 0;
+		}
+
+		@Override
+		public String getLocation() {
+			return null;
+		}
+
+		@Override
+		public String getMessage() {
+			return message;
+		}
+
+		@Override
+		public String toString() {
+			return message;
+		}
+	}
+
 	private static final Logger log = Logger.getLogger(BaseCSorASDocumentProvider.class);
 
 	public static final String PERSIST_AS_PIVOT = "pivot";
@@ -304,7 +340,22 @@
 				}
 				//				xmiResource.load(new InputSource(new StringReader(sourceText)), null);
 				xmiResource.load(inputStream, null);
-				EcoreUtil.resolveAll(asResourceSet);
+				//
+				//	Check that all proxies are resolved. (This is EcoreUtil.resolveAll(asResourceSet) plus diagnostics.)
+				//
+				List<@NonNull Resource> asResources = ClassUtil.nullFree(asResourceSet.getResources());
+				for (int i = 0; i < asResources.size(); i++) {			// Proxy resolution grows domain.
+					Resource resource = asResources.get(i);
+					for (EObject eObject : new TreeIterable(resource)) {
+						for (Iterator<EObject> it =  eObject.eCrossReferences().iterator(); it.hasNext(); ) {
+							EObject eReferencedObject = it.next();
+							if (eReferencedObject.eIsProxy() ) {
+								resource.getErrors().add(new UnresolvedProxyDiagnostic("Unresolved proxy '" + EcoreUtil.getURI(eReferencedObject) + "' at '" + EcoreUtil.getURI(eObject) + "'"));
+							}
+						}
+					}
+				}
+
 				List<Resource.Diagnostic> allErrors = null;
 				for (Resource resource : asResourceSet.getResources()) {
 					List<Resource.Diagnostic> errors = resource.getErrors();
@@ -317,7 +368,7 @@
 				}
 				if (allErrors != null) {
 					Throwable firstThrowable = null;
-					StringWriter s = new StringWriter();
+					StringBuilder s = new StringBuilder();
 					boolean isFirst = true;
 					for (Resource.Diagnostic diagnostic : allErrors) {
 						Object diag = diagnostic;