Example #1
0
 protected PropertyGeneratorBase(T type, Property property, ISymbolMap symbols, INamespaceSet namespaces)
 {
     Type       = type ?? throw new ArgumentNullException(nameof(type));
     Property   = property ?? throw new ArgumentNullException(nameof(property));
     Symbols    = symbols ?? throw new ArgumentNullException(nameof(symbols));
     Namespaces = namespaces ?? throw new ArgumentNullException(nameof(namespaces));
 }
Example #2
0
        public bool IsVaild(ISymbolMap symbol, out string message)
        {
            DebugSymbolMap debug = symbol as DebugSymbolMap;

            GItem[] vs  = m_items;
            Range[] map = m_nonterminals;

            int x = vs.Length;

            string result   = string.Empty;
            int    errorcnt = 1;

            while (--x >= 0)
            {
                GItem current = vs[x];

                ExpressInt expression = current.express;
                int        len        = expression.Length;

                while (--len >= 0)
                {
                    int now = expression[len];
                    if (!now.IsTerminal() && map[now.ToIndex()] == default)
                    {
                        result += $"[{errorcnt++}] Invalid Non-Terminal: " + (debug?.Get(now) ?? $"<{now}>") + Environment.NewLine;
                    }
                }
            }

            message = result;
            return(result.Length == 0);
        }
 protected MethodGeneratorBase(T type, Method method, ISymbolMap symbols, INamespaceSet namespaces)
 {
     Type       = type ?? throw new ArgumentNullException(nameof(type));
     Method     = method ?? throw new ArgumentNullException(nameof(method));
     Symbols    = symbols ?? throw new ArgumentNullException(nameof(symbols));
     Namespaces = namespaces ?? throw new ArgumentNullException(nameof(namespaces));
 }
        public static void MapTypeName(this ISymbolMap symbols, string fullyQualifiedName, string frameworkName, TypeKind kind)
        {
            var proxyName = $"{frameworkName}Proxy";

            switch (kind)
            {
            case TypeKind.Interface:
                var defaultName = frameworkName;

                symbols
                .GetInterfaceProxyName(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(proxyName);
                symbols
                .GetInterfaceDefaultName(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(defaultName);
                symbols
                .GetInterfaceProxyNameSyntaxToken(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseToken(proxyName));
                symbols
                .GetInterfaceDefaultNameSyntaxToken(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseToken(defaultName));
                symbols
                .GetInterfaceProxyNameSyntax(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseName(proxyName));
                symbols
                .GetInterfaceDefaultNameSyntax(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseName(defaultName));

                frameworkName = $"I{frameworkName}";
                break;

            case TypeKind.Class:
                symbols
                .GetAbstractClassProxyName(Arg.Is <ClassType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(proxyName);
                break;
            }

            symbols
            .GetName(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(frameworkName);
            symbols
            .GetName(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(frameworkName);
            symbols
            .GetNameSyntaxToken(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseToken(frameworkName));
            symbols
            .GetNameSyntaxToken(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseToken(frameworkName));
            symbols
            .GetNameSyntax(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseName(frameworkName));
            symbols
            .GetNameSyntax(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseName(frameworkName));
            symbols
            .GetTypeSyntax(Arg.Is <TypeReference>(t => t.FullyQualifiedName == fullyQualifiedName), false)
            .Returns(SF.ParseTypeName(frameworkName));
        }
Example #5
0
        public void Generate(string jsiiFile, string tarballPath, ISymbolMap symbols = null)
        {
            jsiiFile = jsiiFile ?? throw new ArgumentNullException(nameof(jsiiFile));
            symbols  = symbols ?? new SymbolMap();

            string   assemblyJson = _fileSystem.File.ReadAllText(jsiiFile);
            Assembly assembly     = JsonConvert.DeserializeObject <Assembly>(assemblyJson);

            symbols.Add(assembly);

            LoadDependencies(assembly, Path.GetDirectoryName(jsiiFile));

            string packageOutputRoot = Path.Combine(_outputRoot, assembly.GetNativeName());

            if (_fileSystem.Directory.Exists(packageOutputRoot))
            {
                _fileSystem.Directory.Delete(packageOutputRoot, true);
            }
            _fileSystem.Directory.CreateDirectory(packageOutputRoot);

            // On Windows, the full destination path including the filename is required.
            _fileSystem.File.Copy(tarballPath, Path.Combine(packageOutputRoot, Path.GetFileName(tarballPath)));
            _fileSystem.File.Copy(jsiiFile, Path.Combine(packageOutputRoot, Path.GetFileName(jsiiFile)));

            Save(packageOutputRoot, symbols, assembly, new FileInfo(tarballPath).Name, new FileInfo(jsiiFile).Name);

            void LoadDependencies(DependencyRoot dependencyRoot, string packageDirectory)
            {
                if (dependencyRoot.Dependencies == null)
                {
                    return;
                }

                foreach (KeyValuePair <string, PackageVersion> entry in dependencyRoot.Dependencies)
                {
                    string   depRoot     = ResolvePackage(entry.Key, packageDirectory);
                    string   depFile     = Path.Combine(depRoot, ".jsii");
                    string   depJson     = _fileSystem.File.ReadAllText(depFile);
                    Assembly depAssembly = JsonConvert.DeserializeObject <Assembly>(depJson);
                    symbols.Add(depAssembly);
                    LoadDependencies(depAssembly, depRoot);
                }

                string ResolvePackage(string packageName, string directory)
                {
                    if (string.IsNullOrEmpty(directory))
                    {
                        throw new FileNotFoundException($"Could not resolve package named {packageName}");
                    }
                    string candidate = Path.Combine(directory, "node_modules", packageName);

                    if (_fileSystem.Directory.Exists(candidate))
                    {
                        return(candidate);
                    }
                    return(ResolvePackage(packageName, Path.GetDirectoryName(directory)));
                }
            }
        }
 public AbstractClassProxyGenerator(string package, ClassType type, ISymbolMap symbols,
                                    INamespaceSet namespaces = null)
     : base(package, type, symbols, namespaces)
 {
     if (!type.IsAbstract)
     {
         throw new ArgumentException("Class type must be abstract.", nameof(type));
     }
 }
Example #7
0
        protected TypeGeneratorBase(string package, T type, ISymbolMap symbols, INamespaceSet namespaces)
        {
            Package = package ?? throw new ArgumentNullException(nameof(package));

            Type    = type ?? throw new ArgumentNullException(nameof(type));
            Symbols = symbols ?? throw new ArgumentNullException(nameof(symbols));

            NameSyntax namespaceSyntax = Symbols.GetNamespaceSyntax(Type);

            Namespaces = namespaces ?? new NamespaceSet(Symbols, namespaceSyntax);
        }
Example #8
0
        public NamespaceSet(ISymbolMap symbols, NameSyntax currentNamespace)
        {
            _symbols          = symbols ?? throw new ArgumentNullException(nameof(symbols));
            _currentNamespace = currentNamespace ?? throw new ArgumentNullException(nameof(currentNamespace));

            _referencedNamespaces = new HashSet <NameSyntax>
                                    (
                new[] { SF.ParseName("Amazon.JSII.Runtime.Deputy") },
                new DelegateComparer <NameSyntax, string>(nameSyntax => nameSyntax.ToString())
                                    );
        }
 public static void MapTypeToNamespace(this ISymbolMap symbols, string fullyQualifiedName, string frameworkNamespace)
 {
     symbols
     .GetNamespace(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(frameworkNamespace);
     symbols
     .GetNamespaceSyntaxToken(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(SF.ParseToken(frameworkNamespace));
     symbols
     .GetNamespaceSyntax(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(SF.ParseName(frameworkNamespace));
 }
 public static void MapNamespace(this ISymbolMap symbols, string jsiiNamespace, string frameworkNamespace)
 {
     symbols
     .GetNamespace(Arg.Is <Type>(t => t.QualifiedNamespace == jsiiNamespace))
     .Returns(frameworkNamespace);
     symbols
     .GetNamespaceSyntaxToken(Arg.Is <Type>(t => t.QualifiedNamespace == jsiiNamespace))
     .Returns(SF.ParseToken(frameworkNamespace));
     symbols
     .GetNamespaceSyntax(Arg.Is <Type>(t => t.QualifiedNamespace == jsiiNamespace))
     .Returns(SF.ParseName(frameworkNamespace));
 }
Example #11
0
        public static void MapTypeName(this ISymbolMap symbols, string fullyQualifiedName, string frameworkName, TypeKind kind)
        {
            if (kind == TypeKind.Interface)
            {
                string proxyName   = $"{frameworkName}Proxy";
                string defaultName = frameworkName;

                symbols
                .GetInterfaceProxyName(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(proxyName);
                symbols
                .GetInterfaceDefaultName(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(defaultName);
                symbols
                .GetInterfaceProxyNameSyntaxToken(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseToken(proxyName));
                symbols
                .GetInterfaceDefaultNameSyntaxToken(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseToken(defaultName));
                symbols
                .GetInterfaceProxyNameSyntax(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseName(proxyName));
                symbols
                .GetInterfaceDefaultNameSyntax(Arg.Is <InterfaceType>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
                .Returns(SF.ParseName(defaultName));

                frameworkName = $"I{frameworkName}";
            }

            symbols
            .GetName(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(frameworkName);
            symbols
            .GetName(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(frameworkName);
            symbols
            .GetNameSyntaxToken(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseToken(frameworkName));
            symbols
            .GetNameSyntaxToken(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseToken(frameworkName));
            symbols
            .GetNameSyntax(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseName(frameworkName));
            symbols
            .GetNameSyntax(Arg.Is <string>(fqn => fqn == fullyQualifiedName), disambiguate: Arg.Any <bool>())
            .Returns(SF.ParseName(frameworkName));
            symbols
            .GetTypeSyntax(Arg.Is <TypeReference>(t => t.FullyQualifiedName == fullyQualifiedName))
            .Returns(SF.ParseTypeName(frameworkName));
        }
 public static void MapPropertyName(this ISymbolMap symbols, string ownerFullyQualifiedName, string jsiiName, string frameworkName)
 {
     symbols.GetName(
         Arg.Is <Type>(t => t.FullyQualifiedName == ownerFullyQualifiedName),
         Arg.Is <Property>(p => p.Name == jsiiName)
         ).Returns(frameworkName);
     symbols.GetNameSyntaxToken(
         Arg.Is <Type>(t => t.FullyQualifiedName == ownerFullyQualifiedName),
         Arg.Is <Property>(p => p.Name == jsiiName)
         ).Returns(SF.ParseToken(frameworkName));
     symbols.GetNameSyntax(
         Arg.Is <Type>(t => t.FullyQualifiedName == ownerFullyQualifiedName),
         Arg.Is <Property>(p => p.Name == jsiiName)
         ).Returns(SF.ParseName(frameworkName));
 }
        public static void MapAssemblyName(this ISymbolMap symbols, string jsiiName, string frameworkName)
        {
            symbols
            .GetName(Arg.Is <Assembly>(a => a.Name == jsiiName))
            .Returns(frameworkName);
            symbols
            .GetNameSyntaxToken(Arg.Is <Assembly>(a => a.Name == jsiiName))
            .Returns(SF.ParseToken(frameworkName));
            symbols
            .GetNameSyntax(Arg.Is <Assembly>(a => a.Name == jsiiName))
            .Returns(SF.ParseName(frameworkName));

            symbols
            .GetAssemblyName(Arg.Is <string>(n => n == jsiiName))
            .Returns(frameworkName);
        }
Example #14
0
        public static bool AnyAncestor(this ClassType classType, ISymbolMap symbols, Func <ClassType, bool> predicate)
        {
            var current = classType.Base;

            while (current != null)
            {
                ClassType currentType = (ClassType)symbols.GetTypeFromFullyQualifiedName(current);

                if (predicate(currentType))
                {
                    return(true);
                }

                current = currentType.Base;
            }

            return(false);
        }
Example #15
0
        static IEnumerable <T> GetAllCore <T>(this InterfaceType @interface, ISymbolMap symbols, Func <InterfaceType, IEnumerable <T> > selector)
        {
            foreach (T member in selector(@interface) ?? Enumerable.Empty <T>())
            {
                yield return(member);
            }

            if (@interface.Interfaces != null)
            {
                var baseMembers = @interface.Interfaces
                                  .Select(r => symbols.GetTypeFromFullyQualifiedName(r) as InterfaceType)
                                  .SelectMany(i => GetAllCore(i, symbols, selector));

                foreach (T member in baseMembers)
                {
                    yield return(member);
                }
            }
        }
 public static void MapTypeToPackage(this ISymbolMap symbols, string fullyQualifiedName, string package)
 {
     symbols
     .GetPackage(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName))
     .Returns(package);
     symbols
     .GetPackage(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(package);
     symbols
     .GetPackageSyntaxToken(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName))
     .Returns(SF.ParseToken(package));
     symbols
     .GetPackageSyntaxToken(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(SF.ParseToken(package));
     symbols
     .GetPackageSyntax(Arg.Is <Type>(t => t.FullyQualifiedName == fullyQualifiedName))
     .Returns(SF.ParseName(package));
     symbols
     .GetPackageSyntax(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(SF.ParseName(package));
 }
Example #17
0
        public InterfaceProxyMethodGenerator(InterfaceType type, Method method, ISymbolMap symbols, INamespaceSet namespaces)
            : base(type, method, symbols, namespaces)
        {
            if (!method.IsAbstract)
            {
                throw new ArgumentException("Interface methods must be abstract", nameof(method));
            }

            if (method.IsProtected)
            {
                throw new ArgumentException("Protected methods are not allowed on interfaces", nameof(method));
            }

            if (method.IsStatic)
            {
                throw new ArgumentException(
                          $"Method {type.Name}.{method.Name} is marked as static, but interfaces must not contain static members.",
                          nameof(method)
                          );
            }
        }
Example #18
0
        public InterfacePropertyGenerator(InterfaceType type, Property property, ISymbolMap symbols, INamespaceSet namespaces)
            : base(type, property, symbols, namespaces)
        {
            if (property.IsAbstract == true)
            {
                throw new ArgumentException("Abstract properties are not allowed on interfaces", nameof(property));
            }

            if (property.IsProtected == true)
            {
                throw new ArgumentException("Protected properties are not allowed on interfaces", nameof(property));
            }

            if (property.IsStatic())
            {
                throw new ArgumentException(
                          $"Property {type.Name}.{property.Name} is marked as static, but interfaces must not contain static members.",
                          nameof(property)
                          );
            }
        }
Example #19
0
        void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName)
        {
            if (assembly.Docs != null)
            {
                // TODO: Use Microsoft.Extensions.Logging instead of Console.Error.
                Console.Error.WriteLine($"Warning: Ignoring documentation comment on assembly {assembly.Name}. Assembly-level documentation comments are not supported for .NET");
            }

            SaveProjectFile();
            SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName);
            SaveDependencyAnchorFile();

            foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>())
            {
                SaveType(type);
            }

            void SaveProjectFile()
            {
                XElement project =
                    new XElement("Project",
                                 new XAttribute("Sdk", "Microsoft.NET.Sdk"),
                                 new XElement("PropertyGroup", assembly.GetMsBuildProperties()),
                                 new XElement("ItemGroup",
                                              new XElement("EmbeddedResource",
                                                           new XAttribute("Include", tarballFileName)
                                                           )
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("PackageReference",
                                                           new XAttribute("Include", "Amazon.JSII.Runtime"),
                                                           new XAttribute("Version", JsiiVersion.Version)
                                                           ),
                                              GetDependencies()
                                              .Distinct()
                                              .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.GetDecoratedVersion() })
                                              .Select(d =>
                                                      new XElement("PackageReference",
                                                                   new XAttribute("Include", d.Package),
                                                                   new XAttribute("Version", d.Version)
                                                                   )
                                                      )
                                              )
                                 );

                if (!_fileSystem.Directory.Exists(packageOutputRoot))
                {
                    _fileSystem.Directory.CreateDirectory(packageOutputRoot);
                }

                // Save to StringBuilder instead of directly to path, so that we can
                // redirect the output through the filesystem shim. Project files are
                // small, so this shouldn't be a memory hog.
                StringBuilder     builder  = new StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    // Visual Studio omits the XML declaration when creating project files, so we do too.
                    OmitXmlDeclaration = true,
                    // Visual Studio indents project files (they are often edited by hand), so we do too.
                    Indent = true,
                };

                using (XmlWriter writer = XmlWriter.Create(builder, settings))
                {
                    project.Save(writer);
                }

                string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativePackageId()}.csproj");

                _fileSystem.File.WriteAllText(csProjPath, builder.ToString());

                IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies()
                {
                    foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly))
                    {
                        yield return(dependency);
                    }

                    IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root)
                    {
                        if (root.Dependencies == null)
                        {
                            yield break;
                        }
                        foreach (var kvp in root.Dependencies)
                        {
                            yield return(kvp);

                            foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value))
                            {
                                yield return(dependency);
                            }
                        }
                    }
                }
            }

            void SaveDependencyAnchorFile()
            {
                string anchorNamespace = $"{assembly.GetNativeNamespace()}.Internal.DependencyResolution";
                var    syntaxTree      = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List <UsingDirectiveSyntax>(),
                        SF.List <AttributeListSyntax>(),
                        SF.List <MemberDeclarationSyntax>(new[] {
                    SF.NamespaceDeclaration(
                        SF.IdentifierName(anchorNamespace),
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List <UsingDirectiveSyntax>(),
                        SF.List(new MemberDeclarationSyntax[] { GenerateDependencyAnchor() })
                        )
                })
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string directory = GetNamespaceDirectory(packageOutputRoot, @anchorNamespace);

                SaveSyntaxTree(directory, "Anchor.cs", syntaxTree);

                ClassDeclarationSyntax GenerateDependencyAnchor()
                {
                    return(SF.ClassDeclaration(
                               SF.List <AttributeListSyntax>(),
                               SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)),
                               SF.Identifier("Anchor"),
                               null,
                               null,
                               SF.List <TypeParameterConstraintClauseSyntax>(),
                               SF.List(new MemberDeclarationSyntax[] {
                        SF.ConstructorDeclaration(
                            SF.List <AttributeListSyntax>(),
                            SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)),
                            SF.Identifier("Anchor"),
                            SF.ParameterList(SF.SeparatedList <ParameterSyntax>()),
                            null,
                            SF.Block(SF.List(GenerateAnchorReferences())),
                            null
                            )
                    })
                               ));

                    IEnumerable <StatementSyntax> GenerateAnchorReferences()
                    {
                        return(assembly.Dependencies?.Keys
                               .Select(k => assembly.GetNativeNamespace(k))
                               .Select(n => $"{n}.Internal.DependencyResolution.Anchor")
                               .Select(t => SF.ExpressionStatement(SF.ObjectCreationExpression(
                                                                       SF.Token(SyntaxKind.NewKeyword),
                                                                       SF.ParseTypeName(t),
                                                                       SF.ArgumentList(SF.SeparatedList <ArgumentSyntax>()),
                                                                       null
                                                                       ))) ?? Enumerable.Empty <StatementSyntax>());
                    }
                }
            }

            void SaveAssemblyInfo(string name, string version, string tarball)
            {
                SyntaxTree assemblyInfo = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List(new[] {
                    SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy"))
                }),
                        SF.List(new[] {
                    SF.AttributeList(
                        SF.AttributeTargetSpecifier(
                            SF.Identifier("assembly"),
                            SF.Token(SyntaxKind.ColonToken)
                            ),
                        SF.SeparatedList(new[] {
                        SF.Attribute(
                            SF.ParseName("JsiiAssembly"),
                            SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})")
                            )
                    })
                        )
                }),
                        SF.List <MemberDeclarationSyntax>()
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs");

                _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString());
            }

            void SaveType(Type type)
            {
                string @namespace = symbols.GetNamespace(type);
                string directory  = GetNamespaceDirectory(packageOutputRoot, @namespace);

                switch (type.Kind)
                {
                case TypeKind.Class:
                {
                    var classType = (ClassType)type;

                    if (classType.IsAbstract)
                    {
                        SaveTypeFile($"{symbols.GetAbstractClassProxyName(classType)}.cs",
                                     new AbstractClassProxyGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
                    }

                    SaveTypeFile($"{symbols.GetName(type)}.cs",
                                 new ClassGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
                    return;
                }

                case TypeKind.Enum:
                {
                    SaveTypeFile($"{symbols.GetName(type)}.cs",
                                 new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree());
                    return;
                }

                case TypeKind.Interface:
                {
                    InterfaceType interfaceType = (InterfaceType)type;

                    SaveTypeFile($"{symbols.GetName(interfaceType)}.cs",
                                 new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs",
                                 new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());

                    if (interfaceType.IsDataType)
                    {
                        SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs",
                                     new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols)
                                     .CreateSyntaxTree());
                    }

                    return;
                }

                default:
                {
                    throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type));
                }
                }

                void SaveTypeFile(string filename, SyntaxTree syntaxTree)
                {
                    SaveSyntaxTree(directory, filename, syntaxTree);
                }
            }

            void SaveSyntaxTree(string directory, string filename, SyntaxTree syntaxTree)
            {
                if (!_fileSystem.Directory.Exists(directory))
                {
                    _fileSystem.Directory.CreateDirectory(directory);
                }

                _fileSystem.File.WriteAllText(
                    Path.Combine(directory, filename),
                    syntaxTree.ToString()
                    );
            }
        }
