//
// NKalore Compiler related class
//
// Licensed under the terms of the GNU GPL
//
// Author:
// Guilherme Labigalini (glabega@gmail.com), 2005
//
// http://aspectsharpcomp.sourceforge.net/
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using Mono.CSharp;
namespace Mono.CSharp.AOP{
public abstract class Advice: Method
{
public const string ThisJoinPointVaribleName = "thisJoinPoint";
public const string JoinPointTypeName = "NKalore.Model.JoinPoint";
public const string InstancePropertyName = "Instance";
public const string ContainerTypePropertyName = "ContainerType";
public const string ParamsDataPropertyName = "ParamsData";
public string AdviceName;
#region CTOR
public Advice(DeclSpace ds, Expression return_type, string callName,
Parameters parameters, Attributes attrs, Location l):
base(ds, return_type, Modifiers.INTERNAL | Modifiers.STATIC, false, callName,
GetParams(parameters,l), attrs, l)
{
Init();
}
public Advice(DeclSpace ds, string callName,
Parameters parameters, Attributes attrs, Location l):
base(ds, TypeManager.system_void_expr,
Modifiers.INTERNAL | Modifiers.STATIC, false, callName,
GetParams(parameters,l), attrs, l)
{
Init();
}
#endregion
#region Private Members
private static Parameters GetParams(Parameters parameters, Location l)
{
if (parameters == CSharp.Parameters.EmptyReadOnlyParameters)
{
parameters = new Parameters(null, null, l);
}
return parameters;
}
private void Init()
{
AdviceName = this.Name;
this.Name = UniqueStringHelper.GetUniqueString(this.GetType().Name + this.Name);
InsertParam(
new Parameter(
new TypeLookupExpression (JoinPointTypeName),
ThisJoinPointVaribleName, Parameter.Modifier.NONE, null)
);
}
private bool CanHandle(Parameters targetParameters)
{
int baseIndex = GetDataParamCount();
bool fixedOk, arrayOk = false;
if (
(targetParameters == CSharp.Parameters.UnnecessaryParameters) ||
(this.Parameters == CSharp.Parameters.EmptyReadOnlyParameters) ||
(this.Parameters.Empty) ||
(this.Parameters.FixedParameters != null &&
this.Parameters.FixedParameters.Length == baseIndex)
)
{
fixedOk = true;
}
else
{
if (this.Parameters.FixedParameters != null &&
targetParameters.FixedParameters != null &&
this.Parameters.FixedParameters.Length == targetParameters.FixedParameters.Length + baseIndex)
{
fixedOk = true;
for (int i = baseIndex; i <this.Parameters.FixedParameters.Length; i++)
{
Parameter p1 = this.Parameters.FixedParameters[i];
int j = i;
if (baseIndex > 0) j -= baseIndex;
Parameter p2 = targetParameters.FixedParameters[j];
if (! ParameterMatch(p1, p2))
{
fixedOk = false;
break;
}
}
}
else
{
fixedOk = false;
}
}
if (fixedOk)
{
arrayOk =
(
(this.Parameters.FixedParameters != null &&
this.Parameters.FixedParameters.Length == baseIndex &&
this.Parameters.ArrayParameter == null)
)
||
(
(this.Parameters.ArrayParameter == null && targetParameters.ArrayParameter == null)
)
||
(
(this.Parameters.ArrayParameter != null && targetParameters.ArrayParameter != null)
&&
(ParameterMatch(this.Parameters.ArrayParameter, targetParameters.ArrayParameter))
);
}
return (fixedOk && arrayOk);
}
private IList GetMethodList(ClassOrStruct type, PointCut call)
{
IList list;
if (call.ReturnType == TypeManager.new_type)
{
list = (IList)type.InstanceConstructors.Clone();
}
else if (call.ReturnType == TypeManager.any_type &&
type.InstanceConstructors != null)
{
list = (IList)type.InstanceConstructors.Clone();
if (type.Methods != null)
{
for (int j = 0; j < type.Methods.Count; j++)
{
list.Add(type.Methods[j]);
}
}
}
else
{
list = (IList)type.Methods.Clone();
}
return list;
}
#endregion
#region Protected Members
protected void InsertParam(Parameter param)
{
bool hasMethodParams = (this.Parameters.FixedParameters != null &&
this.Parameters.FixedParameters.Length > 0);
int len = 1;
if (hasMethodParams)
{
len += this.Parameters.FixedParameters.Length;
}
Parameter[] parameters = new Parameter[len];
parameters[0] = param;
if (hasMethodParams)
{
this.Parameters.FixedParameters.CopyTo(parameters, 1);
}
this.Parameters.FixedParameters = parameters;
}
protected virtual int GetDataParamCount()
{
return 1; //the thisJoinPoint object
}
protected bool ParameterMatch(Parameter p1, Parameter p2)
{
//BUG problema se qnd os tipos estao em namespaces <> da certo! ou no msm namespace mas de maneira <>!
return (p1.TypeName.ToString() == p2.TypeName.ToString());
}
protected virtual ArrayList CreateInvocationParameters(MethodCore method)
{
CSharp.Parameter[] paramaters = this.Parameters.FixedParameters;
ArrayList arguments = new ArrayList(paramaters.Length);
int baseIndex = GetDataParamCount();
for (int i = baseIndex; i < paramaters.Length; i++)
{
Argument arg = StatementFactory.GetInstance().CreateArgument(method.Parameters.FixedParameters[i-baseIndex], paramaters[i]);
arguments.Add(arg);
}
if (this.Parameters.ArrayParameter != null)
{
Argument arg = StatementFactory.GetInstance().CreateArgument(method.Parameters.ArrayParameter, this.Parameters.ArrayParameter);
arguments.Add(arg);
}
ArrayList jointPointArgs = new ArrayList();
#region current method
SimpleName methodBase = new SimpleName("System.Reflection.MethodBase", method.Location);
MemberAccess getCurrentMethod = new MemberAccess(methodBase, "GetCurrentMethod", method.Location);
Invocation getCurrentMethodInvoc = new Invocation(getCurrentMethod, null, method.Location);
jointPointArgs.Add(new Argument(getCurrentMethodInvoc, Argument.AType.Expression));
#endregion
#region instance
Argument instanceArg = null;
if ((method.ModFlags & Modifiers.STATIC) == 0)
{
instanceArg = new Argument(new This(method.Block,this.Location), Argument.AType.Expression);
}
else
{
instanceArg = new Argument(new NullLiteral(), Argument.AType.Expression);
}
jointPointArgs.Add(instanceArg);
#endregion
#region parameters
ArrayList initializers = new ArrayList();
for (int i = 0;
method.Parameters.FixedParameters != null && i < method.Parameters.FixedParameters.Length; i++)
{
initializers.Add(new SimpleName(method.Parameters.FixedParameters[i].Name, method.Location));
}
if (method.Parameters.ArrayParameter != null)
{
initializers.Add(new SimpleName(method.Parameters.ArrayParameter.Name, method.Location));
}
ArrayCreation methodParam =
new ArrayCreation (TypeManager.system_object_expr, "[]", initializers, method.Location);
jointPointArgs.Add(new Argument(methodParam, Argument.AType.Expression));
#endregion
Expression jointPointExpr = new New(new SimpleName(JoinPointTypeName, method.Location), jointPointArgs, method.Location);
Argument jointPoint = new Argument(jointPointExpr, Argument.AType.Expression);
arguments.Insert(0, jointPoint);
return arguments;
}
protected StatementExpression CreateInvocationStatement(MethodCore method)
{
ArrayList arguments = CreateInvocationParameters(method);
return StatementFactory.GetInstance().CreateMethodInvocation(this, arguments);
}
#endregion
#region Public Members
public Aspect Aspect
{
get
{
return (Aspect)this.ds;
}
}
public abstract void InsertAspectCode(PointCut call, MethodCore method);
public virtual bool CanHandle(MethodCore method)
{
return (! (method is AOPMethodImpl)) && (method.Block != null) &&
CanHandle(method.Parameters);
}
public virtual bool CanHandle(PointCut pointCut)
{
return (CanHandle(pointCut.Parameters));
}
public void ApplyAspect(PointCut pointCut)
{
for (int i = 0; i < RootContext.Tree.Types.Types.Count; i++)
{
ClassOrStruct type = (RootContext.Tree.Types.Types[i] as ClassOrStruct);
if (type == null || type is Aspect)
continue;
IList list = GetMethodList(type, pointCut);
if (list == null)
{
continue;
}
foreach (MethodCore method in list)
{
if (pointCut.IsMatch(type, method) &&
this.CanHandle(method))
{
InsertAspectCode(pointCut, method);
}
}
}
}
#endregion
}
}
|