using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.Loader; using Codelyzer.Analysis; using CTA.Rules.Config; using CTA.Rules.Models; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; namespace CTA.Rules.Actions { /// /// Loads actions into the current execution context /// public class ActionsLoader : ActionLoaderBase { private readonly List compilationUnitActions, attributeActions, attributeListActions, classActions, identifierNameActions, invocationExpressionActions, expressionActions, methodDeclarationActions, elementAccessActions, objectCreationExpressionActions, namespaceActions, interfaceActions; private readonly object attributeObject, attributeListObject, classObject, interfaceObject, compilationUnitObject, identifierNameObject, invocationExpressionObject, expressionObject, methodDeclarationObject, elementAccessObject, objectExpressionObject, namespaceObject; /// /// Initializes a new ActionLoader that loads the default actions /// /// A directory containing additional actions to be used public ActionsLoader(List assemblyPaths) { compilationUnitActions = new List(); attributeActions = new List(); attributeListActions = new List(); classActions = new List(); identifierNameActions = new List(); invocationExpressionActions = new List(); expressionActions = new List(); methodDeclarationActions = new List(); elementAccessActions = new List(); memberAccessActions = new List(); objectCreationExpressionActions = new List(); namespaceActions = new List(); projectLevelActions = new List(); interfaceActions = new List(); projectFileActions = new List(); projectTypeActions = new List(); var actionsAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.Contains("CTA.Rules.Actions")).FirstOrDefault(); var assemblies = new List { actionsAssembly }; foreach (var path in assemblyPaths) { try { var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); assemblies.Add(assembly); } catch (Exception ex) { LogHelper.LogError(ex, string.Format("Error loading assembly from {0}{1}{2}", path, Environment.NewLine, ex.Message)); } } foreach (var assembly in assemblies) { try { var types = assembly.GetTypes() .Where(t => t.Name.EndsWith("Actions") && (t.Namespace.EndsWith(ProjectLanguage.Csharp.ToString()) || t.Name.StartsWith("Project") || t.Name.StartsWith("MemberAccess"))).ToList(); attributeObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.AttributeActions)); attributeListObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.AttributeListActions)); classObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ClassActions)); compilationUnitObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.CompilationUnitActions)); identifierNameObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.IdentifierNameActions)); invocationExpressionObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.InvocationExpressionActions)); expressionObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ExpressionActions)); methodDeclarationObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.MethodDeclarationActions)); elementAccessObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ElementAccessActions)); memberAccessObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.MemberAccessActions)); namespaceObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.NamespaceActions)); objectExpressionObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ObjectCreationExpressionActions)); projectLevelObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ProjectLevelActions)); interfaceObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.InterfaceActions)); projectFileObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ProjectFileActions)); projectTypeObject = Activator.CreateInstance(types.FirstOrDefault(t => t.Name == Constants.ProjectTypeActions)); foreach (var t in types) { switch (t.Name) { case Constants.AttributeActions: { attributeActions.AddRange(GetFuncMethods(t)); break; } case Constants.AttributeListActions: { attributeListActions.AddRange(GetFuncMethods(t)); break; } case Constants.ClassActions: { classActions.AddRange(GetFuncMethods(t)); break; } case Constants.InterfaceActions: { interfaceActions.AddRange(GetFuncMethods(t)); break; } case Constants.CompilationUnitActions: { compilationUnitActions.AddRange(GetFuncMethods(t)); break; } case Constants.IdentifierNameActions: { identifierNameActions.AddRange(GetFuncMethods(t)); break; } case Constants.InvocationExpressionActions: { invocationExpressionActions.AddRange(GetFuncMethods(t)); break; } case Constants.ExpressionActions: { expressionActions.AddRange(GetFuncMethods(t)); break; } case Constants.MethodDeclarationActions: { methodDeclarationActions.AddRange(GetFuncMethods(t)); break; } case Constants.ElementAccessActions: { elementAccessActions.AddRange(GetFuncMethods(t)); break; } case Constants.MemberAccessActions: { memberAccessActions.AddRange(GetFuncMethods(t)); break; } case Constants.ObjectCreationExpressionActions: { objectCreationExpressionActions.AddRange(GetFuncMethods(t)); break; } case Constants.NamespaceActions: { namespaceActions.AddRange(GetFuncMethods(t)); break; } case Constants.ProjectLevelActions: { projectLevelActions.AddRange(GetFuncMethods(t)); break; } case Constants.ProjectFileActions: { projectFileActions.AddRange(GetFuncMethods(t)); break; } case Constants.ProjectTypeActions: { projectTypeActions.AddRange(GetFuncMethods(t)); break; } default: { LogHelper.LogError(string.Format("Action type {0} is not found", t.Name)); break; } } } } catch (Exception ex) { LogHelper.LogError(ex, string.Format("Error loading actions from {0}", assembly.FullName, ex.Message)); } } } public Func GetCompilationUnitAction(string name, dynamic value) => GetAction> (compilationUnitActions, compilationUnitObject, name, value); public Func GetAttributeAction(string name, dynamic value) => GetAction> (attributeActions, attributeObject, name, value); public Func GetAttributeListAction(string name, dynamic value) => GetAction> (attributeListActions, attributeListObject, name, value); public Func GetClassAction(string name, dynamic value) => GetAction> (classActions, classObject, name, value); public Func GetInterfaceAction(string name, dynamic value) => GetAction> (interfaceActions, interfaceObject, name, value); public Func GetIdentifierNameAction(string name, dynamic value) => GetAction> (identifierNameActions, identifierNameObject, name, value); public Func GetInvocationExpressionAction(string name, dynamic value) => GetAction> (invocationExpressionActions, invocationExpressionObject, name, value); public Func GetExpressionAction(string name, dynamic value) => GetAction> (expressionActions, expressionObject, name, value); public Func GetMethodDeclarationAction(string name, dynamic value) => GetAction> (methodDeclarationActions, methodDeclarationObject, name, value); public Func GetNamespaceActions(string name, dynamic value) => GetAction> (namespaceActions, namespaceObject, name, value); public Func GetObjectCreationExpressionActions(string name, dynamic value) => GetAction> (objectCreationExpressionActions, objectExpressionObject, name, value); public Func GetElementAccessExpressionActions(string name, dynamic value) => GetAction> (elementAccessActions, elementAccessObject, name, value); } }