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);
}
}