Example #20
0
        public static IEnumerable <Property> GetAllProperties(this InterfaceType @interface, ISymbolMap symbols)
        {
            @interface = @interface ?? throw new ArgumentNullException(nameof(@interface));
            symbols    = symbols ?? throw new ArgumentNullException(nameof(symbols));

            return(GetAllCore(@interface, symbols, i => i.Properties));
        }
 public static void MapFullyQualifiedNameToType(this ISymbolMap symbols, string fullyQualifiedName, Type type)
 {
     symbols
     .GetTypeFromFullyQualifiedName(Arg.Is <string>(n => n == fullyQualifiedName))
     .Returns(type);
 }
Example #22
0
 public InterfaceGenerator(string package, InterfaceType type, ISymbolMap symbols, INamespaceSet namespaces = null)
     : base(package, type, symbols, namespaces)
 {
 }
Example #23
0
        public static ParameterListSyntax GetParameterListSyntax(this Method method, INamespaceSet namespaces, ISymbolMap symbols)
        {
            method     = method ?? throw new ArgumentNullException(nameof(method));
            namespaces = namespaces ?? throw new ArgumentNullException(nameof(namespaces));
            symbols    = symbols ?? throw new ArgumentNullException(nameof(symbols));

            return(SF.ParameterList(SF.SeparatedList(GetParameters())));

            IEnumerable <ParameterSyntax> GetParameters()
            {
                if (method.Parameters == null)
                {
                    yield break;
                }

                foreach (Parameter parameter in method.Parameters)
                {
                    namespaces.Add(parameter.Type);

                    yield return(SF.Parameter(
                                     SF.List <AttributeListSyntax>(),
                                     SF.TokenList(),
                                     symbols.GetTypeSyntax(parameter.Type),
                                     symbols.GetNameSyntaxToken(parameter),
                                     null
                                     ));
                }
            }
        }
 public ClassPropertyGenerator(ClassType type, Property property, ISymbolMap symbols, INamespaceSet namespaces)
     : base(type, property, symbols, namespaces)
 {
 }
