public void SetUp() { var inputPath = FixtureUtil.GetInputPath( "Java", "default", "Namespace.java"); var code = File.ReadAllText(inputPath, Encoding.Default); _model = JavaFactory.GenerateModel(code); }
public override bool Visit(UnifiedProgram element, VisitorArgument arg) { element.MagicComment.TryAccept(this, arg); Writer.WriteLine(); element.Body.TryAccept(this, arg); return(false); }
/// <summary> /// モデルを通した再生成したコードが変化しないか検査します。 元コード1→モデル1→コード2→モデル2→コード3→モデル3と再生成します。 モデル2とモデル3を比較します。 /// </summary> /// <param name="orgCode"> 検査対象のソースコード </param> /// <param name="codeObject"> 検査対象のモデル </param> private void AssertEqualsModel( string orgCode, UnifiedProgram codeObject) { string code2 = null, code3 = null; try { code2 = Fixture.CodeGenerator.Generate(codeObject); var obj2 = Fixture.ProgramGenerator.Generate(code2); code3 = Fixture.CodeGenerator.Generate(obj2); var obj3 = Fixture.ProgramGenerator.Generate(code3); Assert.That( obj3, Is.EqualTo(obj2).Using( StructuralEqualityComparerForDebug.Instance)); } catch (Exception e) { var outPath = FixtureUtil.GetOutputPath(); File.WriteAllText( Path.Combine(outPath, "orgignal.txt"), orgCode); if (code2 != null) { File.WriteAllText( Path.Combine(outPath, "generate.txt"), code2); } if (code3 != null) { File.WriteAllText( Path.Combine(outPath, "regenerate.txt"), code3); } throw e; } }
public override bool Visit(UnifiedProgram element, VisitorArgument arg) { element.MagicComment.TryAccept(this, arg); Writer.WriteLine(); element.Body.TryAccept(this, arg); return false; }
/// <summary> /// 指定されたクラス名を持つクラスを,プログラム中から検索して取得します /// </summary> /// <param name="program"> (トップノードの)プログラムオブジェクト </param> /// <param name="className"> 検索するクラス名 </param> /// <returns> 検索したクラスの UnifiedClassDefinition オブジェクト(の集合) </returns> public static IEnumerable<UnifiedClassDefinition> FindClassByClassName( UnifiedProgram program, string className) { var result = program.Descendants<UnifiedClassDefinition>().Where( e => ((UnifiedIdentifier)(e.Name)).Name == className); return result; }
/// <summary> /// 全要素の文字列情報を取得できるかソースコードを指定して検査します。 /// </summary> /// <param name="codeObject"> 検査対象のモデル </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertToString( UnifiedProgram codeObject, string message) { foreach (var element in codeObject.DescendantsAndSelf()) { Assert.That(element.ToString(), Is.Not.Null, message); } }
/// <summary> /// 指定した統一コードオブジェクトが適切な性質を備えているか検査します. /// </summary> /// <param name="codeObject"> 検査対象の統一コードオブジェクト </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertModelFeature( UnifiedProgram codeObject, string message) { AssertDeepCopy(codeObject, message); AssertGetElements(codeObject, message); AssertGetElementReferences(codeObject, message); AssertGetElementReferenecesOfFields(codeObject, message); AssertParentProperty(codeObject, message); AssertToString(codeObject, message); }
public static IEnumerable<UnifiedIdentifier> GetVariables( string name, UnifiedProgram codeObj) { var ids = codeObj.Descendants<UnifiedIdentifier>(); foreach (var id in ids) { if (id.Name.Equals(UnifiedIdentifier.CreateVariable(name).Name)) { yield return id; } } }
/// <summary> /// 指定されたクラスまたはプログラムに指定されたフィールドやメソッドを追加します。 /// </summary> /// <param name = "program">メンバーを追加するモデルのルートノード</param> /// <param name = "name">対象となるクラスやプログラムを指定する名前</param> /// <param name = "members">挿入するメンバーのリスト</param> public static void AddIntertypeDeclaration( UnifiedProgram program, string name, List <UnifiedExpression> members) { //クラスのリストを取得(Java, C#向け) var classes = program.Descendants <UnifiedClassDefinition>(); if (classes.Count() > 0) { foreach (var c in classes) { //クラス名を取得 var className = c.Name as UnifiedVariableIdentifier; if (className == null) { continue; } //受け取った名前を正規表現に変換し、クラス名が一致する場合は合成する var regex = new Regex(name == "*" ? ".*" : name); var m = regex.Match(className.Name); if (m.Success) { foreach (var e in members) { c.Body.Insert(0, e.DeepCopy()); } } } return; } //TODO interfaceのようにUnifiedClassDefinitionがない場合はここまでくるのでどう対処するか //とりあえず応急処置 var interfaces = program.Descendants <UnifiedInterfaceDefinition>(); if (interfaces.Count() > 0) { return; } var enums = program.Descendants <UnifiedEnumDefinition>(); if (enums.Count() > 0) { return; } //プログラムに対してメンバーを追加(JavaScript向け)) if (program != null) { foreach (var e in members) { program.Body.Insert(0, e.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 void Setup() { //Java言語のモデルを作成 _javaModel = UnifiedGenerators.GenerateProgramFromFile(JavaCodePath); _amountOfBlockInJava = _javaModel.Descendants <UnifiedBlock>().Count(); //JavaScript言語のモデルを作成 _javaScriptModel = UnifiedGenerators.GenerateProgramFromFile(JavaScriptCodePath); _amountOfBlockInJavaScript = _javaScriptModel.Descendants <UnifiedBlock>().Count(); }
//プログラム全体 public override bool Visit(UnifiedProgram element, VisitorArgument arg) { foreach (var sourceElement in element.Body) { if (sourceElement.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write("\n"); } return(false); }
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 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); }
/// <summary> /// コンパイル結果を通して再生成したコードが変化しないかテストします。 元コード1→モデル1→コード2と再生成します。 コンパイルしたアセンブリファイルの逆コンパイル結果を通して、 元コード1とコード2を比較します。 /// </summary> /// <param name="orgCode"> 検査対象のソースコード </param> /// <param name="fileName"> 再生成するソースコードのファイル名 </param> /// <param name="codeObject"> 検査対象のモデル </param> private void AssertEqualsCompiledCode( string orgCode, string fileName, UnifiedProgram codeObject) { // コンパイル用の作業ディレクトリの取得 var workPath = FixtureUtil.CleanOutputAndGetOutputPath(); // 作業ディレクトリ内にソースコードを配置 var srcPath = FixtureUtil.GetOutputPath(fileName); File.WriteAllText(srcPath, orgCode, XEncoding.SJIS); try { // 作業ディレクトリ内でコンパイル Fixture.Compile(workPath, srcPath); } catch (Exception e) { throw new Exception("Fail to compile the original code:\n" + orgCode, e); } // コンパイル結果の取得 var orgByteCode1 = Fixture.GetAllCompiledCode(workPath); // 再生成したソースコードを配置 var code2 = Fixture.CodeGenerator.Generate(codeObject); File.WriteAllText(srcPath, code2, XEncoding.SJIS); const string line = "------------------------"; try { // 再生成したソースコードのコンパイル結果の取得 Fixture.Compile(workPath, srcPath); } catch (Exception e) { throw new Exception( "Fail to compile the regenerated code:\n" + line + "regenerated code" + line + "\n" + code2 + line + "original code" + line + "\n" + orgCode, e); } var byteCode2 = Fixture.GetAllCompiledCode(workPath); try { AssertFuzzyEquals(byteCode2, orgByteCode1); } catch (Exception e) { throw new Exception( "Differencies exist:\n" + line + "regenerated code" + line + "\n" + code2 + line + "original code" + line + "\n" + orgCode, e); } }
/// <summary> /// 子要素の列挙機能が正常に動作するかソースーコードを指定して検査します。 /// </summary> /// <param name="codeObject"> 検査対象のモデル </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertGetElements( UnifiedProgram codeObject, string message) { foreach (var element in codeObject.Descendants()) { var elements = element.Elements(); // Depends on field refelection var references = element.ElementReferences(); var referenecesOfPrivateFields = element.ElementReferencesOfFields(); var propValues = GetProperties(element).ToList(); // Depends on property reflection var refElements = references.Select(t => t.Element).ToList(); var privateRefElements = referenecesOfPrivateFields.Select(t => t.Element).ToList (); Assert.That(elements, Is.EqualTo(propValues), message); Assert.That(refElements, Is.EqualTo(propValues), message); Assert.That(privateRefElements, Is.EqualTo(propValues), message); } }
/// <summary> /// 深いコピーが正常に動作するか検査します. /// </summary> /// <param name="codeObject"> 検査対象のモデル </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertDeepCopy( UnifiedProgram codeObject, string message) { var copiedModel = codeObject.DeepCopy(); Assert.That( copiedModel, Is.EqualTo(codeObject).Using( StructuralEqualityComparerForDebug.Instance)); var pairs = copiedModel.Descendants().Zip(codeObject.Descendants()); foreach (var pair in pairs) { Assert.That(pair.Item1.Parent, Is.Not.Null, message); Assert.That( ReferenceEquals(pair.Item1.Parent, pair.Item2.Parent), Is.False, message); } }
/// <summary> /// 子要素とプロパティを介さないセッターの列挙機能が正常に動作するかソースーコードを指定して検査します。 /// </summary> /// <param name="codeObject"> 検査対象のモデル </param> /// <param name="message"> アサーションに違反した際のエラーメッセージ </param> private static void AssertGetElementReferenecesOfFields( UnifiedProgram codeObject, string message) { codeObject = codeObject.DeepCopy(); var elements = codeObject.Descendants().ToList(); foreach (var element in elements) { var references = element.ElementReferencesOfFields(); foreach (var reference in references) { reference.Element = null; } } foreach (var element in elements) { foreach (var child in element.Elements()) { Assert.That(child, Is.Null, message); } } }
/// <summary> /// 指定されたクラスまたはプログラムに指定されたフィールドやメソッドを追加します。 /// </summary> /// <param name = "program">メンバーを追加するモデルのルートノード</param> /// <param name = "name">対象となるクラスやプログラムを指定する名前</param> /// <param name = "members">挿入するメンバーのリスト</param> public static void AddIntertypeDeclaration( UnifiedProgram program, string name, List<UnifiedExpression> members) { //クラスのリストを取得(Java, C#向け) var classes = program.Descendants<UnifiedClassDefinition>(); if (classes.Count() > 0) { foreach (var c in classes) { //クラス名を取得 var className = c.Name as UnifiedVariableIdentifier; if(className == null) continue; //受け取った名前を正規表現に変換し、クラス名が一致する場合は合成する var regex = new Regex(name == "*" ? ".*" : name); var m = regex.Match(className.Name); if (m.Success) { foreach (var e in members) { c.Body.Insert(0, e.DeepCopy()); } } } return; } //TODO interfaceのようにUnifiedClassDefinitionがない場合はここまでくるのでどう対処するか //とりあえず応急処置 var interfaces = program.Descendants<UnifiedInterfaceDefinition>(); if(interfaces.Count() > 0) return; var enums = program.Descendants<UnifiedEnumDefinition>(); if(enums.Count() > 0) return; //プログラムに対してメンバーを追加(JavaScript向け)) if (program != null) { foreach (var e in members) { program.Body.Insert(0, e.DeepCopy()); } } }
// 統合コードオブジェクトに対してアスペクトの合成処理を行います 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 bool Visit(UnifiedProgram element, VisitorArgument arg) { foreach (var sourceElement in element.Body) { if (sourceElement.TryAccept(this, arg)) { Writer.Write(";"); } Writer.Write("\n"); } return false; }
/// <summary> /// モデルを通した再生成したコードが変化しないか検査します。 /// 元コード1→モデル1→コード2→モデル2→コード3→モデル3と再生成します。モデル2とモデル3を比較します。 /// </summary> /// <param name="orgCode"> 検査対象のソースコード </param> /// <param name="codeObject"> 検査対象のモデル </param> private void AssertEqualsModel( string orgCode, UnifiedProgram codeObject) { string code2 = null, code3 = null; try { code2 = Fixture.CodeGenerator.Generate(codeObject); var obj2 = Fixture.ProgramGenerator.Generate(code2); code3 = Fixture.CodeGenerator.Generate(obj2); var obj3 = Fixture.ProgramGenerator.Generate(code3); Assert.That( obj3, Is.EqualTo(obj2).Using( StructuralEqualityComparerForDebug.Instance)); } catch (Exception e) { var outPath = FixtureUtil.GetOutputPath(); File.WriteAllText( Path.Combine(outPath, "orgignal.txt"), orgCode); if (code2 != null) { File.WriteAllText( Path.Combine(outPath, "generate.txt"), code2); } if (code3 != null) { File.WriteAllText( Path.Combine(outPath, "regenerate.txt"), code3); } throw e; } }
/// <summary> /// コンパイル結果を通して再生成したコードが変化しないかテストします。元コード1→モデル1→コード2と再生成します。 /// コンパイルしたアセンブリファイルの逆コンパイル結果を通して、元コード1とコード2を比較します。 /// </summary> /// <param name="orgCode"> 検査対象のソースコード </param> /// <param name="fileName"> 再生成するソースコードのファイル名 </param> /// <param name="codeObject"> 検査対象のモデル </param> private void AssertEqualsCompiledCode( string orgCode, string fileName, UnifiedProgram codeObject) { // コンパイル用の作業ディレクトリの取得 var workPath = FixtureUtil.CleanOutputAndGetOutputPath(); // 作業ディレクトリ内にソースコードを配置 var srcPath = FixtureUtil.GetOutputPath(fileName); File.WriteAllText(srcPath, orgCode, XEncoding.SJIS); try { // 作業ディレクトリ内でコンパイル Fixture.Compile(workPath, srcPath); } catch (Exception e) { throw new Exception("Fail to compile the original code:\n" + orgCode, e); } // コンパイル結果の取得 var orgByteCode1 = Fixture.GetAllCompiledCode(workPath); // 再生成したソースコードを配置 var code2 = Fixture.CodeGenerator.Generate(codeObject); File.WriteAllText(srcPath, code2, XEncoding.SJIS); const string line = "------------------------"; try { // 再生成したソースコードのコンパイル結果の取得 Fixture.Compile(workPath, srcPath); } catch (Exception e) { throw new Exception( "Fail to compile the regenerated code:\n" + line + "regenerated code" + line + "\n" + code2 + line + "original code" + line + "\n" + orgCode, e); } var byteCode2 = Fixture.GetAllCompiledCode(workPath); try { AssertFuzzyEquals(byteCode2, orgByteCode1); } catch (Exception e) { throw new Exception( "Differencies exist:\n" + line + "regenerated code" + line + "\n" + code2 + line + "original code" + line + "\n" + orgCode, e); } }
// 統合コードオブジェクトに対してアスペクトの合成処理を行います 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(); } } }
// プログラム全体(UnifiedProgram) /* UnifiedProgramはUnifiedBlockとしてプログラム内の全要素を保持しているが、 * その際中括弧を必要としないため、DecorationとしてForTopBlockを与える */ public override bool Visit(UnifiedProgram element, VisitorArgument arg) { element.Body.TryAccept(this, arg.Set(ForTopBlock)); return(false); }
public void Setup() { //Java言語のモデルを作成 _javaModel = UnifiedGenerators.GenerateProgramFromFile(JavaCodePath); _amountOfBlockInJava = _javaModel.Descendants<UnifiedBlock>().Count(); //JavaScript言語のモデルを作成 _javaScriptModel = UnifiedGenerators.GenerateProgramFromFile(JavaScriptCodePath); _amountOfBlockInJavaScript = _javaScriptModel.Descendants<UnifiedBlock>().Count(); }
// count statements of a unified code object private static int StatementNumber(UnifiedProgram codeObject) { var blocks = codeObject.Descendants<UnifiedBlock>(); var sum = 0; foreach (var block in blocks) { sum += block.Elements().Count(); } return sum; }
public static UnifiedProgram CreateProgram(XElement node) { Contract.Requires(node != null); return(UnifiedProgram.Create(CreateSmartBlock(node))); }
// コンストラクタ public EncapsulateCollection(UnifiedProgram program) { Program = program; }
// コンストラクタ public EncapsulateField(UnifiedProgram program) { Program = program; }
public override bool Visit(UnifiedProgram element, VisitorArgument arg) { element.Body.TryAccept(this, arg.Set(ForTopBlock)); return false; }
public void SetUp() { var inputPath = FixtureUtil.GetInputPath("CSharp", "EncapsulateField.cs"); var code = File.ReadAllText(inputPath, Encoding.Default); _model = CSharpFactory.GenerateModel(code); }