static void _Patch(CodeVariableDeclarationStatement vd, CodeDomVisitContext ctx, CodeDomResolver resolver) { if (null != vd) { if (CodeDomResolver.IsNullOrVoidType(vd.Type) || (0 == vd.Type.ArrayRank && 0 == vd.Type.TypeArguments.Count && 0 == string.Compare("var", vd.Type.BaseType, StringComparison.InvariantCulture))) { if (null == vd.InitExpression) { throw new ArgumentException(_AppendLineInfo("The code contains an incomplete variable declaration", vd), "resolver"); } if (!_HasUnresolved(vd.InitExpression)) { var t = resolver.GetTypeOfExpression(vd.InitExpression, resolver.GetScope(vd.InitExpression)); vd.Type = t; if (!CodeDomResolver.IsNullOrVoidType(t)) { vd.UserData.Remove("slang:unresolved"); } } } } }
static void _Patch(CodeFieldReferenceExpression fr, CodeDomVisitContext ctx, CodeDomResolver resolver) { if (null != fr) { // this probably means part of our field has been resolved, or at the very least // it does not come from a rooted var ref. if (!fr.TargetObject.UserData.Contains("slang:unresolved")) { var scope = resolver.GetScope(fr); var binder = new CodeDomBinder(scope); var t = resolver.GetTypeOfExpression(fr.TargetObject, scope); if (null != t && CodeDomResolver.IsNullOrVoidType(t) && fr.TargetObject is CodeVariableReferenceExpression) { return; // can't patch this field yet - it's part of a var reference that hasn't been filled in } var isStatic = false; var tre = fr.TargetObject as CodeTypeReferenceExpression; if (null != tre) { isStatic = true; } var tt = resolver.TryResolveType(isStatic ? tre.Type : t, scope, true); if (null == tt) { throw new InvalidOperationException(_AppendLineInfo(string.Format("The type {0} could not be resolved", t.BaseType), t)); } var td = tt as CodeTypeDeclaration; // TODO: This code could be a lot faster if we added some functionality to the binder // we're just checking to see if the method, property or field exists var m = binder.GetField(tt, fr.FieldName, _BindFlags); if (null != m) { fr.UserData.Remove("slang:unresolved"); return; } m = binder.GetEvent(tt, fr.FieldName, _BindFlags); if (null != m) { var er = new CodeEventReferenceExpression(fr.TargetObject, fr.FieldName); CodeDomVisitor.ReplaceTarget(ctx, er); return; } var ml = binder.GetMethodGroup(tt, fr.FieldName, _BindFlags); if (0 < ml.Length) { var mr = new CodeMethodReferenceExpression(fr.TargetObject, fr.FieldName); CodeDomVisitor.ReplaceTarget(ctx, mr); return; } ml = binder.GetPropertyGroup(tt, fr.FieldName, _BindFlags); if (0 < ml.Length) { var pr = new CodePropertyReferenceExpression(fr.TargetObject, fr.FieldName); CodeDomVisitor.ReplaceTarget(ctx, pr); return; } throw new InvalidProgramException(_AppendLineInfo(string.Format("Cannot deterimine the target reference {0}", fr.FieldName), fr)); } // TODO: This used to be first but I moved it here. // This shouldn't be done first because it's resolving types before fields and // that is a no no. I still need to make sure it doesn't break things var path = _GetUnresRootPathOfExpression(fr); if (null != path) { // now we have something to work with. var scope = resolver.GetScope(fr); var sa = path.Split('.'); if (1 == sa.Length) { System.Diagnostics.Debugger.Break(); throw new NotImplementedException(); } else { object t = null; string tn = null; CodeExpression tf = fr; CodeExpression ptf = null; CodeTypeReference ctr = null; for (var i = sa.Length - 1; i >= 1; --i) { tn = string.Join(".", sa, 0, i); ptf = tf; tf = _GetTargetOfExpression(tf); ctr = new CodeTypeReference(tn); t = resolver.TryResolveType(ctr, scope); if (null != t) { break; } } if (null != t) { var tt = t as Type; if (null != tt) { ctr = new CodeTypeReference(tt); } else { ctr = resolver.GetQualifiedType(ctr, scope); } // we found a type reference _SetTargetOfExpression(ptf, new CodeTypeReferenceExpression(ctr)); return; //args.Cancel = true; } } } } }
static void _Patch(CodeVariableReferenceExpression vr, CodeDomVisitContext ctx, CodeDomResolver resolver) { if (null != vr) { var scope = resolver.GetScope(vr); if (0 == string.Compare("value", vr.VariableName, StringComparison.InvariantCulture)) { // this could be a property set value reference var p = scope.Member as CodeMemberProperty; if (null != p) { var found = false; for (int ic = p.SetStatements.Count, i = 0; i < ic; ++i) { found = false; CodeDomVisitor.Visit(p.SetStatements[i], (ctx2) => { if (ctx2.Target == vr) { found = true; ctx2.Cancel = true; } }); if (found) { break; } } if (found) { CodeDomVisitor.ReplaceTarget(ctx, new CodePropertySetValueReferenceExpression()); return; } } } CodeTypeReference ctr; if (scope.VariableTypes.TryGetValue(vr.VariableName, out ctr)) { if (!CodeDomResolver.IsNullOrVoidType(ctr)) { vr.UserData.Remove("slang:unresolved"); return; } } // we need to replace it. if (scope.ArgumentTypes.ContainsKey(vr.VariableName)) { var a = new CodeArgumentReferenceExpression(vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, a); return; //args.Cancel = true; } else if (scope.FieldNames.Contains(vr.VariableName)) { CodeTypeReference tref; // find out where it belongs. if (scope.ThisTargets.Contains(vr.VariableName)) { var f = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, f); //return; } else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref)) { var f = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, f); //return; } return; } else if (scope.MethodNames.Contains(vr.VariableName)) { CodeTypeReference tref; // find out where it belongs. if (scope.ThisTargets.Contains(vr.VariableName)) { var m = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, m); return; //args.Cancel = true; } if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref)) { var m = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, m); return; //args.Cancel = true; } } else if (scope.PropertyNames.Contains(vr.VariableName)) { CodeTypeReference tref; // find out where it belongs. if (scope.ThisTargets.Contains(vr.VariableName)) { var p = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, p); return; //args.Cancel = true; } else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref)) { var p = new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, p); return; //args.Cancel = true; } } else if (scope.EventNames.Contains(vr.VariableName)) { CodeTypeReference tref; // find out where it belongs. if (scope.ThisTargets.Contains(vr.VariableName)) { var e = new CodeEventReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, e); return; //args.Cancel = true; } else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref)) { var e = new CodeEventReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName); CodeDomVisitor.ReplaceTarget(ctx, e); return; //args.Cancel = true; } } return; } return; }