public StandardRule <T> GetRule <T>(CodeContext callerContext, DynamicAction action, object[] args) { Contract.RequiresNotNull(action, "action"); //Debug.Assert(action.Kind != ActionKind.GetMember || ((GetMemberAction)action).Name != SymbolTable.StringToId("x")); StandardRule <T> rule = _ruleCache.FindRule <T>(callerContext, action, args); if (rule != null) { return(rule); } NoteRuleCreation(action, args); IDynamicObject ndo = args[0] as IDynamicObject; if (ndo != null) { rule = ndo.GetRule <T>(action, callerContext, args); Debug.Assert(rule == null || rule.Target != null && rule.Test != null); } rule = rule ?? MakeRule <T>(callerContext, action, args); Debug.Assert(rule != null && rule.Target != null && rule.Test != null); #if DEBUG AstWriter.Dump(rule); #endif return(rule); }
public static void SyntaxFactoryArgumentListIncludeEmptyTrivia() { var actual = AstWriter.Serialize(SyntaxFactory.ArgumentList(), new AstWriterSettings(AstFormat.Light, AstTrivia.Token | AstTrivia.Node, ignoreEmptyTrivia: false)); var expected = "{ ArgumentList LeadingTrivia: [ { WhitespaceTrivia: \"\" } ] TrailingTrivia: [ { WhitespaceTrivia: \"\" } ]\n" + " ChildTokens: [ { OpenParenToken Text: \"(\" LeadingTrivia: [ { WhitespaceTrivia: \"\" } ] TrailingTrivia: [ { WhitespaceTrivia: \"\" } ] }\n" + " { CloseParenToken Text: \")\" LeadingTrivia: [ { WhitespaceTrivia: \"\" } ] TrailingTrivia: [ { WhitespaceTrivia: \"\" } ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public static void CompareTrees(string expected, AstRoot actualTree) { var astWriter = new AstWriter(); var actual = astWriter.WriteTree(actualTree); var result = BaselineCompare.CompareLines(expected, actual, out var expectedLine, out var actualLine, out var index); result.Should().Be(0, "Line at {0} should be {1}, but found {2}, different at position {3}", result, expectedLine, actualLine, index); }
public HappyScriptCode Analyze(Module module, SourceUnit sourceUnit) { Init(); //This List<Expression> becomes the global scope initializer var rootNamespaces = LoadAllAssemblies(module.LoadDirectives); ExpandoObject importScope = new ExpandoObject(); foreach (HappyNamespaceTracker tracker in rootNamespaces.Values) DynamicObjectHelpers.SetMember(importScope, tracker.Name, tracker); #if WRITE_AST AstWriter writer = new AstWriter(Console.Out); module.WriteString(writer); #endif var getRuntimeContextExpr = Expression.Dynamic(_languageContext.CreateGetMemberBinder(RuntimeContextIdentifier, false), typeof(object), _globalScopeExp); UnaryExpression runtimeContextExpression = Expression.Convert(getRuntimeContextExpr, typeof(HappyRuntimeContext)); var errorCollector = new ErrorCollector(_languageContext.ErrorSink); _analysisContext = new AnalysisContext(errorCollector, _languageContext, runtimeContextExpression, _globalScopeExp); RunAllVisitors(module, rootNamespaces); List<Expression> body = new List<Expression>(); //Initialize globals using (_scopeStack.TrackPush(module.SymbolTable)) { foreach (VariableDef def in module.GlobalDefStatements.SelectMany(defStmt => defStmt.VariableDefs)) { Expression initialValue = def.InitializerExpression != null ? ExpressionAnalyzer.Analyze(_analysisContext, def.InitializerExpression) : Expression.Constant(null, typeof(object)); HappySymbolBase symbol = module.SymbolTable.Items[def.Name.Text]; body.Add(symbol.GetSetExpression(initialValue)); } } body.AddRange(module.Functions.Select( func => _analysisContext.PropertyOrFieldSet(func.Name.Text, _globalScopeExp, FunctionAnalyzer.Analzye(_analysisContext, func)))); //At this point analysis has completed and all of our stacks should be empty DebugAssert.AreEqual(0, _scopeStack.Count, "scope stack not empty after analysis"); //Add an empty expression--prevents an exception by Expression.Lambda when body is empty. //This allows compilation of empty template sets. if(body.Count == 0) body.Add(Expression.Empty()); LambdaExpression globalScopeInitializer = Expression.Lambda(typeof(Action<IDynamicMetaObjectProvider>), Expression.Block(body), new[] { _globalScopeExp }); HappyScriptCode output = new HappyScriptCode(sourceUnit, globalScopeInitializer.Compile()); return output; }
/// <summary> /// Gets a rule, updates the site that called, and then returns the result of executing the rule. /// </summary> /// <typeparam name="T">The type of the DynamicSite the rule is being produced for.</typeparam> /// <param name="action">The Action the rule is being produced for.</param> /// <param name="args">The arguments to the rule as provided from the call site at runtime.</param> /// <param name="callerContext">The CodeContext that is requesting the rule and that should be used for conversions.</param> /// <param name="rules"></param> /// <param name="site"></param> /// <param name="target"></param> /// <returns>The result of executing the rule.</returns> internal object UpdateSiteAndExecute <T>(CodeContext callerContext, DynamicAction action, object[] args, object site, ref T target, ref RuleSet <T> rules) { Contract.RequiresNotNull(action, "action"); //Debug.Assert(action.Kind != ActionKind.GetMember || ((GetMemberAction)action).Name != SymbolTable.StringToId("x")); object result; StandardRule <T> rule = _ruleCache.ExecuteRuleAndUpdateSite <T>(callerContext, action, args, site, ref target, ref rules, out result); if (rule != null) { return(result); } NoteRuleCreation(action, args); for (; ;) { IDynamicObject ndo = args[0] as IDynamicObject; if (ndo != null) { rule = ndo.GetRule <T>(action, callerContext, args); Debug.Assert(rule == null || rule.Target != null && rule.Test != null); } rule = rule ?? MakeRule <T>(callerContext, action, args); Debug.Assert(rule != null && rule.Target != null && rule.Test != null); #if DEBUG AstWriter.Dump(rule); #endif object[] callArgs = args; if (args.Length > 6) { // BigDynamicSite callArgs = new object[] { Tuple.MakeTuple(rule.ParamVariables[0].Type, args) }; } CodeContext tmpCtx = callerContext.Scope.GetTemporaryVariableContext(callerContext, rule.ParamVariables, callArgs); try { if ((bool)rule.Test.Evaluate(tmpCtx)) { if (site != null) { DynamicSiteHelpers.UpdateSite <T>(callerContext, site, ref target, ref rules, rule); } _ruleCache.AddRule(action, args, rule); return(rule.Target.Execute(tmpCtx)); } } finally { tmpCtx.Scope.TemporaryStorage.Clear(); } } }
public static void SimpleClassJsonAllTrivia() { var tree = CSharpSyntaxTree.ParseText(@" namespace N { public class C { } }"); var node = tree.FindClassDeclaration("C"); var actual = AstWriter.Serialize(node, new AstWriterSettings(AstFormat.Json, AstTrivia.Node | AstTrivia.Token, ignoreEmptyTrivia: false)); var expected = "{ \"Kind\": \"ClassDeclaration\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ],\r\n" + " \"ChildTokens\": [ { \"Kind\": \"PublicKeyword\", \"Text\": \"public\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ] },\r\n" + " { \"Kind\": \"ClassKeyword\", \"Text\": \"class\", \"TrailingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ] },\r\n" + " { \"Kind\": \"IdentifierToken\", \"Text\": \"C\", \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] },\r\n" + " { \"Kind\": \"OpenBraceToken\", \"Text\": \"{\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] },\r\n" + " { \"Kind\": \"CloseBraceToken\", \"Text\": \"}\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public static void SimpleClassAllTrivia() { var tree = CSharpSyntaxTree.ParseText(@" namespace N { public class C { } }"); var node = tree.FindClassDeclaration("C"); var actual = AstWriter.Serialize(node, new AstWriterSettings(AstFormat.Light, AstTrivia.Node | AstTrivia.Token, ignoreEmptyTrivia: false)); var expected = "{ ClassDeclaration LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ EndOfLineTrivia ]\r\n" + " ChildTokens: [ { PublicKeyword LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ { WhitespaceTrivia: \" \" } ] }\r\n" + " { ClassKeyword TrailingTrivia: [ { WhitespaceTrivia: \" \" } ] }\r\n" + " { IdentifierToken Text: \"C\" TrailingTrivia: [ EndOfLineTrivia ] }\r\n" + " { OpenBraceToken Text: \"{\" LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ EndOfLineTrivia ] }\r\n" + " { CloseBraceToken Text: \"}\" LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ EndOfLineTrivia ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public static void SimpleClass() { var tree = CSharpSyntaxTree.ParseText(@" namespace N { public class C { } }"); var node = tree.FindClassDeclaration("C"); var actual = AstWriter.Serialize(node); var expected = "{ ClassDeclaration\r\n" + " ChildTokens: [ { PublicKeyword LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ { WhitespaceTrivia: \" \" } ] }\r\n" + " { ClassKeyword TrailingTrivia: [ { WhitespaceTrivia: \" \" } ] }\r\n" + " { IdentifierToken Text: \"C\" TrailingTrivia: [ EndOfLineTrivia ] }\r\n" + " { OpenBraceToken Text: \"{\" LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ EndOfLineTrivia ] }\r\n" + " { CloseBraceToken Text: \"}\" LeadingTrivia: [ { WhitespaceTrivia: \" \" } ] TrailingTrivia: [ EndOfLineTrivia ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public void SimpleClassJson() { SyntaxTree tree = CSharpSyntaxTree.ParseText(@" namespace RoslynSandbox { public class Foo { } }"); var node = tree.FindClassDeclaration("Foo"); var actual = AstWriter.Serialize(node, AstWriterSettings.DefaultJson); var expected = "{ \"Kind\": \"ClassDeclaration\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ],\r\n" + " \"ChildTokens\": [ { \"Kind\": \"PublicKeyword\", \"Text\": \"public\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ] },\r\n" + " { \"Kind\": \"ClassKeyword\", \"Text\": \"class\", \"TrailingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ] },\r\n" + " { \"Kind\": \"IdentifierToken\", \"Text\": \"Foo\", \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] },\r\n" + " { \"Kind\": \"OpenBraceToken\", \"Text\": \"{\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] },\r\n" + " { \"Kind\": \"CloseBraceToken\", \"Text\": \"}\", \"LeadingTrivia\": [ { \"Kind\": \"WhitespaceTrivia\", \"Text\": \" \" } ], \"TrailingTrivia\": [ { \"Kind\": \"EndOfLineTrivia\", \"Text\": \"\\r\\n\" } ] } ] }"; CodeAssert.AreEqual(expected, actual); }
private static void ParseFileImplementation(CoreTestFilesFixture fixture, string name) { string testFile = fixture.GetDestinationPath(name); string baselineFile = testFile + ".tree"; string text = fixture.LoadDestinationFile(name); AstRoot actualTree = RParser.Parse(text); AstWriter astWriter = new AstWriter(); string actual = astWriter.WriteTree(actualTree); if (_regenerateBaselineFiles) { // Update this to your actual enlistment if you need to update baseline baselineFile = Path.Combine(fixture.SourcePath, name) + ".tree"; TestFiles.UpdateBaseline(baselineFile, actual); } else { TestFiles.CompareToBaseLine(baselineFile, actual); } }
public static void Comment() { var tree = CSharpSyntaxTree.ParseText(@" namespace N { /// <summary> /// Some text /// </summary> public class C { } }"); var comment = (DocumentationCommentTriviaSyntax)tree.FindClassDeclaration("C").GetLeadingTrivia().Single(x => x.HasStructure).GetStructure(); var actual = AstWriter.Serialize(comment); var expected = "{ SingleLineDocumentationCommentTrivia\n" + " ChildTokens: [ { EndOfDocumentationCommentToken Text: \"\" } ]\n" + " ChildNodes: [ { XmlText\n" + " ChildTokens: [ { XmlTextLiteralToken Text: \" \" LeadingTrivia: [ { DocumentationCommentExteriorTrivia: \"///\" } ] } ] }\n" + " { XmlElement\n" + " ChildNodes: [ { XmlElementStartTag\n" + " ChildTokens: [ { LessThanToken Text: \"<\" }\n" + " { GreaterThanToken Text: \">\" } ]\n" + " ChildNodes: [ { XmlName\n" + " ChildTokens: [ { IdentifierToken Text: \"summary\" } ] } ] }\n" + " { XmlText\n" + " ChildTokens: [ { XmlTextLiteralNewLineToken Text: \"\\r\\n\" }\n" + " { XmlTextLiteralToken Text: \" Some text\" LeadingTrivia: [ { DocumentationCommentExteriorTrivia: \" ///\" } ] }\n" + " { XmlTextLiteralNewLineToken Text: \"\\r\\n\" }\n" + " { XmlTextLiteralToken Text: \" \" LeadingTrivia: [ { DocumentationCommentExteriorTrivia: \" ///\" } ] } ] }\n" + " { XmlElementEndTag\n" + " ChildTokens: [ { LessThanSlashToken Text: \"</\" }\n" + " { GreaterThanToken Text: \">\" } ]\n" + " ChildNodes: [ { XmlName\n" + " ChildTokens: [ { IdentifierToken Text: \"summary\" } ] } ] } ] }\n" + " { XmlText\n" + " ChildTokens: [ { XmlTextLiteralNewLineToken Text: \"\\r\\n\" } ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public static void CommentJsonAllTrivia() { var tree = CSharpSyntaxTree.ParseText(@" namespace N { /// <summary> /// Some text /// </summary> public class C { } }"); var comment = (DocumentationCommentTriviaSyntax)tree.FindClassDeclaration("C").GetLeadingTrivia().Single(x => x.HasStructure).GetStructure(); var expected = "{ \"Kind\": \"SingleLineDocumentationCommentTrivia\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ],\n" + " \"ChildTokens\": [ { \"Kind\": \"EndOfDocumentationCommentToken\", \"Text\": \"\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlText\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ],\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" \", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ] } ] },\n" + " { \"Kind\": \"XmlElement\",\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlElementStartTag\",\n" + " \"ChildTokens\": [ { \"Kind\": \"LessThanToken\", \"Text\": \"<\" },\n" + " { \"Kind\": \"GreaterThanToken\", \"Text\": \">\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlName\",\n" + " \"ChildTokens\": [ { \"Kind\": \"IdentifierToken\", \"Text\": \"summary\" } ] } ] },\n" + " { \"Kind\": \"XmlText\",\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" },\n" + " { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" Some text\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \" ///\" } ] },\n" + " { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" },\n" + " { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" \", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \" ///\" } ] } ] },\n" + " { \"Kind\": \"XmlElementEndTag\",\n" + " \"ChildTokens\": [ { \"Kind\": \"LessThanSlashToken\", \"Text\": \"</\" },\n" + " { \"Kind\": \"GreaterThanToken\", \"Text\": \">\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlName\",\n" + " \"ChildTokens\": [ { \"Kind\": \"IdentifierToken\", \"Text\": \"summary\" } ] } ] } ] },\n" + " { \"Kind\": \"XmlText\",\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" } ] } ] }"; var actual = AstWriter.Serialize(comment, new AstWriterSettings(AstFormat.Json, AstTrivia.Node | AstTrivia.Token, ignoreEmptyTrivia: false)); CodeAssert.AreEqual(expected, actual); }
public void CommentJson() { SyntaxTree tree = CSharpSyntaxTree.ParseText(@" namespace RoslynSandbox { /// <summary> /// Some text /// </summary> public class Foo { } }"); var comment = (DocumentationCommentTriviaSyntax)tree.FindClassDeclaration("Foo").GetLeadingTrivia().Single(x => x.HasStructure).GetStructure(); var actual = AstWriter.Serialize(comment, AstWriterSettings.DefaultJson); var expected = "{ \"Kind\": \"SingleLineDocumentationCommentTrivia\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ],\n" + " \"ChildTokens\": [ { \"Kind\": \"EndOfDocumentationCommentToken\", \"Text\": \"\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlText\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ],\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" \", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \"///\" } ] } ] },\n" + " { \"Kind\": \"XmlElement\",\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlElementStartTag\",\n" + " \"ChildTokens\": [ { \"Kind\": \"LessThanToken\", \"Text\": \"<\" },\n" + " { \"Kind\": \"GreaterThanToken\", \"Text\": \">\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlName\",\n" + " \"ChildTokens\": [ { \"Kind\": \"IdentifierToken\", \"Text\": \"summary\" } ] } ] },\n" + " { \"Kind\": \"XmlText\",\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" },\n" + " { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" Some text\", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \" ///\" } ] },\n" + " { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" },\n" + " { \"Kind\": \"XmlTextLiteralToken\", \"Text\": \" \", \"LeadingTrivia\": [ { \"Kind\": \"DocumentationCommentExteriorTrivia\", \"Text\": \" ///\" } ] } ] },\n" + " { \"Kind\": \"XmlElementEndTag\",\n" + " \"ChildTokens\": [ { \"Kind\": \"LessThanSlashToken\", \"Text\": \"</\" },\n" + " { \"Kind\": \"GreaterThanToken\", \"Text\": \">\" } ],\n" + " \"ChildNodes\": [ { \"Kind\": \"XmlName\",\n" + " \"ChildTokens\": [ { \"Kind\": \"IdentifierToken\", \"Text\": \"summary\" } ] } ] } ] },\n" + " { \"Kind\": \"XmlText\",\n" + " \"ChildTokens\": [ { \"Kind\": \"XmlTextLiteralNewLineToken\", \"Text\": \"\\r\\n\" } ] } ] }"; CodeAssert.AreEqual(expected, actual); }
public string WriteTree() { var writer = new AstWriter(); return(writer.WriteTree(this)); }
private static void DumpBlock(CodeBlock block, string id) { #if DEBUG AstWriter.Dump(block, id); #endif }