/// <summary> /// Processes each rule object by creating tokens and associated actions /// </summary> /// <param name="rootobject">An object containing tokens and actions to run on these tokens</param> private void ProcessObject(Rootobject rootobject) { var namespaces = rootobject.NameSpaces; foreach (var @namespace in namespaces) { if (@namespace.Actions != null && @namespace.Actions.Count > 0) { //Global Actions: if (@namespace.@namespace == Constants.Project && @namespace.Assembly == Constants.Project) { var projectToken = _rootNodes.ProjectTokens.FirstOrDefault(); ParseActions(projectToken, @namespace.Actions); } //Namespace specific actions: else { var usingToken = new UsingDirectiveToken() { Key = @namespace.@namespace }; var namespaceToken = new NamespaceToken() { Key = @namespace.@namespace }; if (!_rootNodes.Usingdirectivetokens.Contains(usingToken)) { _rootNodes.Usingdirectivetokens.Add(usingToken); } if (!_rootNodes.NamespaceTokens.Contains(namespaceToken)) { _rootNodes.NamespaceTokens.Add(namespaceToken); } ParseActions(usingToken, @namespace.Actions); ParseActions(namespaceToken, @namespace.Actions); } } foreach (var @class in @namespace.Classes) { if (@class.Actions != null && @class.Actions.Count > 0) { if (@class.KeyType == CTA.Rules.Config.Constants.BaseClass || @class.KeyType == CTA.Rules.Config.Constants.ClassName) { var token = new ClassDeclarationToken() { Key = @class.FullKey, FullKey = @class.FullKey, Namespace = @namespace.@namespace }; if (!_rootNodes.Classdeclarationtokens.Contains(token)) { _rootNodes.Classdeclarationtokens.Add(token); } ParseActions(token, @class.Actions); } else if (@class.KeyType == CTA.Rules.Config.Constants.Identifier) { var token = new IdentifierNameToken() { Key = @class.FullKey, FullKey = @class.FullKey, Namespace = @namespace.@namespace }; if (!_rootNodes.Identifiernametokens.Contains(token)) { _rootNodes.Identifiernametokens.Add(token); } ParseActions(token, @class.Actions); } } foreach (var attribute in @class.Attributes) { if (attribute.Actions != null && attribute.Actions.Count > 0) { var token = new AttributeToken() { Key = attribute.Key, Namespace = @namespace.@namespace, FullKey = attribute.FullKey, Type = @class.Key }; if (!_rootNodes.Attributetokens.Contains(token)) { _rootNodes.Attributetokens.Add(token); } ParseActions(token, attribute.Actions); } } foreach (var method in @class.Methods) { if (method.Actions != null && method.Actions.Count > 0) { var token = new InvocationExpressionToken() { Key = method.Key, Namespace = @namespace.@namespace, FullKey = method.FullKey, Type = @class.Key }; if (!_rootNodes.Invocationexpressiontokens.Contains(token)) { _rootNodes.Invocationexpressiontokens.Add(token); } ParseActions(token, method.Actions); } } foreach (var objectCreation in @class.ObjectCreations) { if (objectCreation.Actions != null && objectCreation.Actions.Count > 0) { var token = new ObjectCreationExpressionToken() { Key = objectCreation.Key, Namespace = @namespace.@namespace, FullKey = objectCreation.FullKey, Type = @class.Key }; if (!_rootNodes.ObjectCreationExpressionTokens.Contains(token)) { _rootNodes.ObjectCreationExpressionTokens.Add(token); } ParseActions(token, objectCreation.Actions); } } } foreach (var @interface in @namespace.Interfaces) { if (@interface.Actions != null && @interface.Actions.Count > 0) { if (@interface.KeyType == CTA.Rules.Config.Constants.BaseClass || @interface.KeyType == CTA.Rules.Config.Constants.InterfaceName) { var token = new InterfaceDeclarationToken() { Key = @interface.FullKey, FullKey = @interface.FullKey, Namespace = @namespace.@namespace }; if (!_rootNodes.InterfaceDeclarationTokens.Contains(token)) { _rootNodes.InterfaceDeclarationTokens.Add(token); } ParseActions(token, @interface.Actions); } else if (@interface.KeyType == CTA.Rules.Config.Constants.Identifier) { var token = new IdentifierNameToken() { Key = @interface.FullKey, FullKey = @interface.FullKey, Namespace = @namespace.@namespace }; if (!_rootNodes.Identifiernametokens.Contains(token)) { _rootNodes.Identifiernametokens.Add(token); } ParseActions(token, @interface.Actions); } } foreach (var attribute in @interface.Attributes) { if (attribute.Actions != null && attribute.Actions.Count > 0) { var token = new AttributeToken() { Key = attribute.Key, Namespace = @namespace.@namespace, FullKey = attribute.FullKey, Type = @interface.Key }; if (!_rootNodes.Attributetokens.Contains(token)) { _rootNodes.Attributetokens.Add(token); } ParseActions(token, attribute.Actions); } } foreach (var method in @interface.Methods) { if (method.Actions != null && method.Actions.Count > 0) { var token = new InvocationExpressionToken() { Key = method.Key, Namespace = @namespace.@namespace, FullKey = method.FullKey, Type = @interface.Key }; if (!_rootNodes.Invocationexpressiontokens.Contains(token)) { _rootNodes.Invocationexpressiontokens.Add(token); } ParseActions(token, method.Actions); } } } } }
/// <summary> /// Analyzes children of nodes in a particular file /// </summary> /// <param name="fileAction">The object containing the actions to run on the file</param> /// <param name="children">List of child nodes to check</param> /// <param name="level">Recursion level to avoid stack overflows</param> private bool AnalyzeChildren(FileActions fileAction, UstList <UstNode> children, int level, string parentNamespace = "", string parentClass = "") { bool containsActions = false; if (children == null || level > Constants.MaxRecursionDepth) { return(false); } foreach (var child in children) { try { switch (child.NodeType) { case IdConstants.AnnotationIdName: { var annotation = (Annotation)child; var compareToken = new AttributeToken() { Key = annotation.Identifier, Namespace = annotation.Reference.Namespace, Type = annotation.SemanticClassType }; AttributeToken token = null; _rootNodes.Attributetokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } break; } case IdConstants.UsingDirectiveIdName: { var compareToken = new UsingDirectiveToken() { Key = child.Identifier }; UsingDirectiveToken token = null; _rootNodes.Usingdirectivetokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } break; } case IdConstants.NamespaceIdName: { var compareToken = new NamespaceToken() { Key = child.Identifier }; NamespaceToken token = null; _rootNodes.NamespaceTokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, child.Identifier)) { containsActions = true; } break; } case IdConstants.ClassIdName: { var classType = (ClassDeclaration)child; var baseToken = new ClassDeclarationToken() { FullKey = classType.BaseType }; ClassDeclarationToken token = null; _rootNodes.Classdeclarationtokens.TryGetValue(baseToken, out token); if (token != null) { //In case of class declarations, add actions on the class by name, instead of property AddNamedActions(fileAction, token, classType.Identifier, child.TextSpan); AddActions(fileAction, token, child.TextSpan); containsActions = true; } token = null; string name = string.Concat(classType.Reference != null ? string.Concat(classType.Reference.Namespace, ".") : string.Empty, classType.Identifier); var nameToken = new ClassDeclarationToken() { FullKey = name }; _rootNodes.Classdeclarationtokens.TryGetValue(nameToken, out token); if (token != null) { //In case of class declarations, add actions on the class by name, instead of property AddNamedActions(fileAction, token, classType.Identifier, child.TextSpan); AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, classType.Identifier)) { containsActions = true; } break; } case IdConstants.InterfaceIdName: { var interfaceType = (InterfaceDeclaration)child; var baseToken = new InterfaceDeclarationToken() { FullKey = interfaceType.BaseType }; InterfaceDeclarationToken token = null; if (!string.IsNullOrEmpty(interfaceType.BaseType)) { _rootNodes.InterfaceDeclarationTokens.TryGetValue(baseToken, out token); } if (token != null) { //In case of interface declarations, add actions on the interface by name, instead of property AddNamedActions(fileAction, token, interfaceType.Identifier, child.TextSpan); AddActions(fileAction, token, child.TextSpan); containsActions = true; } token = null; string name = string.Concat(interfaceType.Reference != null ? string.Concat(interfaceType.Reference.Namespace, ".") : string.Empty, interfaceType.Identifier); var nameToken = new InterfaceDeclarationToken() { FullKey = name }; _rootNodes.InterfaceDeclarationTokens.TryGetValue(nameToken, out token); if (token != null) { //In case of interface declarations, add actions on the interface by name, instead of property AddNamedActions(fileAction, token, interfaceType.Identifier, child.TextSpan); AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace)) { containsActions = true; } break; } case IdConstants.MethodIdName: { var compareToken = new MethodDeclarationToken() { FullKey = string.Concat(child.Identifier) }; MethodDeclarationToken token = null; _rootNodes.MethodDeclarationTokens.TryGetValue(compareToken, out token); if (token != null) { AddNamedActions(fileAction, token, child.Identifier, child.TextSpan); AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } case IdConstants.InvocationIdName: { InvocationExpression invocationExpression = (InvocationExpression)child; var compareToken = new InvocationExpressionToken() { Key = invocationExpression.MethodName, Namespace = invocationExpression.Reference.Namespace, Type = invocationExpression.SemanticClassType }; InvocationExpressionToken token = null; _rootNodes.Invocationexpressiontokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } case IdConstants.DeclarationNodeIdName: { var declarationNode = (DeclarationNode)child; var compareToken = new IdentifierNameToken() { Key = string.Concat(declarationNode.Reference.Namespace, ".", declarationNode.Identifier), Namespace = declarationNode.Reference.Namespace }; IdentifierNameToken token = null; _rootNodes.Identifiernametokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } case IdConstants.ObjectCreationIdName: { var objectCreationNode = (ObjectCreationExpression)child; //Rules based on Object Creation Parent Hierarchy var compareToken = new ObjectCreationExpressionToken() { Key = objectCreationNode.Identifier, Namespace = objectCreationNode.Reference?.Namespace, Type = objectCreationNode.SemanticClassType }; ObjectCreationExpressionToken token = null; _rootNodes.ObjectCreationExpressionTokens.TryGetValue(compareToken, out token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } //Rules based on Object Creation location within code var compareTokenLocation = new ObjectCreationExpressionToken() { Key = objectCreationNode.Identifier, Namespace = parentNamespace, Type = parentClass }; ObjectCreationExpressionToken tokenLocation = null; _rootNodes.ObjectCreationExpressionTokens.TryGetValue(compareTokenLocation, out tokenLocation); if (tokenLocation != null) { AddActions(fileAction, tokenLocation, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } default: { if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } } } catch (Exception ex) { LogHelper.LogError(ex, "Error loading actions for item {0} of type {1}", child.Identifier, child.NodeType); } } return(containsActions); }