Example #25
0
 public ClassMethodGenerator(ClassType type, Method method, ISymbolMap symbols, INamespaceSet namespaces)
     : base(type, method, symbols, namespaces)
 {
 }
Example #26
0
 public EnumGenerator(string package, EnumType type, ISymbolMap symbols, INamespaceSet namespaces = null)
     : base(package, type, symbols, namespaces)
 {
 }
 public static void MapParameterName(this ISymbolMap symbols, string jsiiName, string frameworkName)
 {
     symbols.GetName(Arg.Is <Parameter>(t => t.Name == jsiiName)).Returns(frameworkName);
     symbols.GetNameSyntaxToken(Arg.Is <Parameter>(t => t.Name == jsiiName)).Returns(SF.ParseToken(frameworkName));
     symbols.GetNameSyntax(Arg.Is <Parameter>(t => t.Name == jsiiName)).Returns(SF.ParseName(frameworkName));
 }
Example #28
0
 protected TypeProxyGeneratorBase(string package, T type, ISymbolMap symbols, INamespaceSet namespaces)
     : base(package, type, symbols, namespaces)
 {
 }
Example #29
0
        void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName)
        {
            if (assembly.Docs != null)
            {
                // TODO: Use Microsoft.Extensions.Logging instead of Console.Error.
                Console.Error.WriteLine("Warning: Ignoring documentation comment on assembly ${assembly.Name}. Assembly-level documentation comments are not supported for .NET");
            }

            SaveProjectFile();
            SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName);

            foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>())
            {
                SaveType(type);
            }

            void SaveProjectFile()
            {
                XElement project =
                    new XElement("Project",
                                 new XAttribute("Sdk", "Microsoft.NET.Sdk"),
                                 new XElement("PropertyGroup",
                                              new XElement("TargetFramework", "netstandard2.0"),
                                              new XElement("GeneratePackageOnBuild", true),
                                              new XElement("Authors", _authors),
                                              new XElement("Company", _company),
                                              new XElement("PackageVersion", assembly.Version)
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("EmbeddedResource",
                                                           new XAttribute("Include", tarballFileName)
                                                           )
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("PackageReference",
                                                           new XAttribute("Include", "Amazon.JSII.Runtime"),
                                                           new XAttribute("Version", JsiiVersion.Version)
                                                           ),
                                              GetDependencies()
                                              .Distinct()
                                              .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.Version })
                                              .Select(d =>
                                                      new XElement("PackageReference",
                                                                   new XAttribute("Include", d.Package),
                                                                   new XAttribute("Version", d.Version)
                                                                   )
                                                      )
                                              )
                                 );

                if (!_fileSystem.Directory.Exists(packageOutputRoot))
                {
                    _fileSystem.Directory.CreateDirectory(packageOutputRoot);
                }

                // Save to StringBuilder instead of directly to path, so that we can
                // redirect the output through the filesystem shim. Project files are
                // small, so this shouldn't be a memory hog.
                StringBuilder     builder  = new StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    // Visual Studio omits the XML declaration when creating project files, so we do too.
                    OmitXmlDeclaration = true,
                    // Visual Studio indents project files (they are often edited by hand), so we do too.
                    Indent = true,
                };

                using (XmlWriter writer = XmlWriter.Create(builder, settings))
                {
                    project.Save(writer);
                }

                string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativeName()}.csproj");

                _fileSystem.File.WriteAllText(csProjPath, builder.ToString());

                IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies()
                {
                    foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly))
                    {
                        yield return(dependency);
                    }

                    IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root)
                    {
                        if (root.Dependencies == null)
                        {
                            yield break;
                        }
                        foreach (var kvp in root.Dependencies)
                        {
                            yield return(kvp);

                            foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value))
                            {
                                yield return(dependency);
                            }
                        }
                    }
                }
            }

            void SaveAssemblyInfo(string name, string version, string tarball)
            {
                SyntaxTree assemblyInfo = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List(new[] {
                    SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy"))
                }),
                        SF.List(new[] {
                    SF.AttributeList(
                        SF.AttributeTargetSpecifier(
                            SF.Identifier("assembly"),
                            SF.Token(SyntaxKind.ColonToken)
                            ),
                        SF.SeparatedList(new[] {
                        SF.Attribute(
                            SF.ParseName("JsiiAssembly"),
                            SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})")
                            )
                    })
                        )
                }),
                        SF.List <MemberDeclarationSyntax>()
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs");

                _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString());
            }

            void SaveType(Type type)
            {
                string packageName = Path.GetFileName(packageOutputRoot);
                string @namespace  = symbols.GetNamespace(type);

                if (@namespace.StartsWith(packageName))
                {
                    @namespace = @namespace.Substring(packageName.Length).TrimStart('.');
                }

                string directory = Path.Combine(packageOutputRoot, Path.Combine(@namespace.Split('.')));

                switch (type.Kind)
                {
                case TypeKind.Class:
                    SaveTypeFile($"{symbols.GetName(type)}.cs", new ClassGenerator(assembly.Name, (ClassType)type, symbols).CreateSyntaxTree());
                    return;

                case TypeKind.Enum:
                    SaveTypeFile($"{symbols.GetName(type)}.cs", new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree());
                    return;

                case TypeKind.Interface:
                    InterfaceType interfaceType = (InterfaceType)type;

                    SaveTypeFile($"{symbols.GetName(interfaceType)}.cs", new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs", new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());

                    if (interfaceType.IsDataType == true)
                    {
                        SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs", new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    }

                    return;

                default:
                    throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type));
                }

                void SaveTypeFile(string filename, SyntaxTree syntaxTree)
                {
                    if (!_fileSystem.Directory.Exists(directory))
                    {
                        _fileSystem.Directory.CreateDirectory(directory);
                    }

                    _fileSystem.File.WriteAllText(
                        Path.Combine(directory, filename),
                        syntaxTree.ToString()
                        );
                }
            }
        }
 public MethodDocCommentGenerator(Callable documentable, ISymbolMap symbols) : base(documentable)
 {
     _symbols = symbols ?? throw new ArgumentNullException(nameof(symbols));
 }