示例#1
0
        public VisualScriptCompilerResult Compile(AssetItem assetItem)
        {
            var generatedAbsolutePath = assetItem.GetGeneratedAbsolutePath().ToWindowsPath();

            var compilerOptions = new VisualScriptCompilerOptions
            {
                FilePath = generatedAbsolutePath,
                Class    = Path.GetFileNameWithoutExtension(generatedAbsolutePath),
            };

            // Try to get root namespace from containing project
            // Since ProjectReference.Location is sometimes absolute sometimes not, we have to handle both case
            // TODO: ideally we should stop converting those and handle this automatically in a custom Yaml serializer?
            var sourceProjectAbsolute = assetItem.SourceProject;
            var sourceProjectRelative = sourceProjectAbsolute?.MakeRelative(assetItem.Package.FullPath.GetFullDirectory());
            var projectReference      = assetItem.Package.Profiles.SelectMany(x => x.ProjectReferences).FirstOrDefault(x => x.Location == (x.Location.IsAbsolute ? sourceProjectAbsolute : sourceProjectRelative));

            if (projectReference != null)
            {
                // Find root namespace from project
                var rootNamespace = projectReference?.RootNamespace ?? projectReference.Location.GetFileName();
                if (rootNamespace != null)
                {
                    compilerOptions.DefaultNamespace = rootNamespace;

                    // Complete namespace with "Include" folder (if not empty)
                    var projectInclude = assetItem.GetProjectInclude();
                    if (projectInclude != null)
                    {
                        var lastDirectorySeparator = projectInclude.LastIndexOf('\\');
                        if (lastDirectorySeparator != -1)
                        {
                            var projectIncludeFolder = projectInclude.Substring(0, lastDirectorySeparator);
                            compilerOptions.DefaultNamespace += '.' + projectIncludeFolder.Replace('\\', '.');
                        }
                    }
                }
            }

            var compilerResult = VisualScriptCompiler.Generate(this, compilerOptions);

            return(compilerResult);
        }
示例#2
0
        public static VisualScriptCompilerResult Generate(VisualScriptAsset visualScriptAsset, VisualScriptCompilerOptions options)
        {
            var result = new VisualScriptCompilerResult();

            var members   = new List <MemberDeclarationSyntax>();
            var className = options.Class;

            // Generate variables
            foreach (var variable in visualScriptAsset.Properties)
            {
                var variableType = variable.Type;
                if (variableType == null)
                {
                    result.Error($"Variable {variable.Name} has no type, using \"object\" instead.");
                    variableType = "object";
                }

                var field =
                    FieldDeclaration(
                        VariableDeclaration(
                            ParseTypeName(variableType))
                        .WithVariables(
                            SingletonSeparatedList(
                                VariableDeclarator(
                                    Identifier(variable.Name)))))
                    .WithModifiers(
                        TokenList(
                            Token(SyntaxKind.PublicKeyword)));

                members.Add(field);
            }

            // Process each function
            foreach (var method in visualScriptAsset.Methods)
            {
                var functionStartBlock = method.Blocks.Values.OfType <FunctionStartBlock>().FirstOrDefault();
                if (functionStartBlock == null)
                {
                    continue;
                }

                var context = new VisualScriptCompilerContext(visualScriptAsset, method, result);

                context.ProcessEntryBlock(functionStartBlock);

                var methodModifiers = new SyntaxTokenList();
                methodModifiers = ConvertAccessibility(methodModifiers, method.Accessibility);
                methodModifiers = ConvertVirtualModifier(methodModifiers, method.VirtualModifier);
                if (method.IsStatic)
                {
                    methodModifiers = methodModifiers.Add(Token(SyntaxKind.StaticKeyword));
                }

                var parameters = new List <SyntaxNodeOrToken>();
                foreach (var parameter in method.Parameters)
                {
                    if (parameters.Count > 0)
                    {
                        parameters.Add(Token(SyntaxKind.CommaToken));
                    }

                    parameters.Add(
                        Parameter(Identifier(parameter.Name))
                        .WithModifiers(ConvertRefKind(parameter.RefKind))
                        .WithType(ParseTypeName(parameter.Type)));
                }

                // Generate method
                var methodDeclaration =
                    MethodDeclaration(
                        method.ReturnType == "void" ? PredefinedType(Token(SyntaxKind.VoidKeyword)) : ParseTypeName(method.ReturnType),
                        Identifier(method.Name))
                    .WithModifiers(methodModifiers)
                    .WithParameterList(ParameterList(
                                           SeparatedList <ParameterSyntax>(parameters)))
                    .WithBody(
                        Block(context.Blocks.SelectMany(x => x.Statements)))
                    .WithAdditionalAnnotations(GenerateAnnotation(method));

                members.Add(methodDeclaration);
            }

            // Generate class
            var classModifiers = new SyntaxTokenList();

            classModifiers = ConvertAccessibility(classModifiers, visualScriptAsset.Accessibility).Add(Token(SyntaxKind.PartialKeyword));
            if (visualScriptAsset.IsStatic)
            {
                classModifiers = classModifiers.Add(Token(SyntaxKind.StaticKeyword));
            }

            var @class =
                ClassDeclaration(className)
                .WithMembers(List(members))
                .WithModifiers(classModifiers);

            if (visualScriptAsset.BaseType != null)
            {
                @class = @class.WithBaseList(BaseList(SingletonSeparatedList <BaseTypeSyntax>(SimpleBaseType(IdentifierName(visualScriptAsset.BaseType)))));
            }

            // Generate namespace around class (if any)
            MemberDeclarationSyntax namespaceOrClass = @class;
            var @namespace = !string.IsNullOrEmpty(visualScriptAsset.Namespace) ? visualScriptAsset.Namespace : options.DefaultNamespace;

            if (@namespace != null)
            {
                namespaceOrClass =
                    NamespaceDeclaration(
                        IdentifierName(@namespace))
                    .WithMembers(
                        SingletonList <MemberDeclarationSyntax>(@class));
            }

            // Generate compilation unit
            var compilationUnit =
                CompilationUnit()
                .WithUsings(
                    List(visualScriptAsset.UsingDirectives.Select(x =>
                                                                  UsingDirective(
                                                                      IdentifierName(x)))))
                .WithMembers(
                    SingletonList(namespaceOrClass))
                .NormalizeWhitespace();

            // Generate actual source code
            result.GeneratedSource = compilationUnit.ToFullString();
            result.SyntaxTree      = SyntaxTree(compilationUnit, path: options.FilePath ?? string.Empty);

            return(result);
        }