public override void VisitMemberReferenceExpression(MemberReferenceExpression p) { // Check to see whether this is on the owner of the ProcessCell method. if (p.Target is ThisReferenceExpression) { // Replace the AST node with the current value. var prop = this.Algorithm.GetType().GetProperties().Where(v => v.Name == p.MemberName).DefaultIfEmpty(null).First(); if (prop == null) { throw new NotSupportedException("Unable to inline ProcessCell methods that invoke other methods on this algorithm."); } var value = prop.GetGetMethod().Invoke(this.Algorithm, null); if (value is Enum) { p.ReplaceWith(new PrimitiveExpression(value, value.GetType().FullName.Replace("+", ".") + "." + value)); } else { p.ReplaceWith(new PrimitiveExpression(value)); } } else if (p.Target is IdentifierExpression && (p.Target as IdentifierExpression).Identifier == ParameterContextName) { // This is a reference to the runtime context, which we replace with this. p.Target.ReplaceWith(new ThisReferenceExpression()); } }
/// <summary> /// Removes all occurrences of transparent identifiers /// </summary> void RemoveTransparentIdentifierReferences(AstNode node, Dictionary <string, object> fromOrLetIdentifiers) { foreach (AstNode child in node.Children) { RemoveTransparentIdentifierReferences(child, fromOrLetIdentifiers); } MemberReferenceExpression mre = node as MemberReferenceExpression; if (mre != null) { IdentifierExpression ident = mre.Target as IdentifierExpression; if (ident != null && IsTransparentIdentifier(ident.Identifier)) { IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName); mre.TypeArguments.MoveTo(newIdent.TypeArguments); newIdent.CopyAnnotationsFrom(mre); newIdent.RemoveAnnotations <Semantics.MemberResolveResult>(); // remove the reference to the property of the anonymous type if (fromOrLetIdentifiers.TryGetValue(mre.MemberName, out var annotation)) { newIdent.AddAnnotation(annotation); } mre.ReplaceWith(newIdent); return; } } }
public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { bool result = base.VisitMemberReferenceExpression(memberReferenceExpression); UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression; if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) { PointerReferenceExpression pre = new PointerReferenceExpression(); pre.Target = uoe.Expression.Detach(); pre.MemberName = memberReferenceExpression.MemberName; memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments); pre.CopyAnnotationsFrom(uoe); pre.RemoveAnnotations <ResolveResult>(); // only copy the ResolveResult from the MRE pre.CopyAnnotationsFrom(memberReferenceExpression); memberReferenceExpression.ReplaceWith(pre); } var rr = memberReferenceExpression.GetResolveResult(); if (rr != null) { if (IsUnsafeType(rr.Type)) { return(true); } } return(result); }
public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { bool result = base.VisitMemberReferenceExpression(memberReferenceExpression); UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression; if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) { PointerReferenceExpression pre = new PointerReferenceExpression(); pre.Target = uoe.Expression.Detach(); pre.MemberName = memberReferenceExpression.MemberName; memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments); pre.CopyAnnotationsFrom(uoe); pre.RemoveAnnotations<ResolveResult>(); // only copy the ResolveResult from the MRE pre.CopyAnnotationsFrom(memberReferenceExpression); memberReferenceExpression.ReplaceWith(pre); } var rr = memberReferenceExpression.GetResolveResult(); if (rr != null) { if (rr.Type is PointerType) return true; if (rr is MemberResolveResult mrr && mrr.Member.ReturnType.Kind == TypeKind.Delegate) { var method = mrr.Member.ReturnType.GetDefinition()?.GetDelegateInvokeMethod(); if (method != null && (method.ReturnType is PointerType || method.Parameters.Any(p => p.Type is PointerType))) return true; } } return result; }
public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { bool result = base.VisitMemberReferenceExpression(memberReferenceExpression, data); UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression; if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) { PointerReferenceExpression pre = new PointerReferenceExpression(); pre.Target = uoe.Expression.Detach(); pre.MemberName = memberReferenceExpression.MemberName; memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments); pre.CopyAnnotationsFrom(uoe); pre.CopyAnnotationsFrom(memberReferenceExpression); memberReferenceExpression.ReplaceWith(pre); } return(result); }
/// <summary> /// Removes all occurrences of transparent identifiers /// </summary> void RemoveTransparentIdentifierReferences(AstNode node) { foreach (AstNode child in node.Children) { RemoveTransparentIdentifierReferences(child); } MemberReferenceExpression mre = node as MemberReferenceExpression; if (mre != null) { IdentifierExpression ident = mre.Target as IdentifierExpression; if (ident != null && IsTransparentIdentifier(ident.Identifier)) { IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName); mre.TypeArguments.MoveTo(newIdent.TypeArguments); mre.ReplaceWith(newIdent); return; } } }
/// <summary> /// Removes all occurrences of transparent identifiers /// </summary> void RemoveTransparentIdentifierReferences(AstNode node) { foreach (AstNode child in node.Children) { RemoveTransparentIdentifierReferences(child); } MemberReferenceExpression mre = node as MemberReferenceExpression; if (mre != null) { IdentifierExpression ident = mre.Target as IdentifierExpression; if (ident != null && IsTransparentIdentifier(ident.Identifier)) { IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName); mre.TypeArguments.MoveTo(newIdent.TypeArguments); newIdent.CopyAnnotationsFrom(mre); newIdent.RemoveAnnotations <PropertyDeclaration>(); // remove the reference to the property of the anonymous type mre.ReplaceWith(newIdent); return; } } }
public override object VisitBlockStatement(BlockStatement blockStatement, object data) { int numberOfVariablesOutsideBlock = currentlyUsedVariableNames.Count; base.VisitBlockStatement(blockStatement, data); foreach (ExpressionStatement stmt in blockStatement.Statements.OfType <ExpressionStatement>().ToArray()) { Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt); if (!displayClassAssignmentMatch.Success) { continue; } ILVariable variable = displayClassAssignmentMatch.Get <AstNode>("variable").Single().Annotation <ILVariable>(); if (variable == null) { continue; } TypeDefinition type = variable.Type.ResolveWithinSameModule(); if (!IsPotentialClosure(context, type)) { continue; } if (displayClassAssignmentMatch.Get <AstType>("type").Single().Annotation <TypeReference>().ResolveWithinSameModule() != type) { continue; } // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses: bool ok = true; foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>()) { if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single()) { //check if it a cross reference to another generated delegate class's member if (identExpr.Parent is AssignmentExpression) { if ((identExpr.Parent as AssignmentExpression).Left is MemberReferenceExpression ) { MemberReferenceExpression tleft = (MemberReferenceExpression)(identExpr.Parent as AssignmentExpression).Left; ILVariable v = tleft.Target.Annotation <ILVariable>(); if (v != null) { TypeDefinition vtype = v.Type.ResolveWithinSameModule(); if (vtype.IsNested && IsPotentialClosure(context, vtype)) { Console.WriteLine(identExpr.Parent.ToString() + " cross reference by delegate should be ok"); continue; } } } } if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation <FieldReference>() != null)) { ok = false; break; } } } if (!ok) { continue; } Dictionary <FieldReference, AstNode> dict = new Dictionary <FieldReference, AstNode>(); // Delete the variable declaration statement: VariableDeclarationStatement displayClassVarDecl = PatternStatementTransform.FindVariableDeclaration(stmt, variable.Name); if (displayClassVarDecl != null) { displayClassVarDecl.Remove(); } // Delete the assignment statement: AstNode cur = stmt.NextSibling; stmt.Remove(); // Delete any following statements as long as they assign parameters to the display class BlockStatement rootBlock = blockStatement.Ancestors.OfType <BlockStatement>().LastOrDefault() ?? blockStatement; List <ILVariable> parameterOccurrances = rootBlock.Descendants.OfType <IdentifierExpression>() .Select(n => n.Annotation <ILVariable>()).Where(p => p != null && p.IsParameter).ToList(); AstNode next; for (; cur != null; cur = next) { next = cur.NextSibling; // Test for the pattern: // "variableName.MemberName = right;" ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement( new AssignmentExpression( new NamedNode("left", new MemberReferenceExpression { Target = new IdentifierExpression(variable.Name), MemberName = Pattern.AnyString }), new AnyNode("right") ) ); Match m = closureFieldAssignmentPattern.Match(cur); if (m.Success) { FieldDefinition fieldDef = m.Get <MemberReferenceExpression>("left").Single().Annotation <FieldReference>().ResolveWithinSameModule(); AstNode right = m.Get <AstNode>("right").Single(); bool isParameter = false; bool isDisplayClassParentPointerAssignment = false; if (right is ThisReferenceExpression) { isParameter = true; } else if (right is IdentifierExpression) { // handle parameters only if the whole method contains no other occurrence except for 'right' ILVariable v = right.Annotation <ILVariable>(); isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1; if (!isParameter && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) { // parent display class within the same method // (closure2.localsX = closure1;) isDisplayClassParentPointerAssignment = true; } } else if (right is MemberReferenceExpression) { // copy of parent display class reference from an outer lambda // closure2.localsX = this.localsY MemberReferenceExpression mre = m.Get <MemberReferenceExpression>("right").Single(); do { // descend into the targets of the mre as long as the field types are closures FieldDefinition fieldDef2 = mre.Annotation <FieldReference>().ResolveWithinSameModule(); if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ResolveWithinSameModule())) { break; } // if we finally get to a this reference, it's copying a display class parent pointer if (mre.Target is ThisReferenceExpression) { isDisplayClassParentPointerAssignment = true; } mre = mre.Target as MemberReferenceExpression; } while (mre != null); } if (isParameter || isDisplayClassParentPointerAssignment) { dict[fieldDef] = right; cur.Remove(); } else { break; } } else { //why need to break? continue to match should be ok //break; } } // Now create variables for all fields of the display class (except for those that we already handled as parameters) List <Tuple <AstType, ILVariable> > variablesToDeclare = new List <Tuple <AstType, ILVariable> >(); foreach (FieldDefinition field in type.Fields) { if (field.IsStatic) { continue; // skip static fields } if (dict.ContainsKey(field)) // skip field if it already was handled as parameter { continue; } string capturedVariableName = field.Name; if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10) { capturedVariableName = capturedVariableName.Substring(10); } EnsureVariableNameIsAvailable(blockStatement, capturedVariableName); currentlyUsedVariableNames.Add(capturedVariableName); ILVariable ilVar = new ILVariable { IsGenerated = true, Name = capturedVariableName, Type = field.FieldType, }; variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), ilVar)); dict[field] = new IdentifierExpression(capturedVariableName).WithAnnotation(ilVar); } // Now figure out where the closure was accessed and use the simpler replacement expression there: foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>()) { if (identExpr.Identifier == variable.Name) { if (!(identExpr.Parent is MemberReferenceExpression)) { //will delete by the next round of the cross reference delegate class continue; } MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent; AstNode replacement; if (dict.TryGetValue(mre.Annotation <FieldReference>().ResolveWithinSameModule(), out replacement)) { mre.ReplaceWith(replacement.Clone()); } } } // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works): Statement insertionPoint = blockStatement.Statements.FirstOrDefault(); foreach (var tuple in variablesToDeclare) { var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2.Name); newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation()); newVarDecl.Variables.Single().AddAnnotation(tuple.Item2); blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl); } } currentlyUsedVariableNames.RemoveRange(numberOfVariablesOutsideBlock, currentlyUsedVariableNames.Count - numberOfVariablesOutsideBlock); return(null); }
void RunAction(RefactoringContext context, AstType baseType, string enumName, Dictionary <string, string> newNames, TypeDeclaration containerTypeDeclaration, List <VariableInitializer> variables, Script script) { var names = variables.Select(variable => variable.Name).ToList(); var containerType = (context.Resolve(containerTypeDeclaration) as TypeResolveResult).Type; var fields = containerTypeDeclaration.Members.OfType <FieldDeclaration>().Where(field => field.Modifiers.HasFlag(Modifiers.Const)).ToList(); List <VariableInitializer> variableUnitsToRemove = new List <VariableInitializer>(variables); List <FieldDeclaration> fieldsToRemove = new List <FieldDeclaration>(); foreach (var field in fields) { if (field.Variables.All(variableUnitsToRemove.Contains)) { fieldsToRemove.Add(field); variableUnitsToRemove.RemoveAll(field.Variables.Contains); } } var generatedEnum = CreateEnumDeclaration(baseType, enumName, variables, names, newNames); AstNode root = GetRootNodeOf(containerTypeDeclaration); var newRoot = root.Clone(); FixIdentifiers(context, enumName, variables, containerType, baseType, names, newNames, root, newRoot); foreach (var member in root.Descendants.OfType <MemberReferenceExpression>().Where(member => names.Contains(member.MemberName))) { if (variables.Any(variable => variable.Descendants.Contains(member))) { //Already handled continue; } var resolvedIdentifier = context.Resolve(member) as MemberResolveResult; if (resolvedIdentifier == null) { continue; } if (resolvedIdentifier.Type.Equals(containerType)) { continue; } var equivalentMember = GetEquivalentNodeFor(root, newRoot, member); MemberReferenceExpression memberToReplace = (MemberReferenceExpression)equivalentMember; var replacement = CreateReplacementMemberReference(enumName, baseType, newNames, memberToReplace); memberToReplace.ReplaceWith(replacement); } //Fix the file InsertAfterEquivalent(root, newRoot, containerTypeDeclaration.LBraceToken, generatedEnum, Roles.TypeMemberRole); foreach (var variableToRemove in variableUnitsToRemove) { GetEquivalentNodeFor(root, newRoot, variableToRemove).Remove(); } foreach (var fieldToRemove in fieldsToRemove) { GetEquivalentNodeFor(root, newRoot, fieldToRemove).Remove(); } script.Replace(root, newRoot); ReplaceVariableReferences(context, root, baseType, enumName, script, newNames, variables); }
public override void VisitMemberReferenceExpression(MemberReferenceExpression p) { base.VisitMemberReferenceExpression(p); // Check to see whether this is on the owner of the ProcessCell method. if (p.Target is ThisReferenceExpression) { // Replace the AST node with the current value. var field = this.Algorithm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Where(v => v.Name == p.MemberName).DefaultIfEmpty(null).First(); var prop = this.Algorithm.GetType() .GetProperties() .Where(v => v.Name == p.MemberName) .DefaultIfEmpty(null) .First(); if (prop == null && field == null) throw new NotSupportedException( "Unable to inline ProcessCell methods that invoke other methods on this algorithm."); if (field != null) return; var value = prop.GetGetMethod().Invoke(this.Algorithm, null); if (value is Enum) p.ReplaceWith(new PrimitiveExpression(value, value.GetType().FullName.Replace("+", ".") + "." + value)); else p.ReplaceWith(new PrimitiveExpression(value)); } else if (p.Target is IdentifierExpression && (p.Target as IdentifierExpression).Identifier == ParameterContextName) { // This is a reference to the runtime context, which we replace with this. p.Target.ReplaceWith(new ThisReferenceExpression()); } }
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { if (this.m_Mappings.ContainsKey(memberReferenceExpression.MemberName)) { if (memberReferenceExpression.Target is ThisReferenceExpression) { memberReferenceExpression.ReplaceWith( new IdentifierExpression( this.m_Mappings[memberReferenceExpression.MemberName])); return; } } base.VisitMemberReferenceExpression(memberReferenceExpression); }
public override object VisitBlockStatement(BlockStatement blockStatement, object data) { base.VisitBlockStatement(blockStatement, data); foreach (ExpressionStatement stmt in blockStatement.Statements.OfType <ExpressionStatement>().ToArray()) { Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt); if (displayClassAssignmentMatch == null) { continue; } ILVariable variable = displayClassAssignmentMatch.Get("variable").Single().Annotation <ILVariable>(); if (variable == null) { continue; } TypeDefinition type = variable.Type.ResolveWithinSameModule(); if (!IsPotentialClosure(context, type)) { continue; } if (displayClassAssignmentMatch.Get("type").Single().Annotation <TypeReference>().ResolveWithinSameModule() != type) { continue; } // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses: bool ok = true; foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>()) { if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single()) { if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation <FieldReference>() != null)) { ok = false; } } } if (!ok) { continue; } Dictionary <FieldReference, AstNode> dict = new Dictionary <FieldReference, AstNode>(); // Delete the variable declaration statement: AstNode cur = stmt.NextSibling; stmt.Remove(); if (blockStatement.Parent.NodeType == NodeType.Member || blockStatement.Parent is Accessor) { // Delete any following statements as long as they assign parameters to the display class // Do parameter handling only for closures created in the top scope (direct child of method/accessor) List <ILVariable> parameterOccurrances = blockStatement.Descendants.OfType <IdentifierExpression>() .Select(n => n.Annotation <ILVariable>()).Where(p => p != null && p.IsParameter).ToList(); AstNode next; for (; cur != null; cur = next) { next = cur.NextSibling; // Test for the pattern: // "variableName.MemberName = right;" ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement( new AssignmentExpression( new NamedNode("left", new MemberReferenceExpression { Target = new IdentifierExpression(variable.Name) }), new AnyNode("right") ) ); Match m = closureFieldAssignmentPattern.Match(cur); if (m != null) { AstNode right = m.Get("right").Single(); bool isParameter = false; if (right is ThisReferenceExpression) { isParameter = true; } else if (right is IdentifierExpression) { // handle parameters only if the whole method contains no other occurrance except for 'right' ILVariable param = right.Annotation <ILVariable>(); isParameter = param.IsParameter && parameterOccurrances.Count(c => c == param) == 1; } if (isParameter) { dict[m.Get <MemberReferenceExpression>("left").Single().Annotation <FieldReference>().ResolveWithinSameModule()] = right; cur.Remove(); } else { break; } } else { break; } } } // Now create variables for all fields of the display class (except for those that we already handled as parameters) List <Tuple <AstType, string> > variablesToDeclare = new List <Tuple <AstType, string> >(); foreach (FieldDefinition field in type.Fields) { if (dict.ContainsKey(field)) { continue; } variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), field.Name)); dict[field] = new IdentifierExpression(field.Name); } // Now figure out where the closure was accessed and use the simpler replacement expression there: foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>()) { if (identExpr.Identifier == variable.Name) { MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent; AstNode replacement; if (dict.TryGetValue(mre.Annotation <FieldReference>().ResolveWithinSameModule(), out replacement)) { mre.ReplaceWith(replacement.Clone()); } } } // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works): Statement insertionPoint = blockStatement.Statements.FirstOrDefault(); foreach (var tuple in variablesToDeclare) { var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2); newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation()); blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl); } } return(null); }
public override void VisitMemberReferenceExpression(MemberReferenceExpression e) { var md = e.Annotation<MethodDefinition>(); if (md != null && md.IsPrivate && md.IsCompilerGenerated()) { //public override void OnMasterMouseLeave(ModifierMouseArgs e) //{ // this.TB(ModifierGroup.YB, e); //} // //[CompilerGenerated] //private static void YB(IChartModifier x, ModifierEventArgsBase y) //{ // x.OnMasterMouseLeave((ModifierMouseArgs)y); //} // //====> //public override void OnMasterMouseLeave(ModifierMouseArgs e) //{ // this.TB((x, y) => x.OnMasterMouseLeave((ModifierMouseArgs)y), e); //} var td = e.Ancestors.OfType<TypeDeclaration>().FirstOrDefault(); if (td != null) { var method = td.Members.OfType<MethodDeclaration>().FirstOrDefault(x => x.Annotation<MethodDefinition>() == md); if (method != null) { LambdaExpression le = new LambdaExpression(); var body = method.Body; if (body.Statements.Count == 1) { le.Body = TryReduceLambdaBody(body.Statements.First()).Detach(); } else { le.Body = body.Detach(); } // 设置 Lambda 函数参数 if (method.Parameters.Count > 0) { var prmNames = new[] { "x", "y", "z", "u", "v", "w", "m", "n", "p", "q", "r", "s", "t" }; var usedNames = new HashSet<string>(body.Descendants.OfType<IdentifierExpression>().Select(x => x.Identifier).Distinct()); var index = 0; foreach (var x in method.Parameters) { var pn = index < prmNames.Length ? prmNames[index] : "e" + index.ToString(); index++; while (usedNames.Contains(pn)) { pn = index < prmNames.Length ? prmNames[index] : "e" + index.ToString(); index++; } foreach (var r in le.Body.Descendants.OfType<IdentifierExpression>().Where(r => r.Identifier == x.Name)) { r.Identifier = pn; } le.Parameters.Add(new ParameterDeclaration(pn)); } } DelayRemove(method); e.ReplaceWith(le); } } } base.VisitMemberReferenceExpression(e); }