private static void WriteUnifiedElement( UnifiedElement elem, StringBuilder buffer, int depth) { WriteTypeWithoutContent(elem, buffer, depth); // write items of enumerable var seq = elem as IEnumerable; if (seq != null) { foreach (var item in seq) { ToStringRecursively(item, buffer, depth + 1); } Debug.Assert( elem.GetType().GetProperties() .Where( prop => prop.Name.StartsWith("Unified") || prop.Name.StartsWith("IUnified")) .Where( prop => !IgnorePropertyNames.Contains(prop.Name)) .Where( prop => prop.GetIndexParameters().Length == 0) .Select(prop => prop.GetValue(elem, null)).Count () == 0); return; } // write properties without indexer var values = elem.GetType().GetProperties() .Where(prop => !IgnorePropertyNames.Contains(prop.Name)) .Where(prop => prop.GetIndexParameters().Length == 0) .Select(prop => prop.GetValue(elem, null)); foreach (var value in values) { ToStringRecursively(value, buffer, depth + 1); } }
/// <summary> /// 指定されたトップノード以下で,指定されたジェネリクスを持つフィールドを検索し,取得します /// </summary> /// <param name="element"> 検索するトップノード </param> /// <param name="containerType"> コンテナの型名(e.g. List[T] の List) </param> /// <param name="type"> 型引数の型名(e.g. List[T] の T,'*'はワイルドカード) </param> /// <returns> </returns> public static IEnumerable<UnifiedElement> FindGenericsField( UnifiedElement element, string containerType, string type = "*") { var fields = element.Descendants<UnifiedVariableDefinition>(); var genericsFields = fields.Where( f => f.Descendants().Any(e => e is UnifiedGenericType)); var result = genericsFields.Where( f => f.Descendants<UnifiedGenericType>() .Select( gt => ((UnifiedVariableIdentifier) gt.Type.BasicTypeName).Name). Contains(containerType)); if (type != "*") { result = result.Where( f => f.Descendants<UnifiedGenericType>().Select( gt => gt.Arguments).Select( arg => arg.Descendants <UnifiedIdentifier>(). First().Name).Contains( type)); } return result; }
/// <summary> /// 関数呼び出しから,定義を探します /// </summary> /// <param name="callNode"> 関数呼び出しノード </param> /// <param name="topNode"> 検索対象のトップノード </param> /// <returns> 呼び出された関数の定義 </returns> public static UnifiedFunctionDefinition FindDefinition( UnifiedCall callNode, UnifiedElement topNode) { var belongingNamespace = GetBelongingNamespace(callNode); var callingFuncName = ((UnifiedVariableIdentifier)callNode.Function).Name; UnifiedFunctionDefinition parent = null; foreach (var ns in belongingNamespace.YieldParents()) { var unifiedElement = FindUnifiedElementByNamespace( ns.GetNamespaceString(), topNode); var element = unifiedElement.First(); var found = element.Descendants<UnifiedFunctionDefinition>().Where( e => e.Name.Name == callingFuncName); if (found.Count() > 0) { parent = found.First(); break; } } // 呼び出しがあるのに,定義がない場合(標準関数など)は null が変える return parent; }
/// <summary> /// 指定した型に限定して,最初の指定した要素もしくはその子孫を取得します. /// </summary> /// <typeparam name="T"> </typeparam> /// <param name="element"> </param> /// <param name="dummyForInference"> </param> /// <returns> </returns> public static T FirstDescendantOrSelf <T>( this UnifiedElement element, T dummyForInference = null) where T : class { Contract.Requires(element != null); return(element.DescendantsAndSelf <T>().FirstOrDefault()); }
/// <summary> /// 指定した型に限定して,指定した要素の最初の祖先を取得します. /// </summary> /// <typeparam name="T"> </typeparam> /// <param name="element"> </param> /// <param name="dummyForInference"> </param> /// <returns> </returns> public static T FirstAncestor <T>( this UnifiedElement element, T dummyForInference = null) where T : class { Contract.Requires(element != null); return(element.Ancestors <T>().FirstOrDefault()); }
/// <summary> /// コレクションにコレクションを代入している関数を検索し取得します. /// </summary> /// <param name="element"> 検索対象のトップノード </param> /// <param name="collections"> コレクションフィールド群 </param> /// <returns> </returns> public static IEnumerable<UnifiedFunctionDefinition> FindSettingCollectionFunction( UnifiedElement element, IEnumerable<UnifiedElement> collections) { var collectionNames = collections.Select(e => e as UnifiedVariableDefinition). Select(e => e.Name.Name); var func = element.Descendants<UnifiedFunctionDefinition>() .Where( e => e.Body.Count == 1 && e.Body.First() is UnifiedBinaryExpression) // 2項演算式で .Where( e => ((UnifiedBinaryExpression)e.Body.First()).Operator. Kind == UnifiedBinaryOperatorKind.Assign) .Where( e => collectionNames.Contains( (((UnifiedBinaryExpression)e.Body.First()). LeftHandSide as UnifiedVariableIdentifier).Name)); // とりあえずは名前で判断 return func; }
/// <summary> /// 指定されたノード以下の,配列フィールドの定義を検索し,取得します /// </summary> /// <param name="element"> 検索するトップノード </param> /// <returns> 配列フィールドの定義 </returns> public static IEnumerable<UnifiedElement> FindArrayField( UnifiedElement element) { var fields = element.Descendants<UnifiedVariableDefinition>(); return fields.Where( f => f.Descendants().Any(e => e is UnifiedArrayType)); }
/// <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 override void Generate( UnifiedElement codeObject, TextWriter writer, string indentSign) { codeObject.Accept( new CCodeFactoryVisitor(writer, indentSign), new VisitorArgument()); }
private static void XmlWriteUnifiedElement( UnifiedElement elem, StringBuilder buffer, int depth) { // write items of enumerable var seq = elem as IEnumerable; if (seq != null) { foreach (var item in seq) { ToXmlRecursively(item, buffer, depth + 1); } } // write properties without indexer var values = elem.GetType().GetProperties() .Where(prop => !XmlIgnorePropertyNames.Contains(prop.Name)) .Where(prop => prop.GetIndexParameters().Length == 0) .Select(prop => prop.GetValue(elem, null)); foreach (var value in values) { ToXmlRecursively(value, buffer, depth + 1); } }
public static IEnumerable<UnifiedElement> GetTargetElements( UnifiedElement codeObject) { return codeObject.Descendants <UnifiedIf, UnifiedFor, UnifiedWhile, UnifiedDoWhile , UnifiedCase>(); }
/// <summary> /// 指定した子要素を削除します。 /// </summary> /// <param name="target"> 自分自身 </param> /// <returns> </returns> public virtual UnifiedElement RemoveChild(UnifiedElement target) { var reference = ElementReferencesOfFields() .First(e => ReferenceEquals(target, e.Element)); reference.Element = null; target.Parent = null; return(this); }
public string GenerateOrEmpty(UnifiedElement model) { if (model == null) { return string.Empty; } var writer = new StringWriter(); Generate(model, writer); return writer.ToString(); }
public static IEnumerable<UnifiedElement> YieldParents(UnifiedElement node) { var n = node; while(n != null) { yield return n; n = (UnifiedElement)n.Parent; } }
public static Dictionary<string, int> Measure( UnifiedElement codeObject, Func<UnifiedElement, IEnumerable<UnifiedElement>> getTargetElementsFunc) { var counts = new Dictionary<string, int>(); InitializeCounter(codeObject, counts); CountElements(getTargetElementsFunc(codeObject), counts); return counts; }
/// <summary> /// 指定した要素の祖先を列挙します. /// </summary> /// <param name="element"> </param> /// <returns> </returns> public static IEnumerable <UnifiedElement> Ancestors( this UnifiedElement element) { Contract.Requires(element != null); var parent = element; while ((parent = parent.Parent) != null) { yield return(parent); } }
public static IEnumerable<UnifiedFunctionDefinition> FindFunctionCollision(UnifiedElement element, UnifiedFunctionDefinition target) { foreach (var function in element.Descendants<UnifiedFunctionDefinition>()) { if (IsFunctionCollision(function, target)) { yield return function; } } }
/// <summary> /// 指定した要素とその子孫を列挙します. /// </summary> /// <param name="element"> </param> /// <returns> </returns> public static IEnumerable <UnifiedElement> DescendantsAndSelf( this UnifiedElement element) { Contract.Requires(element != null); yield return(element); foreach (var e in element.Descendants()) { yield return(e); } }
private static string GetOutersName(UnifiedElement element) { var klass = element as UnifiedClassLikeDefinition; if (klass != null) { return "[class] " + JavaFactory.GenerateCode(klass.Name); } var method = element as UnifiedFunctionDefinition; if (method != null) { return "[method] " + JavaFactory.GenerateCode(method.Name); } return null; }
//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()); } }
/// <summary> /// node から親をたどって,teypArray に含まれる要素のうち,一番早く見つかったものを返します.最上位ノードまで探索して,見つからなかったら null を返します. /// </summary> /// <param name="node"> 検索対象のノード </param> /// <param name="typeArray"> 検索する型の集合(の集合) </param> /// <returns> 1番早く見つかったオブジェクト </returns> public static IUnifiedElement GetFirstFoundNode( UnifiedElement node, IEnumerable<IEnumerable<Type>> typeArray) { foreach (var ancestor in node.Ancestors()) { foreach (var types in typeArray) { foreach (var t in types) { if (ancestor.GetType().Equals(t)) { return ancestor; } } } } return null; }
public static UnifiedVariableDefinition FindDefinition(UnifiedVariableIdentifier identifier, UnifiedElement topNode) { UnifiedVariableDefinition found = null; foreach (var node in identifier.FirstAncestor<UnifiedBlock>().Descendants()) { if (node is UnifiedVariableDefinition) { var vd = (UnifiedVariableDefinition)node; if (vd.Name.Name == identifier.Name) { return vd; } } } return null; }
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()); } } }
/// <summary> /// 深さ優先で指定した要素の子孫を列挙します. /// </summary> /// <param name="element"> </param> /// <returns> </returns> public static IEnumerable <UnifiedElement> Descendants( this UnifiedElement element) { Contract.Requires(element != null); var children = element.Elements() .Where(e => e != null); foreach (var child in children) { yield return(child); foreach (var grandchild in child.Descendants()) { yield return(grandchild); } } }
/// <summary> /// 深さ優先で指定した要素の子孫を列挙します. ただし条件に一致する要素を見つけたとき,その要素の探索を中止し次の要素の探索に移ります. /// </summary> /// <param name="element"> </param> /// <param name="predicate"> </param> /// <returns> </returns> public static IEnumerable <UnifiedElement> DescendantsUntil( this UnifiedElement element, Func <UnifiedElement, bool> predicate) { Contract.Requires(element != null); var children = element.Elements() .Where(e => e != null && !predicate(e)); foreach (var child in children) { yield return(child); foreach (var grandchild in child.DescendantsUntil(predicate)) { yield return(grandchild); } } }
/// <summary> /// 指定した子要素の親を指定した要素に設定します。 /// </summary> /// <typeparam name="T"> </typeparam> /// <param name="child"> 新たに設定する子要素 </param> /// <param name="oldChild"> 元の子要素 </param> /// <returns> </returns> public T SetChild <T>(T child, UnifiedElement oldChild) where T : UnifiedElement { if (child != null) { if (child.Parent != null) { throw new InvalidOperationException( "既に親要素が設定されている要素を設定できません。"); } (child).Parent = this; } else if (oldChild != null && Parent != null) { oldChild.RemoveSelf(); } return(child); }
/// <summary> /// コレクションフィールドをそのまま返却している関数を検索し取得します /// </summary> /// <param name="element"> 検索対象のトップノード </param> /// <param name="collections"> コレクションフィールド群 </param> /// <returns> </returns> public static IEnumerable<UnifiedFunctionDefinition> FindReturningCollectionFunction( UnifiedElement element, IEnumerable<UnifiedElement> collections) { var func = element.Descendants<UnifiedFunctionDefinition>().Where( f => f.Body.Count == 1 && f.Body.First() is UnifiedReturn); var collectionNames = collections.Select(e => e as UnifiedVariableDefinition). Select(e => e.Name.Name); var result = func.Where( f => collectionNames.Contains( (((UnifiedReturn)f.Body.First()).Value as UnifiedVariableIdentifier).Name)); return result; }
/// <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()); } } } }
/// <summary> /// 幅優先で指定した要素の子孫を列挙します. /// </summary> /// <param name="element"> </param> /// <returns> </returns> public static IEnumerable <UnifiedElement> DescendantsBfs( this UnifiedElement element) { Contract.Requires(element != null); var queue = new Queue <UnifiedElement>(); queue.Enqueue(element); while (queue.Count > 0) { var children = queue.Dequeue() .Elements() .Where(e => e != null); foreach (var child in children) { yield return(child); queue.Enqueue(child); } } }
/// <summary> /// 指定しオブジェクトのプロパティを再帰的に比較してオブジェクト同士の等価性を判断します. /// </summary> /// <param name="element"> </param> /// <param name="that"> </param> /// <returns> </returns> public static bool StructuralEquals( this UnifiedElement element, UnifiedElement that) { return(StructuralEqualityComparer.StructuralEquals(element, that)); }
/// <summary> /// 指定しオブジェクトのプロパティを再帰的に比較してオブジェクト同士の等価性を判断します. /// </summary> /// <param name="element"> </param> /// <param name="that"> </param> /// <returns> </returns> public static bool StructuralEquals( this UnifiedElement element, UnifiedElement that) { return StructuralEqualityComparer.StructuralEquals(element, that); }
public static string GenerateCode(UnifiedElement model) { return CodeGenerator.Generate(model); }
/// <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); }
/// <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="element"> </param> /// <returns> </returns> public static UnifiedElement GrandGrandParent( this UnifiedElement element) { Contract.Requires(element != null); return(element.Parent.SafeParent().SafeParent()); }
/// <summary> /// 指定した子要素を削除します。 /// </summary> /// <param name="target"> 削除する子要素 </param> /// <returns> レシーバーオブジェクト </returns> public override UnifiedElement RemoveChild(UnifiedElement target) { return(RemoveChild((TElement)target)); }
public abstract void Around(UnifiedElement model);
private static IEnumerable<UnifiedElement> GetProperties( UnifiedElement element) { var elements = element as IEnumerable<UnifiedElement>; if (elements != null) { foreach (var e in elements) { yield return e; } } var props = element.GetType().GetProperties() .Where(prop => prop.Name != "Parent") .Where(prop => prop.GetIndexParameters().Length == 0) .Where( prop => typeof(UnifiedElement).IsAssignableFrom( prop.PropertyType)); if (element is UnifiedWrapType) { props = props.Where(prop => prop.Name != "BasicTypeName"); } foreach (var prop in props) { yield return (UnifiedElement)prop.GetValue(element, null); } }
/// <summary> /// 親要素に不適切な要素がないかソースコードを指定して検査します。 /// </summary> /// <param name="codeObject"> 検査対象のモデル </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertParentProperty( UnifiedElement codeObject, string message) { foreach (var element in codeObject.Elements()) { if (element != null) { Assert.That(element.Parent, Is.SameAs(codeObject), message); AssertParentProperty(element, message); } } }
// TODO Pointcutの名前が競合しないようにする public abstract void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice);
public override void Around(UnifiedElement model) { throw new NotImplementedException(); }
public override void Generate( UnifiedElement codeObject, TextWriter writer) { Generate(codeObject, writer, "\t"); }
public override void Before(UnifiedElement model, AspectElement.Pointcut target, UnifiedBlock advice) { InsertAtBeforeCallByName(model, target.GetTargetName().ElementAt(1), advice); }