public override void VisitClassDeclaration(ClassDeclarationSyntax node) { if (node.ShouldBeHidden()) return; ++ClassDepth; if (ClassDepth == 1) { base.VisitClassDeclaration(node); } else if (node.ChildNodes().All(childNode => childNode is PropertyDeclarationSyntax || childNode is AttributeListSyntax)) { // simple nested POCO var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); walker.Visit(node); this.Blocks.AddRange(walker.Blocks); } else { var methods = node.ChildNodes().OfType<MethodDeclarationSyntax>(); if (!methods.Any(m => m.AttributeLists.SelectMany(a => a.Attributes).Any())) { // nested class with methods that are not unit or integration tests e.g. example PropertyVisitor in Automap.doc.cs var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); walker.Visit(node); this.Blocks.AddRange(walker.Blocks); } } --ClassDepth; }
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) { var typeList = node.ChildNodes().OfType<TypeParameterListSyntax>(); if (typeList.Any()) return node.RemoveNodes(typeList, SyntaxRemoveOptions.KeepEndOfLine); return node; }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { ++ClassDepth; if (ClassDepth == 1) { base.VisitClassDeclaration(node); } // are we dealing with a simple nested POCO? else if (node.ChildNodes().All(childNode => childNode is PropertyDeclarationSyntax || childNode is AttributeListSyntax)) { var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); walker.Visit(node); this.Blocks.AddRange(walker.Blocks); } --ClassDepth; }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { // generate empty ctor if necessary if (node.HasInitializableMembers(model) && !node.HasDefaultConstructor()) { cb.AppendWithIndent(node.Identifier.ToString()) .Append("::") .Append(node.Identifier.ToString()) .AppendLine("() :"); //cb.Indent(() => //{ // AppendFieldInitializers(node); //}); cb.AppendLine("{}").AppendLine(); } // generate static initialization foreach (var fields in node.ChildNodes().OfType<FieldDeclarationSyntax>()) { foreach (var v in fields.Declaration.Variables) { var z = (IFieldSymbol)model.GetDeclaredSymbol(v); if (z.IsStatic && v.Initializer != null) { cb.AppendWithIndent("extern ") .Append(node.Identifier.ToString()) .Append("::") .Append(v.Identifier.ToString()) .Append(" = ") .Append(v.Initializer.Value.ToString()) .AppendLine(";").AppendLine(); } } } base.VisitClassDeclaration(node); }
public SyntaxTree UnWeave(ClassDeclarationSyntax c) { var foundMethods = c.ChildNodes().OfType<MethodDeclarationSyntax>().Where(HasBeenWeaved); return WeaveOrUnWeave(foundMethods, UnWeaveMethod); }
/// <summary> /// Tries to get the list of potential methods that can override the given virtual call. /// If it cannot find such methods then it returns false. /// </summary> /// <param name="overriders">List of overrider methods</param> /// <param name="virtualCall">Virtual call</param> /// <param name="syntaxNode">SyntaxNode</param> /// <param name="cfgNode">ControlFlowGraphNode</param> /// <param name="originalMachine">Original machine</param> /// <param name="model">SemanticModel</param> /// <param name="context">AnalysisContext</param> /// <returns>Boolean</returns> internal static bool TryGetPotentialMethodOverriders(out HashSet<MethodDeclarationSyntax> overriders, InvocationExpressionSyntax virtualCall, SyntaxNode syntaxNode, ControlFlowGraphNode cfgNode, ClassDeclarationSyntax originalMachine, SemanticModel model, AnalysisContext context) { overriders = new HashSet<MethodDeclarationSyntax>(); ISymbol calleeSymbol = null; SimpleNameSyntax callee = null; bool isThis = false; if (virtualCall.Expression is MemberAccessExpressionSyntax) { var expr = virtualCall.Expression as MemberAccessExpressionSyntax; var identifier = expr.Expression.DescendantNodesAndSelf(). OfType<IdentifierNameSyntax>().Last(); calleeSymbol = model.GetSymbolInfo(identifier).Symbol; if (expr.Expression is ThisExpressionSyntax || context.IsMachineType(identifier, model)) { callee = expr.Name; isThis = true; } } else { callee = virtualCall.Expression as IdentifierNameSyntax; isThis = true; } if (isThis) { foreach (var nestedClass in originalMachine.ChildNodes().OfType<ClassDeclarationSyntax>()) { foreach (var method in nestedClass.ChildNodes().OfType<MethodDeclarationSyntax>()) { if (method.Identifier.ToString().Equals(callee.Identifier.ToString())) { overriders.Add(method); return true; } } } foreach (var method in originalMachine.ChildNodes().OfType<MethodDeclarationSyntax>()) { if (method.Identifier.ToString().Equals(callee.Identifier.ToString())) { overriders.Add(method); return true; } } return false; } if (calleeSymbol == null) { return false; } Dictionary<ISymbol, HashSet<ITypeSymbol>> objectTypeMap = null; if (!cfgNode.Summary.DataFlowMap.TryGetObjectTypeMapForSyntaxNode( syntaxNode, cfgNode, out objectTypeMap)) { return false; } if (!objectTypeMap.ContainsKey(calleeSymbol)) { return false; } foreach (var objectType in objectTypeMap[calleeSymbol]) { MethodDeclarationSyntax m = null; if (InheritanceAnalysis.TryGetMethodFromType(out m, objectType, virtualCall, context)) { overriders.Add(m); } } return true; }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { // be sure to add the includes cb.AppendLine($"#include <{node.Identifier.Text}.h>") .AppendLine(); // generate empty ctor if necessary if (node.HasInitializableMembers(model) && !node.HasDefaultConstructor()) { cb.AppendWithIndent(node.Identifier.ToString()) .Append("::") .Append(node.Identifier.ToString()) .AppendLine("() :"); //cb.Indent(() => //{ // AppendFieldInitializers(node); //}); cb.AppendLine("{}").AppendLine(); } // generate static initialization foreach (var fields in node.ChildNodes().OfType<FieldDeclarationSyntax>()) { foreach (var v in fields.Declaration.Variables) { var z = (IFieldSymbol)model.GetDeclaredSymbol(v); if (z.IsStatic && v.Initializer != null) { var cppType = z.Type.ToCppType(); string initExpression; if (cppType.Contains("shared_ptr")) { var argumentList = new StringBuilder(); var evcs = v.Initializer as EqualsValueClauseSyntax; if (evcs != null) { var oces = evcs.Value as ObjectCreationExpressionSyntax; if (oces != null) { var count = oces.ArgumentList.Arguments.Count; for (int i = 0; i < count; i++) { var a = oces.ArgumentList.Arguments[i]; argumentList.Append(a.ToFullString()); if (i + 1 != count) argumentList.Append(","); } } } initExpression = $"std::make_shared<{z.Type.Name}>({argumentList})"; } else { initExpression = v.Initializer.Value.ToString(); } cb.AppendWithIndent("extern ") .Append(node.Identifier.ToString()) .Append("::") .Append(v.Identifier.ToString()) .Append(" = ") .Append(initExpression) .AppendLine(";").AppendLine(); } } } base.VisitClassDeclaration(node); }
private void AppendFieldInitializers(ClassDeclarationSyntax node) { foreach (var fields in node.ChildNodes().OfType<FieldDeclarationSyntax>() .Where(f => f.RequiresInitialization(model))) { var vs = new List<Tuple<VariableDeclaratorSyntax, IFieldSymbol>>(); foreach (var v in fields.Declaration.Variables) { var z = (IFieldSymbol) model.GetDeclaredSymbol(v); if (!z.IsStatic) { vs.Add(new Tuple<VariableDeclaratorSyntax, IFieldSymbol>(v,z)); } } for (int i = 0; i < vs.Count; ++i) { var v = vs[i].Item1; var symbol = vs[i].Item2; cb.AppendWithIndent(v.Identifier.ToString()).Append("("); // if the field has an initer, use that instead if (v.Initializer != null) { cb.Append(v.Initializer.Value.ToString()); } else { cb.Append(symbol.Type.GetDefaultValue()); } cb.Append(")"); if (i + 1 != vs.Count) cb.Append(","); cb.AppendLine(); } } }
/// <summary> /// Checks if the given name is a state of the given machine. /// </summary> /// <param name="name">string</param> /// <param name="machine">Machine</param> /// <returns>Boolean value</returns> private static bool IsStateOfTheMachine(string name, ClassDeclarationSyntax machine) { List<string> stateNames = new List<string>(); foreach (var nestedClass in machine.ChildNodes().OfType<ClassDeclarationSyntax>()) { stateNames.Add(nestedClass.Identifier.ValueText); } if (stateNames.Any(str => str.Equals(name))) { return true; } return false; }
/// <summary> /// Computes the summary for the given method. /// </summary> /// <param name="method">Method</param> /// <param name="machine">Machine</param> /// <param name="state">State</param> private void ComputeSummaryForMethod(MethodDeclarationSyntax method, ClassDeclarationSyntax machine, ClassDeclarationSyntax state) { List<InvocationExpressionSyntax> givesUpSources = new List<InvocationExpressionSyntax>(); foreach (var call in method.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var model = this.AnalysisContext.Compilation.GetSemanticModel(call.SyntaxTree); var callSymbol = model.GetSymbolInfo(call).Symbol; if (callSymbol == null) { continue; } var definition = SymbolFinder.FindSourceDefinitionAsync(callSymbol, this.AnalysisContext.Solution).Result; if (definition == null) { continue; } var callee = this.AnalysisContext.GetCallee(call); var calleeMethod = definition.DeclaringSyntaxReferences.First().GetSyntax() as BaseMethodDeclarationSyntax; if (this.AnalysisContext.IsSourceOfGivingUpOwnership(call, model, callee) || this.AnalysisContext.Summaries.ContainsKey(calleeMethod)) { givesUpSources.Add(call); } else if (machine.ChildNodes().OfType<BaseMethodDeclarationSyntax>().Contains(calleeMethod) && !this.AnalysisContext.Summaries.ContainsKey(calleeMethod) && !calleeMethod.Modifiers.Any(SyntaxKind.AbstractKeyword)) { return; } } MethodSummary summary = MethodSummary.Factory.Summarize(this.AnalysisContext, method, machine, state); foreach (var givesUpNode in summary.GivesUpNodes) { this.TryComputeGivesUpSetForSendControlFlowGraphNode(givesUpNode, summary); this.TryComputeGivesUpSetForCreateControlFlowGraphNode(givesUpNode, summary); this.TryComputeGivesUpSetForGenericControlFlowGraphNode(givesUpNode, summary); } }
/// <summary> /// Analyses all the eligible methods of the given machine to compute each /// method summary. This process continues until it reaches a fix point. /// </summary> /// <param name="machine">Machine</param> private void AnalyseMethodsInMachine(ClassDeclarationSyntax machine) { int fixPoint = 0; foreach (var nestedClass in machine.ChildNodes().OfType<ClassDeclarationSyntax>()) { foreach (var method in nestedClass.ChildNodes().OfType<MethodDeclarationSyntax>()) { if (!this.AnalysisContext.ShouldAnalyseMethod(method) || this.AnalysisContext.Summaries.ContainsKey(method)) { continue; } this.ComputeSummaryForMethod(method, machine, nestedClass); if (!this.AnalysisContext.Summaries.ContainsKey(method)) { fixPoint++; } } } foreach (var method in machine.ChildNodes().OfType<MethodDeclarationSyntax>()) { if (!this.AnalysisContext.ShouldAnalyseMethod(method) || this.AnalysisContext.Summaries.ContainsKey(method)) { continue; } this.ComputeSummaryForMethod(method, machine, null); if (!this.AnalysisContext.Summaries.ContainsKey(method)) { fixPoint++; } } if (fixPoint > 0) { this.AnalyseMethodsInMachine(machine); } }
/// <summary> /// Tries to parse and return the state transitions for the given machine. /// </summary> /// <param name="stateTransitions">State transitions</param> /// <param name="machine">Machine</param> /// <param name="model">SemanticModel</param> /// <returns>Boolean value</returns> private bool TryParseStateTransitions(out Dictionary<ClassDeclarationSyntax, HashSet<ClassDeclarationSyntax>> stateTransitions, ClassDeclarationSyntax machine, SemanticModel model) { stateTransitions = new Dictionary<ClassDeclarationSyntax, HashSet<ClassDeclarationSyntax>>(); var defineGotoStateTransitionsMethod = machine.ChildNodes(). OfType<MethodDeclarationSyntax>().FirstOrDefault(v => v.Identifier.ValueText.Equals("DefineGotoStateTransitions") && v.Modifiers.Any(SyntaxKind.OverrideKeyword) && v.ReturnType.ToString(). Equals("System.Collections.Generic.Dictionary<Type, GotoStateTransitions>")); if (defineGotoStateTransitionsMethod == null) { return false; } var returnStmt = defineGotoStateTransitionsMethod.DescendantNodes(). OfType<ReturnStatementSyntax>().First(); var returnSymbol = model.GetSymbolInfo(returnStmt.Expression).Symbol; Dictionary<ClassDeclarationSyntax, IdentifierNameSyntax> stateMap = null; if (!this.TryParseStateMap(out stateMap, returnSymbol, defineGotoStateTransitionsMethod, model)) { return false; } foreach (var state in stateMap) { if (state.Value == null) { continue; } var dictionarySymbol = model.GetSymbolInfo(state.Value).Symbol; var dictionaryInvocations = this.GetInvocationsFromSymbol( dictionarySymbol, defineGotoStateTransitionsMethod); var transitions = ParseTransitions(dictionarySymbol, defineGotoStateTransitionsMethod, model); if (transitions.Count == 0) { continue; } stateTransitions.Add(state.Key, transitions); } return true; }
public Class TraverseClass(ClassDeclarationSyntax cds) { Class retClass = new Class(); //public List<Delegate> Delegates { get; set; } //public List<Method> FunctionDefs { get; set; } //public Inheritance Inheritance { get; set; } //public List<Module> Modules { get; set; } //public List<Preprocessor> Preprocessors { get; set; } //public List<Property> Properties { get; set; } //public List<Union> Unions { get; set; } retClass.Name = cds.Identifier.ValueText; if (cds.HasLeadingTrivia) { SetOuterComments(retClass, cds.GetLeadingTrivia().ToFullString()); } if (cds.HasTrailingTrivia) { SetInnerComments(retClass, cds.GetTrailingTrivia().ToFullString()); } foreach (SyntaxToken st in cds.Modifiers) { string modifier = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(st.ValueText); Encapsulation encap; Qualifiers qual; if (System.Enum.TryParse<Encapsulation>( modifier, out encap)) { retClass.Encapsulation.Add(encap); } else if (System.Enum.TryParse<Qualifiers>(modifier, out qual)) { retClass.Qualifiers.Add(qual); } } var enums = from aEnu in cds.ChildNodes().OfType<EnumDeclarationSyntax>() select aEnu; foreach (EnumDeclarationSyntax eds in enums) { retClass.Enums.Add(TraverseEnums(eds)); } var structs = from aStruct in cds.ChildNodes().OfType<StructDeclarationSyntax>() select aStruct; foreach (StructDeclarationSyntax sds in structs) { retClass.Structs.Add(TransverseStructs(sds)); } var methods = from aMethod in cds.ChildNodes().OfType<MethodDeclarationSyntax>() select aMethod; foreach (MethodDeclarationSyntax mds in methods) { retClass.Methods.Add(TransverseMethods(mds)); } var Fields = from aField in cds.ChildNodes().OfType<FieldDeclarationSyntax>() select aField; foreach (FieldDeclarationSyntax fds in Fields) { retClass.Fields.Add(TransverseVariables(fds)); } //var properties = from aProperty in cds.ChildNodes().OfType<PropertyDeclarationSyntax>() select aProperty; //foreach (PropertyDeclarationSyntax pds in properties) //{ // //traverse attributes //} var constructors = from aConstructor in cds.ChildNodes().OfType<ConstructorDeclarationSyntax>() select aConstructor; foreach (ConstructorDeclarationSyntax cods in constructors) { retClass.Constructors.Add(TransverseConstructors(cods)); } var destructors = from aDestructor in cds.ChildNodes().OfType<DestructorDeclarationSyntax>() select aDestructor; foreach (DestructorDeclarationSyntax dds in destructors) { retClass.Destructors.Add(TransverseDestructors(dds)); } var classes = from aClass in cds.ChildNodes().OfType<ClassDeclarationSyntax>() select aClass; foreach (ClassDeclarationSyntax cds2 in classes) { retClass.Classes.Add(TraverseClass(cds2)); } return retClass; }