/// <summary> /// 指定された関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name="element"></param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecution( UnifiedElement root, Regex regex, Type element, UnifiedBlock advice) { //関数の一覧を取得 var functions = root.Descendants <UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) { continue; } //関数内部に指定された要素があるかどうかを判定 var specifiedElements = ModelSweeper.Descendants(function.Body).Where(e => e.GetType().Equals(element)); if (specifiedElements.Count() == 0) { continue; } //関数名が与えられた正規表現にマッチする場合はアドバイスを合成する var m = regex.Match(function.Name.Name); if (m.Success) { //アドバイス内の特定の変数を、現在の対象関数名で置き換える var copy = ReplaceSpecialToken(advice.DeepCopy(), function.Name.Name); function.Body.Insert(0, copy); } } }
/// <summary> /// 指定された関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecution( UnifiedElement root, Regex regex, UnifiedBlock advice) { //get function list var functions = root.Descendants <UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) { continue; } //weave given advice, when function's name matches given Regex var m = regex.Match(function.Name.Name); if (m.Success) { //アドバイス内の特定の変数を、現在の対象関数名で置き換える var copy = ReplaceSpecialToken(advice.DeepCopy(), function.Name.Name); //アドバイスを対象関数に合成する function.Body.Insert(0, copy); } } }
private static UnifiedCase CreateCaseOrDefault(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "labeled_statement"); Contract.Requires(node.FirstElement().Name != "IDENTIFIER"); /* * labeled_statement * : IDENTIFIER ':' statement | 'case' constant_expression ':' statement | 'default' ':' statement */ switch (node.FirstElement().Value) { case "case": return (UnifiedCase.Create( CreateConstantExpression(node.NthElement(1)), UnifiedBlock.Create( CreateStatement(node.NthElement(3))))); case "default": return (UnifiedCase.CreateDefault( UnifiedBlock.Create( CreateStatement(node.NthElement(2))))); default: throw new InvalidOperationException(); } }
/// <summary> /// 指定された関数呼び出しの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterCall( UnifiedElement root, Regex regex, UnifiedBlock advice) { //get cass list var calls = root.Descendants<UnifiedCall>().ToList(); //親要素がUnifiedBlockの場合に、その関数呼び出しは単項式であると判断する。 foreach (var call in calls) { //プロパティでない関数呼び出しのみを扱う //e.g. write()はOK. Math.max()はNG. var functionName = call.Function as UnifiedIdentifier; if (functionName == null) continue; var m = regex.Match(functionName.Name); if (!m.Success) continue; //(Javaにおいて)関数呼び出しの親ノードがブロックの場合、それは単独である //(JavaScriptにおいて)関数呼び出しの親ノードがブロックの場合、それは単独である var block = call.Parent as UnifiedBlock; if (block != null) block.Insert(block.IndexOf(call, 0) + 1, advice.DeepCopy()); } }
/// <summary> /// 指定された関数呼び出しの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterCall( UnifiedElement root, Regex regex, UnifiedBlock advice) { //get cass list var calls = root.Descendants <UnifiedCall>().ToList(); //親要素がUnifiedBlockの場合に、その関数呼び出しは単項式であると判断する。 foreach (var call in calls) { //プロパティでない関数呼び出しのみを扱う //e.g. write()はOK. Math.max()はNG. var functionName = call.Function as UnifiedIdentifier; if (functionName == null) { continue; } var m = regex.Match(functionName.Name); if (!m.Success) { continue; } //(Javaにおいて)関数呼び出しの親ノードがブロックの場合、それは単独である //(JavaScriptにおいて)関数呼び出しの親ノードがブロックの場合、それは単独である var block = call.Parent as UnifiedBlock; if (block != null) { block.Insert(block.IndexOf(call, 0) + 1, advice.DeepCopy()); } } }
public static IEnumerable<UnifiedElement> FindDefines( UnifiedBlock codeObj) { /* * Binary Expressionを探索 * "="だけ * 左辺の変数名を調べる * 左辺のやつを表示するものを作る * */ var binaryExpressions = codeObj.Descendants<UnifiedBinaryExpression>(); foreach (var be in binaryExpressions) { if (be.Operator.Kind == UnifiedBinaryOperatorKind.Assign) { var leftName = ""; var left = be.LeftHandSide as UnifiedVariableIdentifier; if (left != null) { Console.WriteLine("left is \n{0}", left); leftName = left.Name; } var right = be.RightHandSide as UnifiedNullLiteral; if (right != null) { Console.WriteLine("{0} is NULL", leftName); } yield return left; } } }
public static UnifiedBlock CreateCompoundStatement(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "compound_statement"); /* compound_statement * : '{' declaration* statement_list? '}' */ var block = UnifiedBlock.Create(); foreach (var declaration in node.Elements("declaration")) { block.Add(CreateDeclaration(declaration)); } var statementList = node.Element("statement_list"); if (statementList != null) { foreach (var statement in CreateStatementList(statementList)) { var stmt = statement; block.Add(stmt); } } return(block); }
//new public static IEnumerable<string> FindNullDefines(UnifiedBlock codeObj) { var binaryExpressions = codeObj.Descendants<UnifiedBinaryExpression>(); var definition = codeObj.Descendants<UnifiedVariableDefinition>(); var nameList = new LinkedList<string>(); foreach (var def in definition) { var nullDefinition = def.InitialValue as UnifiedNullLiteral; if (nullDefinition != null) { Console.WriteLine("{0} defines null", def.Name.Name); nameList.AddFirst(def.Name.Name); } } foreach (var be in binaryExpressions) { if (be.Operator.Kind == UnifiedBinaryOperatorKind.Assign) { var right = be.RightHandSide as UnifiedNullLiteral; var nullId = be.LeftHandSide as UnifiedVariableIdentifier; if (right != null && nullId != null) { Console.WriteLine("{0} will be null", nullId.Name); nameList.AddFirst(nullId.Name); } } } return nameList; }
public void compares_different_blocks() { var o1 = UnifiedBlock.Create( new UnifiedExpression[] { UnifiedBinaryExpression.Create( UnifiedVariableIdentifier.Create("n"), UnifiedBinaryOperator.Create( "=", UnifiedBinaryOperatorKind.Assign), UnifiedInt32Literal.Create(1)), UnifiedReturn.Create( UnifiedInt32Literal.Create(2)), }); var o2 = UnifiedBlock.Create( new UnifiedExpression[] { UnifiedBinaryExpression.Create( UnifiedVariableIdentifier.Create("n"), UnifiedBinaryOperator.Create( "=", UnifiedBinaryOperatorKind.Assign), UnifiedInt32Literal.Create(2)), UnifiedReturn.Create( UnifiedInt32Literal.Create(2)), }); Assert.That( StructuralEqualityComparer.StructuralEquals(o1, o2), Is.False); }
// ブロック(UnifiedBlock) public override bool Visit(UnifiedBlock element, VisitorArgument arg) { // 要素の左端に記述すべきものがある場合はそれを出力する // プログラム全体の場合は何も出力しないが、関数の場合には中括弧が必要になるなど if (!string.IsNullOrEmpty(arg.Decoration.MostLeft)) { Writer.WriteLine(arg.Decoration.MostLeft); arg = arg.IncrementDepth(); } // ブロック内の要素を列挙する // セミコロンが必要な要素の場合にはセミコロンを出力する foreach (var stmt in element) { WriteIndent(arg); if (stmt.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write(arg.Decoration.EachRight); } // 要素の右端に記述すべきものがある場合はインデントを元に戻しそれを出力する if (!string.IsNullOrEmpty(arg.Decoration.MostRight)) { arg = arg.DecrementDepth(); WriteIndent(arg); Writer.Write(arg.Decoration.MostRight); } return false; }
/// <summary> /// 指定された変数参照の直後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name="root">コードを追加するモデルのルートノード</param> /// <param name="regex">対象変数を指定する正規表現</param> /// <param name="advice">挿入するコード断片</param> public static void InsertAtAfterGet(UnifiedElement root, Regex regex, UnifiedBlock advice) { //a = b;のb //TODO とりえあずAssignのみ +=,-=などについてはおいおい var assignmentExpressions = root.Descendants <UnifiedBinaryExpression>().Where(e => e.Operator.Kind == UnifiedBinaryOperatorKind.Assign).ToList(); foreach (var exp in assignmentExpressions) { var parent = exp.Parent as UnifiedBlock; var rhs = exp.RightHandSide as UnifiedVariableIdentifier; //親がブロック かつ 右辺がUnifiedVariableIdentifier でない場合は次の要素へ if (parent == null || rhs == null) { continue; } //変数名が与えられた正規表現にマッチするか確認する var m = regex.Match(rhs.Name); if (!m.Success) { continue; } //アドバイスの合成 parent.Insert(parent.IndexOf(exp, 0) + 1, advice.DeepCopy()); } //int a = b;のb var variableDefinitions = root.Descendants <UnifiedVariableDefinition>().ToList(); foreach (var definition in variableDefinitions) { //初期化子を変数として取得 var identifier = definition.InitialValue as UnifiedVariableIdentifier; var block = definition.Parent.Parent as UnifiedBlock; //初期化子が変数でない場合は次の要素へ if (block == null || identifier == null) { continue; } //変数名が与えられた正規表現にマッチするか確認する var m = regex.Match(identifier.Name); if (!m.Success) { continue; } //アドバイスの合成 var parent = definition.Parent as UnifiedVariableDefinitionList; block.Insert(block.IndexOf(parent, 0) + 1, advice.DeepCopy()); } }
public override bool Visit(UnifiedBlock element, VisitorArgument arg) { foreach (var stmt in element) { WriteIndent(arg.IndentDepth); stmt.TryAccept(this, arg); Writer.WriteLine(); } return(false); }
/// <summary> /// 指定された関数ブロックの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name="statementNum">対象関数に含まれるstatement数の下限を指定する閾値</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterExecution( UnifiedElement root, Regex regex, int statementNum, UnifiedBlock advice) { //get function list var functions = root.Descendants <UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) { continue; } //関数内部のStatementの一覧を取得し、閾値より多いかどうかを判定 var innerStatements = ModelSweeper.Descendants(function.Body).Where(e => e.Parent.GetType().Equals(typeof(UnifiedBlock))); if (innerStatements.Count() < statementNum) { continue; } //when function's name doesn't match given Regex, ignore current functionDefinition var m = regex.Match(function.Name.Name); if (!m.Success) { continue; } /*ToList()を呼び出しておかないと例外を吐く * 【例外】 * C# エラーメッセージ:コレクションが変更されました。 * 列挙操作は実行されない可能性があります。 */ var returns = function.Descendants <UnifiedReturn>().ToList(); if (returns.Count() == 0) { //case function don't have return statement function.Body.Add(advice.DeepCopy()); } else { foreach (var returnStmt in returns) { var block = returnStmt.Parent as UnifiedBlock; if (block == null) { continue; } block.Insert(block.IndexOf(returnStmt, 0), advice.DeepCopy()); } } } }
public UnifiedProgram Generate(string code) { if (string.IsNullOrWhiteSpace(code)) { return(UnifiedProgram.Create(UnifiedBlock.Create())); } var model = GenerateWithoutNormalizing(code); model.Normalize(); return(model); }
public static UnifiedProgram CreateProgram(ProduireFile rdr) { var program = UnifiedProgram.Create(UnifiedBlock.Create()); ParseClass(rdr.Global, program.Body); foreach (var construct in rdr.GetConstructs()) { program.Body.Add(CreateClassDefinition(construct)); } return(program); }
public static UnifiedExpression CreateIterationStatement(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "iteration_statement"); /* * iteration_statement * : 'while' '(' expression ')' statement | 'do' statement 'while' '(' expression ')' ';' | 'for' '(' expression_statement expression_statement expression? ')' statement */ var first = node.FirstElement().Value; var body = UnifiedBlock.Create( CreateStatement(node.FirstElement("statement"))); switch (first) { case "while": return (UnifiedWhile.Create( CreateExpression(node.NthElement(2)).First(), body)); case "do": return (UnifiedDoWhile.Create( CreateExpression(node.NthElement(4)).First(), body)); case "for": var step = node.Element("expression") != null? CreateExpression ( node . FirstElement ( "expression")) . First () : null; return(UnifiedFor.Create( CreateExpressionStatement(node.NthElement(2)), CreateExpressionStatement(node.NthElement(3)), step, body)); default: throw new InvalidOperationException(); } }
private static UnifiedBlock CreateSmartBlock(XElement node) { if (node == null || node.Name() == "nil") { return(UnifiedBlock.Create()); } if (node.Name() == "block") { return(CreateBlock(node)); } return(CreateExpresion(node).ToBlock()); }
public static UnifiedBlock CreateStructDeclarationList(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "struct_declaration_list"); /* struct_declaration_list * : struct_declaration+ */ return (UnifiedBlock.Create( node.Elements("struct_declaration").Select( CreateStructDeclaration))); }
//TODO a = b = cの扱いはどうするか考える public static void InsertAtBeforeSet(UnifiedElement root, Regex regex, UnifiedBlock advice) { //a = b;のa //TODO とりえあずAssignのみ +=,-=などについてはおいおい var assignmentExpressions = root.Descendants<UnifiedBinaryExpression>().Where(e => e.Operator.Kind == UnifiedBinaryOperatorKind.Assign).ToList(); foreach (var exp in assignmentExpressions) { var parent = exp.Parent as UnifiedBlock; var lhs = exp.LeftHandSide as UnifiedVariableIdentifier; //親がブロック かつ 左辺がUnifiedVariableIdentifier でない場合は次の要素へ if(parent == null || lhs == null) continue; //変数名が与えられた正規表現にマッチするか確認する var m = regex.Match(lhs.Name); if (!m.Success) continue; //アドバイスの合成 parent.Insert(parent.IndexOf(exp, 0), advice.DeepCopy()); } //int a = b;のa var variableDefinitions = root.Descendants<UnifiedVariableDefinition>().ToList(); foreach(var definition in variableDefinitions) { //初期化子がない場合は値はセットされないので次の要素へ if(definition.InitialValue == null) continue; //初期化子を変数として取得 var variable = definition.Name as UnifiedVariableIdentifier; var block = definition.Parent.Parent as UnifiedBlock; //初期化子が変数でない場合は次の要素へ if(block == null || variable == null) continue; //変数名が与えられた正規表現にマッチするか確認する var m = regex.Match(variable.Name); if (!m.Success) continue; //アドバイスの合成 var parent = definition.Parent as UnifiedVariableDefinitionList; block.Insert(block.IndexOf(parent, 0), advice.DeepCopy()); } }
public UnifiedElement VisitSyntaxTree(SyntaxTree syntaxTree, object data) { var prog = UnifiedProgram.Create(UnifiedBlock.Create()); foreach (var child in syntaxTree.Children) { var elem = child.TryAcceptForExpression(this); if (elem != null) { prog.Body.Add(elem); } } return(prog); }
//ブロック public override bool Visit(UnifiedBlock element, VisitorArgument arg) { //「いわゆるブロック」と「式のリストの入れ物としてのブロック」があるため、decorationでどちらかを判断する var decoration = arg.Decoration; //いわゆるブロックの場合 : e.g. while(true){ }の{ }の部分 if (decoration.MostLeft == "{") { Writer.WriteLine(decoration.MostLeft); arg = arg.IncrementDepth(); //ブロック内部ではインデントを1つ下げる //ブロック内部の式を出力 foreach (var stmt in element) { WriteIndent(arg.IndentDepth); if (stmt.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write(decoration.EachRight); } arg = arg.DecrementDepth(); //インデントを元に戻す WriteIndent(arg.IndentDepth); Writer.Write(decoration.MostRight); return(false); } //式のリストの入れ物としてのブロックの場合 : e.g. return 1,2,3;の1,2,3の部分 //式の数が0個の場合は何も出力せずに終了 if (element.Count == 0) { return(false); } //式が1つ以上ある場合 //TODO なぜ括弧を出力するのか確認 Writer.Write("("); var comma = ""; foreach (var e in element) { Writer.Write(comma); e.TryAccept(this, arg); comma = decoration.Delimiter; } Writer.Write(")"); return(false); }
// TODO 置換前は変数だが、置換後は文字列リテラルになるので、どのように置換するか考える /// <summary> /// 指定されたアドバイスに含まれる特殊文字を指定された関数名に置き換えます /// </summary> public static UnifiedBlock ReplaceSpecialToken(UnifiedBlock old, string functionName) { //指定されたアドバイスに含まれる変数をリストアップする var variables = old.Descendants <UnifiedVariableIdentifier>(); //特殊文字に指定されている変数を指定された関数名で置き換える foreach (var e in variables) { if (e.Name.Equals("JOINPOINT_NAME")) { e.Name = "\"" + functionName + "\""; } } return(old); }
public override void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { var exceptions = model.Descendants<UnifiedCatch>(); foreach (var e in exceptions) { var regex = new Regex("^" + target.GetTargetName().ElementAt(1) + "$"); var type = e.Types[0].BasicTypeName as UnifiedIdentifier; if(type == null) continue; var m = regex.Match(type.Name); if (m.Success) { //アドバイスを対象関数に合成する e.Body.Insert(0, advice.DeepCopy()); } } }
public UnifiedElement VisitAnonymousTypeCreateExpression( AnonymousTypeCreateExpression expr, object data) { var block = UnifiedBlock.Create(); foreach (var nExpr in expr.Initializers) { var uExpr = nExpr.TryAcceptForExpression(this); if (uExpr != null) { block.Add(uExpr); } } return(UnifiedNew.Create(body: block)); }
private static void ParseClass(Construct construct, UnifiedBlock block) { // コードの取得 // ステートメントの取得 foreach (var procedure in construct.GetProcedures()) { foreach (var statement in procedure.Statements) { block.AddRange(CreateStatement(statement)); } } // フィールドの取得 foreach (var field in construct.GetAllFields()) { block.Add(CreateField(field)); } }
public static UnifiedFunctionDefinition CreateFunctionDefinition( XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "function_definition"); /* function_definition * : declaration_specifiers? declarator * ( declaration+ compound_statement // K&R style * | compound_statement // ANSI style * ) */ UnifiedSet <UnifiedModifier> modifiers = null; UnifiedType type = null; UnifiedSet <UnifiedGenericParameter> genericParameters = null; UnifiedIdentifier name = null; UnifiedSet <UnifiedParameter> parameters = null; UnifiedBlock body = null; var first = node.FirstElement(); if (first.Name() == "declaration_specifiers") { var modifiersAndType = CreateDeclarationSpecifiers(first); modifiers = modifiersAndType.Item1; type = (UnifiedType)modifiersAndType.Item2; } var declarator = CreateDeclarator(node.Element("declarator")); name = declarator.Item1; parameters = declarator.Item2; if (node.Elements("declaration").Count() != 0) { // TODO declaration+ compound_statement に該当するケースが未検出 throw new NotImplementedException(); } body = CreateCompoundStatement(node.Element("compound_statement")); return(UnifiedFunctionDefinition.Create( null, modifiers, type, genericParameters, name, parameters, null, body)); }
public static UnifiedBlock CreateEnumeratorList(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "enumerator_list"); /* * enumerator_list * : enumerator (',' enumerator)* */ var enumerators = node.Elements("enumerator").Select(CreateEnumerator); return (UnifiedBlock.Create( UnifiedVariableDefinitionList.Create(enumerators))); }
public static UnifiedProgram CreateTranslationUnit(XElement node) { Contract.Requires(node != null); Contract.Requires(node.Name() == "translation_unit"); /* * translation_unit: external_declaration+ ; */ var program = UnifiedProgram.Create(UnifiedBlock.Create()); var expressions = program.Body; foreach (var e in node.Elements("external_declaration")) { expressions.Add(CreateExternalDeclaration(e)); } return(program); }
//ブロック public override bool Visit(UnifiedBlock element, VisitorArgument arg) { //「いわゆるブロック」と「式のリストの入れ物としてのブロック」があるため、decorationでどちらかを判断する var decoration = arg.Decoration; //いわゆるブロックの場合 : e.g. while(true){ }の{ }の部分 if (decoration.MostLeft == "{") { Writer.WriteLine(decoration.MostLeft); arg = arg.IncrementDepth(); //ブロック内部ではインデントを1つ下げる //ブロック内部の式を出力 foreach (var stmt in element) { WriteIndent(arg.IndentDepth); if (stmt.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write(decoration.EachRight); } arg = arg.DecrementDepth(); //インデントを元に戻す WriteIndent(arg.IndentDepth); Writer.Write(decoration.MostRight); return false; } //式のリストの入れ物としてのブロックの場合 : e.g. return 1,2,3;の1,2,3の部分 //式の数が0個の場合は何も出力せずに終了 if (element.Count == 0) { return false; } //式が1つ以上ある場合 //TODO なぜ括弧を出力するのか確認 Writer.Write("("); var comma = ""; foreach (var e in element) { Writer.Write(comma); e.TryAccept(this, arg); comma = decoration.Delimiter; } Writer.Write(")"); return false; }
/// <summary> /// 指定された関数ブロックの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name="statementNum">対象関数に含まれるstatement数の下限を指定する閾値</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterExecution( UnifiedElement root, Regex regex, int statementNum, UnifiedBlock advice) { //get function list var functions = root.Descendants<UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) continue; //関数内部のStatementの一覧を取得し、閾値より多いかどうかを判定 var innerStatements = ModelSweeper.Descendants(function.Body).Where(e => e.Parent.GetType().Equals(typeof(UnifiedBlock))); if(innerStatements.Count() < statementNum) continue; //when function's name doesn't match given Regex, ignore current functionDefinition var m = regex.Match(function.Name.Name); if (!m.Success) continue; /*ToList()を呼び出しておかないと例外を吐く * 【例外】 * C# エラーメッセージ:コレクションが変更されました。 * 列挙操作は実行されない可能性があります。 */ var returns = function.Descendants<UnifiedReturn>().ToList(); if (returns.Count() == 0) { //case function don't have return statement function.Body.Add(advice.DeepCopy()); } else { foreach (var returnStmt in returns) { var block = returnStmt.Parent as UnifiedBlock; if (block == null) continue; block.Insert(block.IndexOf(returnStmt, 0), advice.DeepCopy()); } } } }
public override bool Visit(UnifiedBlock element, VisitorArgument arg) { if (!string.IsNullOrEmpty(arg.Decoration.MostLeft)) { Writer.WriteLine(arg.Decoration.MostLeft); arg = arg.IncrementDepth(); } foreach (var stmt in element) { WriteIndent(arg); if (stmt.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write(arg.Decoration.EachRight); } if (!string.IsNullOrEmpty(arg.Decoration.MostRight)) { arg = arg.DecrementDepth(); WriteIndent(arg); Writer.WriteLine(arg.Decoration.MostRight); } return(false); }
public override void After(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { InsertAtAfterCallByName(model, target.GetTargetName().ElementAt(1), advice); }
public override bool Visit(UnifiedBlock element, VisitorArgument arg) { foreach (var stmt in element) { WriteIndent(arg.IndentDepth); stmt.TryAccept(this, arg); Writer.WriteLine(); } return false; }
public static void InsertAtAfterGetByName(UnifiedElement root, string name, UnifiedBlock advice) { InsertAtAfterGet(root, new Regex(name), advice); }
/// <summary> /// 指定された関数呼び出しの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルードノード</param> /// <param name = "name">対象関数の名前</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterCallByName( UnifiedElement root, string name, UnifiedBlock advice) { InsertAtAfterCall(root, new Regex("^" + name + "$"), advice); }
public override void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { InsertAtBeforeGetByName(model, target.GetTargetName().ElementAt(1), advice); }
public override void After(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { throw new NotImplementedException(); }
public override void After(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { InsertAtAfterGetByName(model, target.GetTargetName().ElementAt(1), advice); }
// TODO Pointcutの名前が競合しないようにする public abstract void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice);
// TODO 置換前は変数だが、置換後は文字列リテラルになるので、どのように置換するか考える /// <summary> /// 指定されたアドバイスに含まれる特殊文字を指定された関数名に置き換えます /// </summary> public static UnifiedBlock ReplaceSpecialToken(UnifiedBlock old, string functionName) { //指定されたアドバイスに含まれる変数をリストアップする var variables = old.Descendants<UnifiedVariableIdentifier>(); //特殊文字に指定されている変数を指定された関数名で置き換える foreach (var e in variables) { if(e.Name.Equals("JOINPOINT_NAME")) e.Name = "\"" + functionName + "\""; } return old; }
// 指定されたポイントカット(名)に対応するafterの織り込み処理を与えられたmodelに適用します public static void WeavingAfter(string name, UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { var aspect = GetProcessorFromName(name); aspect.After(model, target, advice); }
/// <summary> /// Add メソッド(コレクションに対して,要素を追加するメソッド)を生成します /// </summary> /// <param name="collectionField"> 対象のコレクション </param> /// <param name="functionName"> Add メソッドの名前(e.g. addItem) </param> /// <param name="addingProcedure"> Add メソッドの中身 </param> /// <returns> Add メソッド </returns> public static UnifiedFunctionDefinition GenerateAddMethod( UnifiedElement collectionField, string functionName, UnifiedBlock addingProcedure) { var func = UnifiedFunctionDefinition.Create(); func.Name = UnifiedIdentifier.CreateLabel(functionName); func.Modifiers = UnifiedModifierCollection.Create( UnifiedModifier.Create("public")); // 引数 var parameter = UnifiedParameter.Create(); parameter.Type = FindUtil.GetTypeParameterAsType( (UnifiedGenericType) ((UnifiedVariableDefinition)collectionField).Type); parameter.Names = UnifiedIdentifierCollection.Create( UnifiedIdentifier.CreateLabel("object")); func.Parameters = UnifiedParameterCollection.Create(parameter); func.Type = UnifiedType.Create("void"); func.Body = addingProcedure; return func; }
// 統合コードオブジェクトに対してアスペクトの合成処理を行います public static void Weave(string language, UnifiedProgram model) { //以前のアスペクトファイルの情報を消去するために辞書の内容を初期化する Pointcuts.Clear(); //与えられたモデルに対してインタータイプを合成する foreach (var intertype in _visitor.Intertypes) { if (intertype.GetLanguageType() != language) { continue; } var members = UcoGenerator.CreateIntertype( intertype.GetLanguageType(), intertype.GetContents()); InterType.AddIntertypeDeclaration(model, intertype.GetTarget(), members); } //ポイントカットを登録する foreach (var pointcut in _visitor.Pointcuts) { var name = pointcut.GetName(); //同じ名前のポイントカットがある場合にはエラーとする if (Pointcuts.ContainsKey(name)) { throw new InvalidOperationException( "同名のポイントカットがすでに宣言されています: " + name); } //ポイントカットを自身の名前で登録 Pointcuts.Add(name, pointcut); } //アドバイスの適用 foreach (var advice in _visitor.Advices) { //アドバイスのターゲットがポイントカット宣言されていない場合はエラーとする if (!Pointcuts.ContainsKey(advice.GetTarget())) { throw new InvalidOperationException( "指定されたポイントカットは宣言されていません"); } //アドバイスのターゲットが登録されていれば、それに対応するポイントカットを取得する Pointcut target; Pointcuts.TryGetValue(advice.GetTarget(), out target); //指定された言語のアドバイスがあればそれをモデルに変換する UnifiedBlock code = null; foreach (var languageDependBlock in advice.GetFragments()) { // if (languageDependBlock.GetLanguageType().Equals(language)) { code = UcoGenerator.CreateAdvice( language, languageDependBlock.GetContents()); break; } } //現在の対象ファイルの言語向けアドバイスが定義されていない場合は次のアドバイス処理に移る if (code == null) { continue; } //ポイントカットの指定に応じて適切なアドバイスの合成処理を行う //TODO ワイルドカードなどへの対応 //TODO 複数のターゲットを持つポイントカットへの対応(これはそもそもパーサを改良する必要あり) var methodName = target.GetTargetName().ElementAt(1); // アドバイスの合成 // リフレクション(MEF)を用いて、対応するメソッドが呼び出されます switch (advice.GetAdviceType()) { case "before": CodeProcessorProvider.WeavingBefore(target.GetPointcutType(), model, target.DeepCopy(), code); break; case "after": CodeProcessorProvider.WeavingAfter(target.GetPointcutType(), model, target.DeepCopy(), code); break; default: throw new InvalidOperationException(); } } }
public override void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { InsertAtBeforeCallByName(model, target.GetTargetName().ElementAt(1), advice); }
/// <summary> /// すべての関数呼び出しの直前に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeCallAll( UnifiedElement root, UnifiedBlock advice) { InsertAtBeforeCall(root, new Regex(".*"), advice); }
public static IEnumerable<UnifiedElement> FindUses( UnifiedBlock codeObj) { var binaryExpressions = codeObj.Descendants<UnifiedBinaryExpression>(); foreach (var be in binaryExpressions) { if (be.Operator.Kind == UnifiedBinaryOperatorKind.Assign) { var right = be.RightHandSide as UnifiedVariableIdentifier; if (right != null) { var rightName = right.Name; Console.WriteLine("{0} is used", rightName); yield return right; } } } }
/// <summary> /// すべての関数呼び出しの後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルードノード</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterCallAll( UnifiedElement root, UnifiedBlock advice) { InsertAtAfterCall(root, new Regex(".*"), advice); }
/// <summary> /// 名前で指定された関数の後に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "name">対象関数の名前</param> /// <param name="statementNum">対象関数に含まれるstatement数の下限を指定する閾値</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtAfterExecutionByName( UnifiedElement root, string name, int statementNum, UnifiedBlock advice) { InsertAtAfterExecution(root, new Regex("^" + name + "$"), statementNum, advice); }
public UnifiedElement VisitEmptyStatement( EmptyStatement stmt, object data) { return(UnifiedBlock.Create()); }
/// <summary> /// 指定された関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecution( UnifiedElement root, Regex regex, UnifiedBlock advice) { //get function list var functions = root.Descendants<UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) continue; //weave given advice, when function's name matches given Regex var m = regex.Match(function.Name.Name); if (m.Success) { //アドバイス内の特定の変数を、現在の対象関数名で置き換える var copy = ReplaceSpecialToken(advice.DeepCopy(), function.Name.Name); //アドバイスを対象関数に合成する function.Body.Insert(0, copy); } } }
//new public static void FindUsesDefine(UnifiedBlock codeObj) { var defineNames = FindUses(codeObj); foreach (var defName in defineNames) { var name = defName; var elements = codeObj.Descendants<UnifiedBinaryExpression>().Where( e => name != e); var variableName = (UnifiedVariableIdentifier)defName; foreach (var element in elements) { var left = element.LeftHandSide as UnifiedVariableIdentifier; var right = element.RightHandSide as UnifiedNullLiteral; if (left != null && left.Name.Equals(variableName.Name)) { Console.WriteLine( "{0} is {1}", left.Name, element.RightHandSide); } } } }
/// <summary> /// 指定された関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "regex">対象関数を指定する正規表現</param> /// <param name="element"></param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecution( UnifiedElement root, Regex regex, Type element, UnifiedBlock advice) { //関数の一覧を取得 var functions = root.Descendants<UnifiedFunctionDefinition>(); foreach (var function in functions) { //関数の定義元がインターフェースまたは抽象クラスの場合はアドバイスを合成しない if (function.Body == null) continue; //関数内部に指定された要素があるかどうかを判定 var specifiedElements = ModelSweeper.Descendants(function.Body).Where(e => e.GetType().Equals(element)); if(specifiedElements.Count() == 0) continue; //関数名が与えられた正規表現にマッチする場合はアドバイスを合成する var m = regex.Match(function.Name.Name); if (m.Success) { //アドバイス内の特定の変数を、現在の対象関数名で置き換える var copy = ReplaceSpecialToken(advice.DeepCopy(), function.Name.Name); function.Body.Insert(0, copy); } } }
//TODO afterも実装する //TODO 共通部分が多いので、うまくまとめて実装する方法を考える /// <summary> /// すべての関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecutionAll( UnifiedElement root, UnifiedBlock advice) { InsertAtBeforeExecution(root, new Regex(".*"), advice); }
/// <summary> /// 名前で指定された関数ブロックの先頭に、指定されたコードを共通コードモデルとして挿入します。 /// </summary> /// <param name = "root">コードを追加するモデルのルートノード</param> /// <param name = "name">対象関数の名前</param> /// <param name="element"></param> /// <param name = "advice">挿入するコード断片</param> public static void InsertAtBeforeExecutionByName( UnifiedElement root, string name, Type element, UnifiedBlock advice) { InsertAtBeforeExecution(root, new Regex("^" + name + "$"), element, advice); }
public override bool Visit(UnifiedBlock element, VisitorArgument arg) { // Write '{' which can be abbreviated if (!string.IsNullOrEmpty(arg.Decoration.MostLeft)) { Writer.WriteLine(arg.Decoration.MostLeft); arg = arg.IncrementDepth(); } foreach (var stmt in element) { WriteIndent(arg); if (stmt.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write(arg.Decoration.EachRight); } // Write '}' which can be abbreviated if (!string.IsNullOrEmpty(arg.Decoration.MostRight)) { arg = arg.DecrementDepth(); WriteIndent(arg); Writer.WriteLine(arg.Decoration.MostRight); } return false; }
/// <summary> /// Remove メソッド(コレクションに対して,要素を削除するメソッド)を生成します /// </summary> /// <param name="collectionField"> 対象にするコレクション </param> /// <param name="functionName"> Remove メソッドの名前(e.g. removeItem) </param> /// <param name="removingProcedure"> Remove メソッドの中身 </param> /// <returns> Remove メソッド </returns> public static UnifiedFunctionDefinition GenerateRemoveMethod( UnifiedElement collectionField, string functionName, UnifiedBlock removingProcedure) { // 関数本体 var func = UnifiedFunctionDefinition.Create(); func.Name = UnifiedIdentifier.CreateLabel(functionName); func.Modifiers = UnifiedModifierCollection.Create( UnifiedModifier.Create("public")); // 引数(操作対象のインデクス) var parameter = UnifiedParameter.Create(); parameter.Type = UnifiedType.Create("int"); parameter.Names = UnifiedIdentifierCollection.Create( UnifiedIdentifier.CreateLabel("i")); func.Parameters = UnifiedParameterCollection.Create(parameter); func.Type = UnifiedType.Create("void"); func.Body = removingProcedure; return func; }