private KeyValuePair <string, UstList <UstNode> > SourceFileToCodeTokens(RootUstNode sourceFile) { var allNodes = new UstList <UstNode>(); allNodes.AddRange(sourceFile.AllInvocationExpressions()); allNodes.AddRange(sourceFile.AllAnnotations()); allNodes.AddRange(sourceFile.AllDeclarationNodes()); allNodes.AddRange(sourceFile.AllStructDeclarations()); allNodes.AddRange(sourceFile.AllEnumDeclarations()); return(KeyValuePair.Create(sourceFile.FileFullPath, allNodes)); }
private static UstList <T> GetNodes <T>(UstNode node) where T : UstNode { UstList <T> nodes = new UstList <T>(); foreach (UstNode child in node.Children) { if (child != null) { if (child is T) { nodes.Add((T)child); } nodes.AddRange(GetNodes <T>(child)); } } return(nodes); }
/// <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 }; _rootNodes.Attributetokens.TryGetValue(compareToken, out var token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } break; } case IdConstants.UsingDirectiveIdName: { var compareToken = new UsingDirectiveToken() { Key = child.Identifier }; _rootNodes.Usingdirectivetokens.TryGetValue(compareToken, out var token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } break; } case IdConstants.NamespaceIdName: { var compareToken = new NamespaceToken() { Key = child.Identifier }; _rootNodes.NamespaceTokens.TryGetValue(compareToken, out var 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 }; _rootNodes.Classdeclarationtokens.TryGetValue(baseToken, out var 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) }; _rootNodes.MethodDeclarationTokens.TryGetValue(compareToken, out var 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: { string overrideKey = string.Empty; InvocationExpression invocationExpression = (InvocationExpression)child; ////If we don't have a semantic analysis, we dont want to replace invocation expressions, otherwise we'll be replacing expressions regardless of their class/namespace if (string.IsNullOrEmpty(invocationExpression.SemanticOriginalDefinition)) { break; } var compareToken = new InvocationExpressionToken() { Key = invocationExpression.SemanticOriginalDefinition, Namespace = invocationExpression.Reference.Namespace, Type = invocationExpression.SemanticClassType }; _rootNodes.Invocationexpressiontokens.TryGetValue(compareToken, out var token); //Attempt a wildcard search, if applicable. This is invocation expression specific because it has to look inside the invocation expressions only if (token == null) { var wildcardMatches = _rootNodes.Invocationexpressiontokens.Where(i => i.Key.Contains("*")); if (wildcardMatches.Any()) { token = wildcardMatches.FirstOrDefault(i => compareToken.Key.WildcardEquals(i.Key) && compareToken.Namespace == i.Namespace && compareToken.Type == i.Type); if (token != null) { //We set the key so that we don't do another wildcard search during replacement, we just use the name as it was declared in the code overrideKey = compareToken.Key; } } //If the semanticClassType is too specific to apply to all TData types if (token == null) { if (invocationExpression.SemanticClassType.Contains('<')) { string semanticClassType = invocationExpression.SemanticClassType.Substring(0, invocationExpression.SemanticClassType.IndexOf('<')); compareToken = new InvocationExpressionToken() { Key = invocationExpression.SemanticOriginalDefinition, Namespace = invocationExpression.Reference.Namespace, Type = semanticClassType }; _rootNodes.Invocationexpressiontokens.TryGetValue(compareToken, out token); } } } if (token != null) { AddActions(fileAction, token, child.TextSpan, overrideKey); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } case IdConstants.ElementAccessIdName: { ElementAccess elementAccess = (ElementAccess)child; var compareToken = new ElementAccessToken() { Key = elementAccess.Expression, FullKey = GetFullKey(elementAccess.Reference?.Namespace, elementAccess.SemanticClassType, elementAccess.Expression), Type = elementAccess.SemanticClassType, Namespace = elementAccess.Reference?.Namespace }; _rootNodes.ElementAccesstokens.TryGetValue(compareToken, out var token); if (token != null) { AddActions(fileAction, token, child.TextSpan); containsActions = true; } if (AnalyzeChildren(fileAction, child.Children, ++level, parentNamespace, parentClass)) { containsActions = true; } break; } case IdConstants.MemberAccessIdName: { MemberAccess memberAccess = (MemberAccess)child; var compareToken = new MemberAccessToken() { Key = memberAccess.Name, FullKey = GetFullKey(memberAccess.Reference?.Namespace, memberAccess.SemanticClassType, memberAccess.Name), Type = memberAccess.SemanticClassType, Namespace = memberAccess.Reference?.Namespace }; _rootNodes.MemberAccesstokens.TryGetValue(compareToken, out var 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 }; _rootNodes.Identifiernametokens.TryGetValue(compareToken, out var 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 }; _rootNodes.ObjectCreationExpressionTokens.TryGetValue(compareToken, out var 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 }; _rootNodes.ObjectCreationExpressionTokens.TryGetValue(compareTokenLocation, out var tokenLocation); if (tokenLocation != null) { AddActions(fileAction, tokenLocation, child.TextSpan); containsActions = true; } token = null; if (!string.IsNullOrEmpty(objectCreationNode.SemanticOriginalDefinition)) { var nameToken = new ObjectCreationExpressionToken() { Key = objectCreationNode.SemanticOriginalDefinition, Namespace = objectCreationNode.SemanticNamespace, Type = objectCreationNode.SemanticClassType }; _rootNodes.ObjectCreationExpressionTokens.TryGetValue(nameToken, out token); if (token != null) { AddActions(fileAction, token, 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); }
/// <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); }