public void LexicalTokenMatching() { RoslynCompiler compiler = new RoslynCompiler(); var lexical = compiler.Lexical(); lexical .match() .any('(', '=', ',') .token("function", named: "fn") .enclosed('(', ')') .token('{', named: "brace") .then(compiler.Lexical().transform() .remove("fn") .insert("=>", before: "brace")) .match() .any(new[] { '(', '=', ',' }, named: "start") .enclosed('[', ']', start: "open", end: "close") .then(compiler.Lexical().transform() .insert("new []", after: "start") .replace("open", "{") .replace("close", "}")); ExpressionSyntax exprFunction = compiler.CompileExpression("call(10, function(x, y) {})"); Assert.IsTrue(exprFunction.DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Any()); ExpressionSyntax exprArray = compiler.CompileExpression("call([1, 2, 3], 4, [5, 6, 7])"); Assert.IsTrue(exprArray.DescendantNodes() .OfType<ImplicitArrayCreationExpressionSyntax>() .Count() == 2); }
public void CompilesHelloWorld() { var options = new Options() { Output = "hello.exe", Verbose = true }; options.AddInput("hello.ceylon"); var compiler = new RoslynCompiler(); compiler.Compile(options); }
public void AsynchUsage() { RoslynCompiler compiler = new RoslynCompiler(); Asynch.Apply(compiler); SyntaxTree tree = null; string text = null; //event handler usage var AsynchText = @" class foo { void bar() { asynch() { foobar(); } } }"; tree = compiler.ApplySemanticalPass(AsynchText, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Count() == 1); //must have added a callback Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<InvocationExpressionSyntax>() .Where(invocation => invocation.Expression.ToString() == "Task.Factory.StartNew") .Count() == 1); //must have added a task factory invocation Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .Count() == 1); //must have added a local variable for the asynch context var Synch = @" class foo { void bar() { asynch() { foobar(); synch() { barfoo(); } } } }"; tree = compiler.ApplySemanticalPass(Synch, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Count() == 2); //must have added a callback for asynch and another for synch }
public void LexicalExtension() { RoslynCompiler compiler = new RoslynCompiler(); var lexical = compiler.Lexical(); lexical .extension("my_ext", ExtensionKind.Code, myExtLexical); string lResult = compiler.ApplyLexicalPass("my_ext(int i) { code(); }"); Assert.IsTrue(lResult == "my_ext_replaced (int i) = { code(); }"); lexical .extension("my_ext_s", ExtensionKind.Member, myExtSyntactical); SyntaxNode sResult = compiler.ApplyLexicalPass("my_ext_s(int i) { code(); }", out lResult); Assert.IsTrue(lResult == "void __extension() {}"); var method = sResult .DescendantNodes() .OfType<MethodDeclarationSyntax>() .FirstOrDefault(); Assert.IsNotNull(method); Assert.IsTrue(method .ParameterList .Parameters .Count == 1); Assert.IsTrue(method .Body .Statements .Count == 1); }
public void Events() { RoslynCompiler compiler = new RoslynCompiler(); XSLang.Apply(compiler); SyntaxTree tree = null; string text = null; //event handler usage var handlerTest = @" class foo { public delegate void bar_delegate(int x, int y); public event bar_delegate bar; on bar() { } }"; tree = compiler.ApplySemanticalPass(handlerTest, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ConstructorDeclarationSyntax>() .Any()); //must have added a constructor Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .First() .Identifier.ToString() == "on_bar"); //must have added a method and renamed it //event declaration usage var declarationTest = @" class foo { public event bar(int x, int y); on bar() { } }"; tree = compiler.ApplySemanticalPass(declarationTest, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<EventFieldDeclarationSyntax>() .Any()); //must have added the event declaration var eventMethod = tree.GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .First(); Assert.IsTrue(eventMethod .ParameterList .Parameters .Count == 2); //must have added the event's parameters to the handler }
public void FlowsProjectPropertiesIntoAssembly() { const string testName = "Test name"; const string testTitle = "Test title"; const string testDescription = "Test description"; const string testCopyright = "Test copyright"; const string testAssemblyFileVersion = "1.2.3.4"; const string testVersion = "1.2.3-rc1"; const string testFrameworkName = "DNX,Version=v4.5.1"; // Arrange var compilationProjectContext = new CompilationProjectContext( new CompilationTarget(testName, new FrameworkName(testFrameworkName), string.Empty, string.Empty), string.Empty, string.Empty, testTitle, testDescription, testCopyright, testVersion, new Version(testAssemblyFileVersion), false, new CompilationFiles( new List<string> { }, new List<string> { }), new Mock<ICompilerOptions>().Object); var compiler = new RoslynCompiler( new Mock<ICache>().Object, new Mock<ICacheContextAccessor>().Object, new Mock<INamedCacheDependencyProvider>().Object, new Mock<IAssemblyLoadContext>().Object, new Mock<IApplicationEnvironment>().Object, new Mock<IServiceProvider>().Object); var metadataReference = new Mock<IRoslynMetadataReference>(); metadataReference .Setup(reference => reference.MetadataReference) .Returns(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); // Act var compilationContext = compiler.CompileProject( compilationProjectContext, new List<IMetadataReference> { metadataReference.Object }, new List<ISourceReference> { }, () => new List<ResourceDescriptor> { }); // Assert var expectedAttributes = new Dictionary<string, string> { [typeof(AssemblyTitleAttribute).FullName] = testTitle, [typeof(AssemblyDescriptionAttribute).FullName] = testDescription, [typeof(AssemblyCopyrightAttribute).FullName] = testCopyright, [typeof(AssemblyFileVersionAttribute).FullName] = testAssemblyFileVersion, [typeof(AssemblyVersionAttribute).FullName] = testVersion.Substring(0, testVersion.IndexOf('-')), [typeof(AssemblyInformationalVersionAttribute).FullName] = testVersion, }; var compilationAttributes = compilationContext.Compilation.Assembly.GetAttributes(); Assert.All(compilationAttributes, compilationAttribute => expectedAttributes[compilationAttribute.AttributeClass.ToString()].Equals( compilationAttribute.ConstructorArguments.First().Value)); }
public RoslynCodeGenVisitor(Logger log, INativeTypeMapper mapper, Options options, RoslynCompiler.State state, TypeChecker tc) { _log = log; _mapper = mapper; _options = options; _state = state; _tc = tc; }
public void Arrays() { RoslynCompiler compiler = new RoslynCompiler(); XSLang.Apply(compiler); ExpressionSyntax exprArray = compiler.CompileExpression("x = [[1, 2, 3], [4, 5, 6]]"); Assert.IsTrue(exprArray.DescendantNodes() .OfType<ImplicitArrayCreationExpressionSyntax>() .Count() == 3); }
public void Contract() { RoslynCompiler compiler = new RoslynCompiler(); Excess.Entensions.XS.Contract.Apply(compiler); SyntaxTree tree = null; string text = null; //usage var Usage = @" class foo { void bar(int x, object y) { contract() { x > 3; y != null; } } }"; tree = compiler.ApplySemanticalPass(Usage, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<IfStatementSyntax>() .Count() == 2); //must have added an if for each contract condition //errors var Errors = @" class foo { void bar(int x, object y) { contract() { x > 3; return 4; //contract01 - only expressions } var noContract = contract() //contract01 - not as expression { x > 3; return 4; } } }"; var doc = compiler.CreateDocument(Errors); compiler.ApplySemanticalPass(doc, out text); Assert.IsTrue(doc .GetErrors() .Count() == 2); //must produce 2 errors }
private static void PrepareCompilation(ICompilerOptions compilerOptions, out RoslynCompiler compiler, out CompilationProjectContext projectContext) { var cacheContextAccessor = new FakeCacheContextAccessor { Current = new CacheContext(null, (d) => { }) }; compiler = new RoslynCompiler(null, cacheContextAccessor, new FakeNamedDependencyProvider(), null, null, null); var compilationTarget = new CompilationTarget("test", new FrameworkName(".NET Framework, Version=4.0"), "Release", null); projectContext = new CompilationProjectContext( compilationTarget, Directory.GetCurrentDirectory(), "project.json", "title", "description", "copyright", "1.0.0", new System.Version(1, 0), false, new CompilationFiles(Enumerable.Empty<string>(), Enumerable.Empty<string>()), compilerOptions); }
public void Json_Usage() { RoslynCompiler compiler = new RoslynCompiler(); JsonExtension.Apply(compiler); SyntaxTree tree = null; string text = null; //usage var Code = @" void main() { var expr = 20; var foo = json() { x : 3, y : [3, 4, 5], z : {a : 10, b : 20}, w : [ {a : 100, b : 200, c: [expr, expr + 1, expr + 2]}, {a : 150, b : 250, c: [expr, expr - 1, expr - 2]} ] } }"; tree = compiler.ApplySemanticalPass(Code, out text); var anonymous = tree.GetRoot() .DescendantNodes() .OfType <AnonymousObjectCreationExpressionSyntax>() .First(); Assert.IsNotNull(anonymous); //must have created an anonymous object Assert.IsTrue(anonymous .Initializers .Count == 4); //4 members Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <ImplicitArrayCreationExpressionSyntax>() .Count() == 4); //4 arrays }
private static SyntaxNode ProcessAsynch(SyntaxNode node, Scope scope, SyntacticalExtension <SyntaxNode> extension) { if (extension.Kind == ExtensionKind.Code) { var result = AsynchTemplate .ReplaceNodes(AsynchTemplate .DescendantNodes() .OfType <BlockSyntax>(), (oldNode, newNode) => extension.Body); var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(node.Parent, RoslynCompiler.AddStatement(ContextVariable, before: node)); return(result); } scope.AddError("asynch01", "asynch does not return a value", node); return(node); }
//compiler private RoslynCompiler CreateCompiler() { var compiler = new RoslynCompiler(); var instance = compiler.Instance(); instance.match <Parameter>() .output("value"); instance.match <Return>() .input("value", ReturnValue) .then <Return>(ReturnExec); instance.match <Operator>() .input("left", Operand(true)) .input("right", Operand(false)) .then <Operator>(OperatorExec); instance.then(GenerateCode); return(compiler); }
public ParserRuleContext Parse(LexicalExtension <SyntaxToken> extension, Scope scope) { var text = RoslynCompiler.TokensToString(extension.Body); //td: token matching AntlrInputStream stream = new AntlrInputStream(text); ITokenSource lexer = GetLexer(stream); ITokenStream tokenStream = new CommonTokenStream(lexer); Parser parser = GetParser(tokenStream); parser.AddErrorListener(new AntlrErrors <IToken>(scope, extension.BodyStart)); var result = GetRoot(parser); if (parser.NumberOfSyntaxErrors > 0) { return(null); } return(result); }
private static CompilationContext Compile(FakeCompilerOptions compilerOptions, CompilationTarget target) { var cacheContextAccessor = new FakeCacheContextAccessor { Current = new CacheContext(null, (d) => { }) }; var compilationProjectContext = new CompilationProjectContext( target, Directory.GetCurrentDirectory(), "project.json", TestTitle, TestDescription, TestCopyright, TestVersion, Version.Parse(TestAssemblyFileVersion), false, new CompilationFiles( new List <string> { }, new List <string> { }), compilerOptions); var compiler = new RoslynCompiler(null, cacheContextAccessor, new FakeNamedDependencyProvider(), null, null, null); var assembly = typeof(object).GetTypeInfo().Assembly; var metadataReference = new FakeMetadataReference() { MetadataReference = MetadataReference.CreateFromFile((string)assembly.GetType().GetProperty("Location").GetValue(assembly)) }; var compilationContext = compiler.CompileProject( compilationProjectContext, new List <IMetadataReference> { metadataReference }, new List <ISourceReference> { }, () => new List <ResourceDescriptor>(), "Debug"); return(compilationContext); }
public static SyntaxTree Link(string code, Action <Compiler> builder = null, Mapper mapper = null) { //build a compiler var compiler = new RoslynCompiler(); if (builder == null) { builder = (c) => XSLanguage.Apply(c); } builder(compiler); //then a document var document = new RoslynDocument(compiler.Scope, code); //mapping document.Mapper = mapper; //do the compilation compiler.apply(document); document.applyChanges(CompilerStage.Syntactical); var node = document.SyntaxRoot; if (mapper != null) { var translated = mapper.RenderMapping(node, string.Empty); node = CSharp.ParseCompilationUnit(translated); } var compilation = CSharpCompilation.Create("mock-assembly", syntaxTrees: new[] { node.SyntaxTree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), MetadataReference.CreateFromFile(typeof(Dictionary <int, int>).Assembly.Location), }); document.SyntaxRoot = node; document.Model = compilation.GetSemanticModel(node.SyntaxTree); document.applyChanges(CompilerStage.Finished); return(document.SyntaxRoot.SyntaxTree); }
public void TypeDef() { RoslynCompiler compiler = new RoslynCompiler(); XSLang.Apply(compiler); SyntaxTree tree = null; string text = null; //event handler usage var cStyle = @" class foo { typedef List<int> bar; bar foobar; }"; tree = compiler.ApplySemanticalPass(cStyle, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <FieldDeclarationSyntax>() .First() .Declaration .Type .ToString() == "List<int>"); //must have replaced the type var csharpStyle = @" class foo { typedef bar = List<int>; bar foobar; }"; tree = compiler.ApplySemanticalPass(csharpStyle, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <FieldDeclarationSyntax>() .First() .Declaration .Type .ToString() == "List<int>"); //must be equivalent to the last test }
public static SyntaxTree Compile(string code, out string text, bool withInterface = false, bool withRemote = false) { var config = MockInjector(new Options { GenerateInterface = withInterface, GenerateRemote = withRemote, }); var compiler = new RoslynCompiler(); config.apply(compiler); var tree = compiler.ApplySemanticalPass(code); text = tree.GetRoot().NormalizeWhitespace().ToFullString(); return(tree); }
/// <summary> /// Initialize engine /// </summary> /// <param name="services">Collection of service descriptors</param> public void Initialize(IServiceCollection services) { //set base application path var provider = services.BuildServiceProvider(); var hostingEnvironment = provider.GetRequiredService <IWebHostEnvironment>(); var grandConfig = provider.GetRequiredService <GrandConfig>(); CommonHelper.HostingEnvironment = hostingEnvironment; //register mongo mappings MongoDBMapperConfiguration.RegisterMongoDBMappings(grandConfig); //initialize plugins var mvcCoreBuilder = services.AddMvcCore(); PluginManager.Initialize(mvcCoreBuilder, grandConfig); //initialize CTX sctipts RoslynCompiler.Initialize(mvcCoreBuilder.PartManager, grandConfig); }
public void BasicAwait() { RoslynCompiler compiler = new RoslynCompiler(); Extensions.Concurrent.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; tree = compiler.ApplySemanticalPass(@" concurrent class SomeClass { public void A(); public void B(); void main() { await A; int val = await C(); val++; } private int C() { await B; return 10; } }", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <InvocationExpressionSyntax>() .Where(invocation => invocation .Expression .ToString() == "__listen") .Count(invocation => new[] { "\"A\"", "\"B\"" } .Contains(invocation .ArgumentList .Arguments[0] .Expression.ToString())) == 2); //must have listened to both signals }
public void BasicTryCatch() { RoslynCompiler compiler = new RoslynCompiler(); Extensions.Concurrent.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; tree = compiler.ApplySemanticalPass(@" concurrent class SomeClass { public void A(); public void B(); void main() { try { int someValue = 10; int someOtherValue = 11; A | B; someValue++; B >> A; someOtherValue++; } catch { } } }", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <TryStatementSyntax>() .Count() == 2); //must have added a a try statement }
public PostSharpProjectCompiler( ICache cache, ICacheContextAccessor cacheContextAccessor, INamedCacheDependencyProvider namedCacheProvider, IAssemblyLoadContext loadContext, IApplicationEnvironment environment, IServiceProvider services) { _services = services; _compiler = new RoslynCompiler( cache, cacheContextAccessor, namedCacheProvider, loadContext, environment, services); _cache = cache; _workingDirectory = cache.Get <string>("PostSharp.Dnx.WorkingDirectory", cacheContext => Path.Combine(Path.GetTempPath(), "PostSharp.Dnx", Guid.NewGuid().ToString())); Task.Run(() => PurgeWorkingDirectories()); CreateWorkingDirectory(); }
private static TypeDeclarationSyntax ParseModel(ClassDeclarationSyntax @class, ParameterListSyntax parameters, Scope scope) { var init = new List <ParameterSyntax>(); var props = new List <PropertyDeclarationSyntax>(); foreach (var member in @class.Members) { var field = ParseField(member); if (field == null) { continue; //error has already been registered } var type = field.Declaration.Type; var variable = field.Declaration .Variables .Single(); init.Add(CSharp.Parameter(variable.Identifier) .WithType(type) .WithDefault(CSharp.EqualsValueClause( variable.Initializer != null ? variable.Initializer.Value : CSharp.DefaultExpression(type)))); props.Add(ModelProperty.Get <PropertyDeclarationSyntax>(type) .WithIdentifier(variable.Identifier)); } if (!RoslynCompiler.HasVisibilityModifier(@class.Modifiers)) { @class = @class.AddModifiers(CSharp.Token(SyntaxKind.PublicKeyword)); } return(@class .WithMembers(CSharp.List <MemberDeclarationSyntax>( props.Union(new[] { GenerateConstructor(@class, init) })))); }
public void Test() { string toCompile = @"using System; namespace Bam.Net.Dynamic { public class WorkerPropertyResolver { public WorkState WorkState { get; set; } public Job Job { get; set; } public {{PropertyType}} Resolve() { return Resolve({{PropertyResolverLambda}}); } public {{PropertyType}} Resolve(Func<WorkState, Job> propertyResolver) { return propertyResolver(WorkState, Job); } } }"; RoslynCompiler compiler = new RoslynCompiler(); compiler.AddAssemblyReference( "C:\\bam\\nuget\\global\\runtime.win-x64.microsoft.netcore.app\\2.2.2\\runtimes\\win-x64\\lib\\netcoreapp2.2\\Microsoft.CSharp.dll"); compiler.AddAssemblyReference(typeof(ExpandoObject).Assembly.Location); compiler.AddAssemblyReference("C:\\bam\\nuget\\global\\runtime.win-x64.microsoft.netcore.app\\2.2.2\\runtimes\\win-x64\\lib\\netcoreapp2.2\\System.Runtime.dll"); compiler.AddAssemblyReference("C:\\bam\\nuget\\global\\runtime.win-x64.microsoft.netcore.app\\2.2.2\\runtimes\\win-x64\\lib\\netcoreapp2.2\\System.Core.dll"); byte[] assBytes = compiler.Compile(toCompile.Sha1(), toCompile); Assembly compiled = Assembly.Load(assBytes); Type dynamicContext = compiled.GetTypes().FirstOrDefault(); object instance = dynamicContext.Construct(); Expect.IsNotNull(dynamicContext); object output = instance.Invoke("Fun", (Func <string>)(() => "baloney")); Expect.IsNotNull(output); Console.WriteLine(output.ToString()); }
public void SyntacticalMatching_Usage() { RoslynCompiler compiler = new RoslynCompiler(); var syntax = compiler.Syntax(); //simple match syntax .match <ClassDeclarationSyntax>(c => !c.Members.OfType <ConstructorDeclarationSyntax>().Any()) .then(addConstructor); var tree = compiler.ApplySyntacticalPass("class foo { } class bar { bar() {} }"); Assert.IsTrue(tree .GetRoot() .DescendantNodes() .OfType <ConstructorDeclarationSyntax>() .Count() == 2); //must have added a constructor to "foo" //scope match & transform syntax .match <ClassDeclarationSyntax>(c => c.Identifier.ToString() == "foo") .descendants <MethodDeclarationSyntax>(named: "methods") .descendants <PropertyDeclarationSyntax>(prop => prop.Identifier.ToString().StartsWith("my"), named: "myProps") .then(syntax.transform() .replace("methods", method => ((MethodDeclarationSyntax)method) .WithIdentifier(CSharp.ParseToken("my" + ((MethodDeclarationSyntax)method).Identifier.ToString()))) .remove("myProps")); var scopeTree = compiler.ApplySyntacticalPass("class foo { public void Method() {} int myProp {get; set;} }"); Assert.IsTrue(scopeTree.ToString() == "class foo { public void myMethod() {} foo (){}}"); Assert.IsTrue(scopeTree .GetRoot() .DescendantNodes() .OfType <ConstructorDeclarationSyntax>() .Count() == 1); //must have added a constructor to "foo", since the syntax is the same }
/// <summary> /// Initialize engine /// </summary> /// <param name="services">Collection of service descriptors</param> public void Initialize(IServiceCollection services, IConfiguration configuration) { //set base application path var provider = services.BuildServiceProvider(); var hostingEnvironment = provider.GetRequiredService <IWebHostEnvironment>(); var config = new GrandConfig(); configuration.GetSection("Grand").Bind(config); CommonHelper.BaseDirectory = hostingEnvironment.ContentRootPath; //register mongo mappings MongoDBMapperConfiguration.RegisterMongoDBMappings(); //initialize plugins var mvcCoreBuilder = services.AddMvcCore(); PluginManager.Initialize(mvcCoreBuilder, config); //initialize CTX sctipts RoslynCompiler.Initialize(mvcCoreBuilder.PartManager, config); }
[TestMethod, Ignore] //reconcile with the extension refactoring public void LexicalExtension_Usage() { RoslynCompiler compiler = new RoslynCompiler(); var lexical = compiler.Lexical(); lexical .extension("my_ext", ExtensionKind.None, myExtLexical); string lResult = compiler.ApplyLexicalPass("my_ext(int i) { code(); }"); Assert.IsTrue(lResult == "my_ext_replaced (int i) = { code(); }"); lResult = compiler.ApplyLexicalPass("my_ext { code(); }"); Assert.IsTrue(lResult == "my_ext_replaced (int i) = { code(); }"); lexical .extension("my_ext_s", ExtensionKind.Member, myExtSyntactical); SyntaxNode sResult = compiler.ApplyLexicalPass("my_ext_s(int i) { code(); }", out lResult); Assert.IsTrue(lResult == "void __extension() {}"); var method = sResult .DescendantNodes() .OfType <MethodDeclarationSyntax>() .FirstOrDefault(); Assert.IsNotNull(method); Assert.IsTrue(method .ParameterList .Parameters .Count == 1); Assert.IsTrue(method .Body .Statements .Count == 1); }
private SyntaxNode myExtSyntactical(SyntaxNode node, Scope scope, LexicalExtension <SyntaxToken> extension) { Assert.IsTrue(node is MethodDeclarationSyntax); var method = node as MethodDeclarationSyntax; Assert.IsTrue(method.Identifier.ToString() == "__extension"); var argString = RoslynCompiler.TokensToString(extension.Arguments); Assert.IsTrue(argString == "(int i) "); var arguments = CSharp.ParseParameterList(argString); var codeString = RoslynCompiler.TokensToString(extension.Body); var codeNode = CSharp.ParseStatement(codeString); Assert.IsTrue(codeNode is BlockSyntax); var code = codeNode as BlockSyntax; return(method .WithIdentifier(CSharp.ParseToken("my_ext_s")) .WithParameterList(arguments) .WithBody(code)); }
private static SyntaxNode Transform(SyntaxNode oldNode, SyntaxNode newNode, Scope scope, LexicalExtension <SyntaxToken> extension) { Debug.Assert(newNode is BlockSyntax); var isAssignment = oldNode is LocalDeclarationStatementSyntax; if (!isAssignment && oldNode is BinaryExpressionSyntax) { var expr = oldNode as BinaryExpressionSyntax; isAssignment = expr.Kind() == SyntaxKind.SimpleAssignmentExpression; } if (isAssignment) { scope.AddError("r01", "R does not return", oldNode); return(newNode); } var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(oldNode.Parent, RoslynCompiler.ExplodeBlock(newNode)); return(newNode); }
private static void FixMissingType(SyntaxNode node, Scope scope) { var type = node .Ancestors() .OfType <TypeDeclarationSyntax>() .FirstOrDefault(); if (type != null) { var typeScope = scope.GetScope <SyntaxToken, SyntaxNode, SemanticModel>(type); if (typeScope != null) { SyntaxNode realType = typeScope.get <SyntaxNode>("__tdef" + node.ToString()); if (realType != null) { realType = RoslynCompiler.Mark(realType); //make sure not to duplicate nodes var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(node, RoslynCompiler.ReplaceNode(realType)); } } } }
public void InstanceUsage() { RoslynCompiler compiler = new RoslynCompiler(); var instance = compiler.Instance(); //code extension instance .match <InstanceFoo>() .input(new InstanceConnector { Id = "input" }, dt: FooInput) .output(new InstanceConnector { Id = "output" }) .then(TransformFoo) .match <InstanceBar>() .input(new InstanceConnector { Id = "input" }) .output(new InstanceConnector { Id = "output" }, transform: BarOutput) .then(TransformBar) .then(TransformInstances); SyntaxTree tree; string text; RoslynInstanceDocument doc = new RoslynInstanceDocument(InstanceTestParser); tree = compiler.CompileInstance(doc, out text); Assert.IsTrue(tree .GetRoot() .DescendantNodes() .OfType <ParenthesizedLambdaExpressionSyntax>() .Count() == 2); //must have added a PropertyChanged handler }
public override Assembly GetAssembly() { if (Directory.Exists(Id)) { RoslynCompiler compiler = new RoslynCompiler(FolderSettings.DebugBuild); bool hasFile = false; StringBuilder sb = new StringBuilder(); sb.Append("Compiling files from ").Append(Id).Append(":").AppendLine(); foreach (var file in GetProjectFiles(Id)) { using (FileStream fileStream = File.OpenRead(file)) { hasFile = true; string name = file.Substring(Id.Length + 1, file.Length - (Id.Length + 1)); sb.Append(name).Append(", "); compiler.Load(fileStream, file); } } if (hasFile) { sb.Length -= 2; LogFile.WriteLine(sb.ToString()); } else { throw new IOException("No files were found in the directory specified."); } byte[] data = compiler.Compile(FriendlyName + '_' + Path.GetRandomFileName(), out byte[] symbols); Assembly a = Assembly.Load(data, symbols); Version = a.GetName().Version; return(a); } throw new DirectoryNotFoundException("Unable to find directory '" + Id + "'"); }
public void DebugPrint() { RoslynCompiler compiler = new RoslynCompiler(); Extensions.Concurrent.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; tree = compiler.ApplySemanticalPass(@" concurrent class ring_item { int _idx; public ring_item(int idx) { _idx = idx; } public ring_item Next {get; set;} static int ITERATIONS = 50*1000*1000; public void token(int value) { console.write(value); if (value >= ITERATIONS) { console.write(_idx); Node.Stop(); } else Next.token(value + 1); } }", out text); Assert.IsNotNull(text); }
public void FlukeUsage() { RoslynCompiler compiler = new RoslynCompiler(); Entensions.XS.Members.Apply(compiler); Extensions.Fluke.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; //usage var Usage = @" public repository CompanyAddress { repository<AddressType> _address; constructor(repository<AddressType> address) { _address = address; } private AddressType GetDefaultAddressType() { //get default address type return __address.ToList().FirstOrDefault(); } }"; tree = compiler.ApplySemanticalPass(Usage, out text); Assert.AreEqual(tree.GetRoot() .DescendantNodes() .OfType<ClassDeclarationSyntax>() .Count(), 1); //must have added a class Assert.AreEqual(tree.GetRoot() .DescendantNodes() .OfType<InterfaceDeclarationSyntax>() .Count(), 1); //must have added an interface }
public void Members() { RoslynCompiler compiler = new RoslynCompiler(); XSLang.Apply(compiler); SyntaxTree tree = null; string text = null; //typed method tree = compiler.ApplySyntacticalPass("class foo { int method bar() {}}", out text); Assert.IsTrue(text == "class foo\r\n{\r\n public int bar()\r\n {\r\n }\r\n}"); //untyped method tree = compiler.ApplySemanticalPass("class foo { method bar() { return 5; }}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .First() .ReturnType .ToString() == "Int32"); //must have added a return type //constructors tree = compiler.ApplySyntacticalPass("class foo { constructor(int x, int y) {}}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ConstructorDeclarationSyntax>() .Any()); //must have added a constructor Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ClassDeclarationSyntax>() .First() .Members .Count == 1); //must have nothing else //typed properties tree = compiler.ApplySyntacticalPass("class foo { int property bar; }", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<PropertyDeclarationSyntax>() .Any()); //must have added a property //untyped properties, initialization tree = compiler.ApplySyntacticalPass("class foo { property bar = 3; }", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<PropertyDeclarationSyntax>() .Any()); //must have added a property Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ConstructorDeclarationSyntax>() .Any()); //must have added a constructor for initialization }
private static SyntaxNode Property(SyntaxNode node, Scope scope) { var field = node.AncestorsAndSelf() .OfType <MemberDeclarationSyntax>() .FirstOrDefault() as FieldDeclarationSyntax; if (field == null) { //td: error, malformed property return(node); } if (field.Declaration.Variables.Count != 1) { //td: error, malformed property return(node); } var variable = field .Declaration .Variables[0]; var initializer = variable.Initializer; var type = field.Declaration.Type; if (type == null || type.IsMissing || type.ToString() == "property") //untyped { if (initializer != null) { type = RoslynCompiler.ConstantType(initializer.Value); } } if (type == null) { type = RoslynCompiler.@object; } var property = _property .WithIdentifier(variable.Identifier) .WithType(type); if (!RoslynCompiler.HasVisibilityModifier(field.Modifiers)) { property = property.AddModifiers(CSharp.Token(SyntaxKind.PublicKeyword)); } var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); //schedule the field replacement //td: coud be done in this pass with the right info from lexical document.change(field, RoslynCompiler.ReplaceNode(property)); //must be initialized if (initializer != null) { var expr = (AssignmentExpressionSyntax)_assignment.Expression; document.change(field.Parent, RoslynCompiler .AddInitializers(_assignment.WithExpression(expr .WithLeft(CSharp.IdentifierName(variable.Identifier)) .WithRight(initializer.Value)))); } return(node); }
public void TypeDef() { RoslynCompiler compiler = new RoslynCompiler(); XSLang.Apply(compiler); SyntaxTree tree = null; string text = null; //event handler usage var cStyle = @" class foo { typedef List<int> bar; bar foobar; }"; tree = compiler.ApplySemanticalPass(cStyle, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<FieldDeclarationSyntax>() .First() .Declaration .Type .ToString() == "List<int>"); //must have replaced the type var csharpStyle = @" class foo { typedef bar = List<int>; bar foobar; }"; tree = compiler.ApplySemanticalPass(csharpStyle, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<FieldDeclarationSyntax>() .First() .Declaration .Type .ToString() == "List<int>"); //must be equivalent to the last test }
public void MatchExtension() { RoslynCompiler compiler = new RoslynCompiler(); Match.Apply(compiler); SyntaxTree tree = null; string text = null; //event handler usage var SimpleUsage = @" class foo { void bar() { match(x) { case 10: is_10(); case > 10: greater_than_10(); default: less_than_10(); } } }"; tree = compiler.ApplySemanticalPass(SimpleUsage, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<IfStatementSyntax>() .Count() == 2); //must have replaced the match with 2 ifs Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ElseClauseSyntax>() .Count() == 2); //must have added an else for the default case var MultipleUsage = @" class foo { void bar() { match(x) { case 10: case 20: is_10_or_20(); case > 10: greater_than_10(); greater_than_10(); case < 10: default: less_than_10(); } } }"; tree = compiler.ApplySemanticalPass(MultipleUsage, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<IfStatementSyntax>() .First() .DescendantNodes() .OfType<BlockSyntax>() .Count() == 1); //must have added a block for multiple stements Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<BinaryExpressionSyntax>() .Where(expr => expr.OperatorToken.Kind() == SyntaxKind.BarBarToken) .Count() == 1); //must have added an or expression for multiple cases, //but not on the case containing the default statement }
public void InstanceUsage() { RoslynCompiler compiler = new RoslynCompiler(); var instance = compiler.Instance(); SyntaxTree tree; string text; //code extension instance .match<InstanceFoo>() .input (new InstanceConnector { Id = "input" }, dt: FooInput) .output(new InstanceConnector { Id = "output" }) .then(TransformFoo) .match<InstanceBar>() .input(new InstanceConnector { Id = "input" }) .output(new InstanceConnector { Id = "output" }, transform: BarOutput) .then(TransformBar) .then(TransformInstances); RoslynInstanceDocument doc = new RoslynInstanceDocument(InstanceTestParser); tree = compiler.CompileInstance(doc, out text); Assert.IsTrue(tree .GetRoot() .DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Count() == 1); //must have added a PropertyChanged handler }
public void JsonUsage() { RoslynCompiler compiler = new RoslynCompiler(); Entensions.XS.Json.Apply(compiler); SyntaxTree tree = null; string text = null; //usage var Usage = @" void main() { var expr = 20; var foo = json() { x : 3, y : [3, 4, 5], z : {a : 10, b : 20}, w : [ {a : 100, b : 200, c: [expr, expr + 1, expr + 2]}, {a : 150, b : 250, c: [expr, expr - 1, expr - 2]} ] } }"; tree = compiler.ApplySemanticalPass(Usage, out text); var anonymous = tree.GetRoot() .DescendantNodes() .OfType<AnonymousObjectCreationExpressionSyntax>() .First(); Assert.IsNotNull(anonymous); //must have created an anonymous object Assert.IsTrue(anonymous .Initializers .Count == 4); //4 members Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ImplicitArrayCreationExpressionSyntax>() .Count() == 4); //4 arrays }
protected override void doRun(Assembly asm, out dynamic client) { if (_assembly != asm) { _assembly = asm; Type type = _assembly.GetType("ExtensionPlugin"); Injector result = (Injector)type.InvokeMember("Create", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, null, null); if (result == null) throw new InvalidOperationException("Corrupted extension"); _compiler = new RoslynCompiler(); result.apply(_compiler); } client = new { debuggerDlg = "/App/Main/dialogs/dslDebugger.html", debuggerCtrl = "dslDebuggerCtrl", debuggerData = new { keywords = keywordString(_compiler.Environment().keywords()) } }; }
public void addDocument(string id, string contents, ICompilerInjector<SyntaxToken, SyntaxNode, SemanticModel> injector) { if (_documents .Where(doc => doc.Id == id) .Any()) throw new InvalidOperationException(); var ext = Path.GetExtension(id); var compiler = null as RoslynCompiler; var tool = null as ICompilationTool; var hash = 0; if (string.IsNullOrEmpty(ext)) { compiler = new RoslynCompiler(_environment, _scope); injector.apply(compiler); } else if (ext == ".cs") { addCSharpFile(id, contents); } else { if (_tools.TryGetValue(ext, out tool)) { var storage = _environment.storage(); hash = storage == null ? hash : storage.cachedId(id); } } var newDoc = new CompilationDocument { Id = id, Stage = CompilerStage.Started, Compiler = compiler, Tool = tool, Hash = hash }; if (compiler != null) { newDoc.Stage = CompilerStage.Started; newDoc.Document = new RoslynDocument(compiler.Scope, contents, id); var documentInjector = newDoc.Compiler as IDocumentInjector<SyntaxToken, SyntaxNode, SemanticModel>; documentInjector.apply(newDoc.Document); } else newDoc.Contents = contents; _documents.Add(newDoc); }
private void initCompiler() { _compiler = new RoslynCompiler(); Injector injector = new CompositeInjector(new[] { XSLang.Create(), demoExtensions() }); injector.apply(_compiler); }
public override void Add(Action <string> output = null, Action <string> error = null) { try { HashSet <FileInfo> codeFiles = new HashSet <FileInfo>(); HandlebarsTemplateRenderer renderer = new HandlebarsTemplateRenderer(new HandlebarsEmbeddedResources(GetType().Assembly)); RoslynCompiler compiler = new RoslynCompiler(); ShellGenConfig config = GetConfig(); Type baseType = null; if (!Arguments.Contains("generateBaseType")) { Message("Searching current AppDomain for specified base type ({0})", output, config.BaseTypeName); foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { baseType = FindType(assembly, config.BaseTypeNamespace, config.BaseTypeName); if (baseType != null) { Message("Found base type ({0}) in assembly ({1})", output, config.BaseTypeName, assembly.FullName); break; } } } CommandLineDelegatedClassModel model = CommandLineDelegatedClassModel.Create(config.ConcreteTypeName, config.BaseTypeName); model.Namespace = config.Namespace; SetConcreteModelProperties(model.ConcreteClass, config); ShellDescriptor descriptor = new ShellDescriptor(); if (baseType != null) { descriptor = new ShellDescriptor(baseType); model.SetMethods(baseType.GetMethods().Where(m => m.IsAbstract).Select(m => m.Name).ToArray()); } else { model.SetMethods(GetArgument("methodNames", "Please enter the method names to define on the base type (comma separated).") .DelimitSplit(",")); compiler.AddAssemblyReference(typeof(IRegisterArguments)); EnsureBaseType(config.BaseTypeName, config.WriteTo, renderer, model, codeFiles); } model.SetBaseTypeName(config.BaseTypeName); GenerateDelegator(config.WriteTo, model.DelegatorClass, renderer, codeFiles); GenerateConcreteType(config.WriteTo, config.ConcreteTypeName, renderer, model.ConcreteClass, codeFiles); byte[] delegatorAssembly = compiler.Compile(config.ConcreteTypeName, codeFiles.ToArray()); descriptor = ShellGenerationRepository.Save(descriptor); ShellWrapperAssembly wrapperAssembly = new ShellWrapperAssembly { ShellDescriptorKey = descriptor.Key(), Base64Assembly = delegatorAssembly.ToBase64() }; ShellGenerationRepository.Save(wrapperAssembly); } catch (Exception ex) { error(ex.Message); Exit(1); } }
public static void Apply(RoslynCompiler compiler, Scope scope) { Apply(compiler, new Options(), scope); }
public static void Default(RoslynCompiler compiler, Scope scope) { ConcurrentExtension.Apply(compiler, scope); }
private static CompilationContext Compile(FakeCompilerOptions compilerOptions, CompilationTarget target) { var cacheContextAccessor = new FakeCacheContextAccessor {Current = new CacheContext(null, (d) => { })}; var compilationProjectContext = new CompilationProjectContext( target, Directory.GetCurrentDirectory(), "project.json", TestTitle, TestDescription, TestCopyright, TestVersion, Version.Parse(TestAssemblyFileVersion), false, new CompilationFiles( new List<string> {}, new List<string> {}), compilerOptions); var compiler = new RoslynCompiler(null, cacheContextAccessor, new FakeNamedDependencyProvider(), null, null, null); var assembly = typeof (object).GetTypeInfo().Assembly; var metadataReference = new FakeMetadataReference() { MetadataReference = MetadataReference.CreateFromFile((string)assembly.GetType().GetProperty("Location").GetValue(assembly)) }; var compilationContext = compiler.CompileProject( compilationProjectContext, new List<IMetadataReference> { metadataReference }, new List<ISourceReference> {}, () => new List<ResourceDescriptor>(), "Debug"); return compilationContext; }
public void SyntacticalMatching() { RoslynCompiler compiler = new RoslynCompiler(); var syntax = compiler.Syntax(); //simple match syntax .match<ClassDeclarationSyntax>(c => !c.Members.OfType<ConstructorDeclarationSyntax>().Any()) .then(addConstructor); var tree = compiler.ApplySyntacticalPass("class foo { } class bar { bar() {} }"); Assert.IsTrue(tree .GetRoot() .DescendantNodes() .OfType<ConstructorDeclarationSyntax>() .Count() == 2); //must have added a constructor to "foo" //scope match & transform syntax .match<ClassDeclarationSyntax>(c => c.Identifier.ToString() == "foo") .descendants<MethodDeclarationSyntax>(named: "methods") .descendants<PropertyDeclarationSyntax>(prop => prop.Identifier.ToString().StartsWith("my"), named: "myProps") .then(syntax.transform() .replace("methods", method => ((MethodDeclarationSyntax)method) .WithIdentifier(CSharp.ParseToken("my" + ((MethodDeclarationSyntax)method).Identifier.ToString()))) .remove("myProps")); var scopeTree = compiler.ApplySyntacticalPass("class foo { public void Method() {} int myProp {get; set;} }"); Assert.IsTrue(scopeTree.ToString() == "class foo { public void myMethod() {} foo (){}}"); Assert.IsTrue(scopeTree .GetRoot() .DescendantNodes() .OfType<ConstructorDeclarationSyntax>() .Count() == 1); //must have added a constructor to "foo", since the syntax is the same }
private static Func <SyntaxNode, Scope, SyntaxNode> FunctionInjection(SyntaxNode toReplace, SyntaxList <StatementSyntax>?toInject) { return((node, scope) => { var scopeParameter = node .Ancestors() .OfType <MethodDeclarationSyntax>() .FirstOrDefault() ?.ParameterList .Parameters .LastOrDefault(); if (scopeParameter == null || scopeParameter.Type.ToString() != "__Scope") { //td: error return node; } var block = node as BlockSyntax; Debug.Assert(block != null); //td: error var variables = new List <StatementSyntax>(); foreach (var injectionStatement in toInject.Value) { var injectionDeclaration = (injectionStatement as LocalDeclarationStatementSyntax); if (injectionDeclaration == null) { //td: error continue; } if (injectionDeclaration.Declaration.Variables.Count != 1) { //td: error continue; } var injectionVariable = injectionDeclaration .Declaration .Variables .Single(); var type = injectionDeclaration.Declaration.Type; if (type.ToString() == "var") { //td: error continue; } var name = injectionVariable.Identifier; variables.Add(injectionDeclaration .WithDeclaration(injectionDeclaration.Declaration .WithVariables(CSharp.SeparatedList(new[] { injectionVariable.WithInitializer(CSharp.EqualsValueClause( Templates.ScopeGet.Get <ExpressionSyntax>( type, RoslynCompiler.Quoted(name.ToString())))) })))); } return block.WithStatements(CSharp.List( FunctionInjectionStatements(block, toReplace, variables))); }); }
public void FunctionUsage() { RoslynCompiler compiler = new RoslynCompiler(); Functions.Apply(compiler); //XSModule.Apply(compiler); //as lambda ExpressionSyntax exprFunction = compiler.CompileExpression("call(10, function(x, y) {})"); Assert.IsTrue(exprFunction.DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Any()); //as typed method string result = compiler.ApplyLexicalPass("class foo { public int function bar(int x) {}}"); Assert.IsTrue(result == "class foo { public int bar(int x) {}}"); SyntaxTree tree = null; string text = null; //as untyped method tree = compiler.ApplySemanticalPass("class foo { public function bar() {}}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .First() .ReturnType .ToString() == "void"); //must have added a return type //as code function tree = compiler.ApplySemanticalPass("class foo { public function bar() { function foobar(int x) {return 3;}}}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<ParenthesizedLambdaExpressionSyntax>() .Any()); //code functions replaced by a lambda declaration //as type, without return type tree = compiler.ApplySemanticalPass("class foo { void bar() { function<void, string> foobar; }}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .First() .Declaration .Type .ToString() == "Action<string>"); //must have changed the function type into an action (because of the void) //as type, with return type tree = compiler.ApplySemanticalPass("class foo { void bar() { function<int, string> foobar; }}", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .First() .Declaration .Type .ToString() == "Func<string,int>"); //must have changed the function type, moving the return type to the end }
public void BasicOperators() { RoslynCompiler compiler = new RoslynCompiler(); Extensions.Concurrent.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; tree = compiler.ApplySemanticalPass(@" concurrent class SomeClass { void main() { A | (B & C()) >> D(10); } public void A(); public void B(); public void F(); public void G(); private string C() { if (2 > 1) return ""SomeValue""; F & G; if (1 > 2) return ""SomeValue""; return ""SomeOtherValue""; } private int D(int v) { return v + 1; } }", out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType <MethodDeclarationSyntax>() .Count(method => new[] { "__concurrentmain", "__concurrentA", "__concurrentB", "__concurrentC", "__concurrentF", "__concurrentG", } .Contains(method .Identifier .ToString())) == 6); //must have created concurrent methods Assert.IsFalse(tree.GetRoot() .DescendantNodes() .OfType <MethodDeclarationSyntax>() .Any(method => method .Identifier .ToString() == "__concurrentD")); //but not for D }
public void RUsage() { RoslynCompiler compiler = new RoslynCompiler(); Excess.Extensions.R.Extension.Apply(compiler); SyntaxTree tree = null; string text = null; //usage var Vectors = @" void main() { R() { x <- c(10.4, 5.6, 3.1, 6.4, 21.7) y <- c(x, 0, x) z <- 2*x + y + 1 a <- x > 13 b <- x[!(is.na(x))] c <- x[-(1:5)] } }"; tree = compiler.ApplySemanticalPass(Vectors, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<VariableDeclarationSyntax>() .Count() == 6); //must have created 5 variables (x, y, z, a, b) Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<BinaryExpressionSyntax>() .Count() == 0); //must have replaced all operators var Sequences = @" void main() { R() { x <- 1:30 y <- 2*1:15 seq(-5, 5, by=.2) -> s3 s4 <- seq(length=51, from=-5, by=.2) s5 <- rep(x, times=5) } }"; tree = compiler.ApplySemanticalPass(Sequences, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<InvocationExpressionSyntax>() .Where(invocation => invocation.Expression.ToString().Contains("RR")) .Count() == 6); //must have replaced all operators var Statements = @" void main() { R() { x <- 1 y <- 2 z <- NA if (x == 1) 3 -> z if (y == 1) { 3 -> z } else { z1 <- 4 z <- z1 } while(z < 10) c(a, z) -> a for(i in z) { a <- c(a, i); } repeat { b <- a a <- c(b, b); if (length(a) > 10) break; } } }"; tree = compiler.ApplySemanticalPass(Statements, out text); Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<WhileStatementSyntax>() .Count() == 2); //must have replaced a while and a repeat Assert.IsTrue(tree.GetRoot() .DescendantNodes() .OfType<StatementSyntax>() .Where(ss => !(ss is ExpressionStatementSyntax || ss is LocalDeclarationStatementSyntax || ss is BlockSyntax)) .Count() == 7); //3 if, 2 whiles, a foreach, a break }
public void SyntacticalExtensions() { RoslynCompiler compiler = new RoslynCompiler(); var syntax = compiler.Syntax(); SyntaxTree tree; //code extension syntax .extension("codeExtension", ExtensionKind.Code, codeExtension); tree = compiler.ApplySyntacticalPass("class foo { void bar() {codeExtension() {bar();}} }"); Assert.IsTrue(tree .GetRoot() .DescendantNodes() .OfType<StatementSyntax>() .Count() == 5); //must have added a couple of statements tree = compiler.ApplySyntacticalPass("class foo { void bar() {var ce = codeExtension() {bar();}} }"); var localDeclStatement = tree .GetRoot() .DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .FirstOrDefault(); Assert.IsNotNull(localDeclStatement); Assert.AreEqual(localDeclStatement.ToString(), "var ce = bar(7);"); tree = compiler.ApplySyntacticalPass("class foo { void bar() {ce = codeExtension() {bar();}} }"); var assignmentStatement = tree .GetRoot() .DescendantNodes() .OfType<ExpressionStatementSyntax>() .FirstOrDefault(); Assert.IsNotNull(assignmentStatement); Assert.AreEqual(assignmentStatement.ToString(), "ce = bar(7);"); //member extension syntax .extension("memberExtension", ExtensionKind.Member, memberExtension); tree = compiler.ApplySyntacticalPass("class foo { memberExtension(param: \"foobar\") {int x = 3;} }"); var method = tree .GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .FirstOrDefault(); Assert.IsNotNull(method); Assert.AreEqual(method.ParameterList.Parameters.Count, 0); Assert.AreEqual(method.Body.Statements.Count, 3); //type extension syntax .extension("typeExtension", ExtensionKind.Type, typeExtension); tree = compiler.ApplySyntacticalPass("public typeExtension foo(param: \"foobar\") { bar(); }"); var @class = tree .GetRoot() .DescendantNodes() .OfType<ClassDeclarationSyntax>() .FirstOrDefault(); Assert.IsNotNull(@class); Assert.AreEqual(@class.Identifier.ToString(), "foo"); var classMethod = @class .Members .OfType<MethodDeclarationSyntax>() .FirstOrDefault(); Assert.IsNotNull(classMethod); Assert.IsTrue(classMethod .Body .DescendantNodes() .OfType<ExpressionStatementSyntax>() .Count() == 1); }
private static SyntaxNode ProcessMemberFunction(SyntaxNode node, Scope scope) { var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); if (node is MethodDeclarationSyntax) { var method = (node as MethodDeclarationSyntax) .AddParameterListParameters(CSharp .Parameter(Templates.ScopeToken) .WithType(Templates.ScopeType)); method = MemberFunctionModifiers(method); if (method.ReturnType.IsMissing) { method = method.WithReturnType(RoslynCompiler.@void); var calculateType = method.Body .DescendantNodes() .OfType <ReturnStatementSyntax>() .Any(); var isMember = method.Parent is TypeDeclarationSyntax; if (!isMember) { var service = scope.GetService <SyntaxToken, SyntaxNode, SemanticModel>(); return(service.MarkNode(Templates .NamespaceFunction .AddMembers((MemberDeclarationSyntax)document.change( method, LinkNamespaceFunction(calculateType))))); } return(calculateType ? document.change(method, CalculateReturnType) : method); } return(node); } //handle functions declared inside code blocks var statement = node .AncestorsAndSelf() .OfType <StatementSyntax>() .FirstOrDefault(); Debug.Assert(statement != null); //td: error, maybe? Debug.Assert(statement is ExpressionStatementSyntax); var invocation = (statement as ExpressionStatementSyntax) .Expression as InvocationExpressionSyntax; Debug.Assert(invocation != null); var function = invocation.Expression as IdentifierNameSyntax; Debug.Assert(function != null); BlockSyntax parent = statement.Parent as BlockSyntax; Debug.Assert(parent != null); //td: error, maybe? var body = RoslynCompiler.NextStatement(parent, statement) as BlockSyntax; if (body == null) { //td: error, function declaration must be followed by a block of code return(node); } //We are not allowed to modify parents, so schedule the removal of the code //And its insertion in the final lambda variable document.change(parent, RoslynCompiler.RemoveStatement(body)); document.change(statement, ProcessCodeFunction(function, body)); return(node); }