Пример #1
0
        private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScriptCoreAssembly, bool inApplicationAssembly,
                                ScriptReference dependency, TypeSymbol outerType = null)
        {
            if (!type.IsPublic && !type.IsNestedPublic && dependency?.InternalesVisible == false)
            {
                return;
            }

            if (inScriptCoreAssembly && MetadataHelpers.ShouldImportScriptCoreType(type) == false)
            {
                return;
            }

            string name          = outerType is TypeSymbol ? $"{outerType.Name}${type.Name}" : type.Name;
            string namespaceName = outerType is TypeSymbol ? outerType.Namespace : type.Namespace;

            bool   dummy;
            string scriptName = MetadataHelpers.GetScriptName(type, out dummy, out dummy);

            NamespaceSymbol namespaceSymbol = symbols.GetNamespace(namespaceName);
            TypeSymbol      typeSymbol      = null;

            if (type.IsInterface)
            {
                typeSymbol = new InterfaceSymbol(name, namespaceSymbol);
            }
            else if (MetadataHelpers.IsEnum(type))
            {
                // NOTE: We don't care about the flags bit on imported enums
                //       because this is only consumed by the generation logic.
                typeSymbol = new EnumerationSymbol(name, namespaceSymbol, /* flags */ false);

                if (MetadataHelpers.ShouldUseEnumNames(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNamedValues();
                }
                else if (MetadataHelpers.ShouldUseEnumValues(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNumericValues();
                }
            }
            else if (MetadataHelpers.IsDelegate(type))
            {
                typeSymbol = new DelegateSymbol(name, namespaceSymbol);
                typeSymbol.SetTransformedName("Function");
                typeSymbol.SetIgnoreGenerics();
                typeSymbol.SetIgnoreNamespace();
            }
            else
            {
                if (MetadataHelpers.ShouldTreatAsRecordType(type))
                {
                    typeSymbol = new RecordSymbol(name, namespaceSymbol);
                    typeSymbol.SetTransformedName(nameof(Object));
                }
                else
                {
                    typeSymbol = new ClassSymbol(name, namespaceSymbol);
                }
            }

            if (typeSymbol != null)
            {
                if (MetadataHelpers.ShouldIgnoreGenerics(type, out var useGenericName))
                {
                    typeSymbol.SetIgnoreGenerics(useGenericName);
                }

                if (type.HasGenericParameters)
                {
                    List <GenericParameterSymbol> genericArguments = new List <GenericParameterSymbol>();

                    foreach (GenericParameter genericParameter in type.GenericParameters)
                    {
                        GenericParameterSymbol arg =
                            new GenericParameterSymbol(genericParameter.Position, genericParameter.Name, true, symbols.GlobalNamespace);

                        genericArguments.Add(arg);
                    }

                    typeSymbol.AddGenericParameters(genericArguments);
                }

                string dependencyName = MetadataHelpers.GetScriptDependencyName(type, out string dependencyIdentifier);

                if (dependencyName != null)
                {
                    dependency = ScriptReferenceProvider.Instance.GetReference(dependencyName, dependencyIdentifier);
                }

                if (!inApplicationAssembly)
                {
                    typeSymbol.SetImported(dependency);
                }

                typeSymbol.SetMetadataToken(type, inScriptCoreAssembly);

                bool ignoreNamespace = MetadataHelpers.ShouldIgnoreNamespace(type);

                if (ignoreNamespace || dependency == null || string.IsNullOrEmpty(dependency.Identifier))
                {
                    typeSymbol.SetIgnoreNamespace();
                }
                else
                {
                    typeSymbol.ScriptNamespace = dependency.Identifier;
                }

                //todo: improve the logic here to support private/protected access modifiers for nested classes
                typeSymbol.IsPublic   = type.IsPublic;
                typeSymbol.IsInternal = type.IsNotPublic;

                if (string.IsNullOrEmpty(scriptName) == false)
                {
                    typeSymbol.SetTransformedName(scriptName);
                }

                SetArrayTypeMetadata(type, typeSymbol, scriptName);

                typeSymbol.SetSource(dependency);
                namespaceSymbol.AddType(typeSymbol);
                importedTypes.Add(typeSymbol);

                if (outerType is TypeSymbol)
                {
                    outerType.AddType(typeSymbol);
                }

                if (type.HasNestedTypes)
                {
                    foreach (TypeDefinition nestedType in type.NestedTypes)
                    {
                        ImportType(mdSource, nestedType, inScriptCoreAssembly, inApplicationAssembly, dependency, typeSymbol);
                    }
                }
            }
        }
Пример #2
0
        private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScriptCoreAssembly, string scriptNamespace)
        {
            if (type.IsPublic == false)
            {
                return;
            }
            if (inScriptCoreAssembly && (MetadataHelpers.ShouldImportScriptCoreType(type) == false))
            {
                return;
            }

            string name          = type.Name;
            string namespaceName = type.Namespace;

            bool   dummy;
            string scriptName = MetadataHelpers.GetScriptName(type, out dummy, out dummy);

            NamespaceSymbol namespaceSymbol = _symbols.GetNamespace(namespaceName);
            TypeSymbol      typeSymbol      = null;

            if (type.IsInterface)
            {
                typeSymbol = new InterfaceSymbol(name, namespaceSymbol);
            }
            else if (MetadataHelpers.IsEnum(type))
            {
                // NOTE: We don't care about the flags bit on imported enums
                //       because this is only consumed by the generation logic.
                typeSymbol = new EnumerationSymbol(name, namespaceSymbol, /* flags */ false);
                if (MetadataHelpers.ShouldUseEnumNames(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNamedValues();
                }
                else if (MetadataHelpers.ShouldUseEnumValues(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNumericValues();
                }
            }
            else if (MetadataHelpers.IsDelegate(type))
            {
                typeSymbol = new DelegateSymbol(name, namespaceSymbol);
                typeSymbol.SetTransformedName("Function");
            }
            else
            {
                if (MetadataHelpers.ShouldTreatAsRecordType(type))
                {
                    typeSymbol = new RecordSymbol(name, namespaceSymbol);
                    typeSymbol.SetTransformedName("Object");
                }
                else
                {
                    typeSymbol = new ClassSymbol(name, namespaceSymbol);

                    string extendee;
                    if (MetadataHelpers.IsScriptExtension(type, out extendee))
                    {
                        ((ClassSymbol)typeSymbol).SetExtenderClass(extendee);
                    }

                    if (String.CompareOrdinal(scriptName, "Array") == 0)
                    {
                        typeSymbol.SetArray();
                    }
                }
            }

            if (typeSymbol != null)
            {
                if (type.HasGenericParameters)
                {
                    List <GenericParameterSymbol> genericArguments = new List <GenericParameterSymbol>();
                    foreach (GenericParameter genericParameter in type.GenericParameters)
                    {
                        GenericParameterSymbol arg =
                            new GenericParameterSymbol(genericParameter.Position, genericParameter.Name,
                                                       /* typeArgument */ true,
                                                       _symbols.GlobalNamespace);
                        genericArguments.Add(arg);
                    }

                    typeSymbol.AddGenericParameters(genericArguments);
                }

                ScriptReference dependency = null;
                string          dependencyIdentifier;
                string          dependencyName = MetadataHelpers.GetScriptDependencyName(type, out dependencyIdentifier);
                if (dependencyName != null)
                {
                    dependency      = new ScriptReference(dependencyName, dependencyIdentifier);
                    scriptNamespace = dependency.Identifier;
                }

                typeSymbol.SetImported(dependency);
                typeSymbol.SetMetadataToken(type, inScriptCoreAssembly);

                bool ignoreNamespace = MetadataHelpers.ShouldIgnoreNamespace(type);
                if (ignoreNamespace || String.IsNullOrEmpty(scriptNamespace))
                {
                    typeSymbol.SetIgnoreNamespace();
                }
                else
                {
                    typeSymbol.ScriptNamespace = scriptNamespace;
                }
                typeSymbol.SetPublic();

                if (String.IsNullOrEmpty(scriptName) == false)
                {
                    typeSymbol.SetTransformedName(scriptName);
                }

                namespaceSymbol.AddType(typeSymbol);
                _importedTypes.Add(typeSymbol);
            }
        }
Пример #3
0
        public ICollection <TypeSymbol> BuildMetadata(ParseNodeList compilationUnits, SymbolSet symbols, CompilerOptions options)
        {
            Debug.Assert(compilationUnits != null);
            Debug.Assert(symbols != null);

            _symbols     = symbols;
            _symbolTable = symbols;
            _options     = options;

            string scriptName = GetAssemblyScriptName(compilationUnits);

            if (String.IsNullOrEmpty(scriptName))
            {
                _errorHandler.ReportError("You must declare a ScriptAssembly attribute.", String.Empty);
            }
            else if (Utility.IsValidScriptName(scriptName) == false)
            {
                string errorMessage = "The ScriptAssembly attribute referenced an invalid name '{0}'. Script names must only contain letters, numbers, dots or underscores.";
                _errorHandler.ReportError(String.Format(errorMessage, scriptName), String.Empty);
            }
            symbols.ScriptName = scriptName;

            string scriptPrefix = GetAssemblyScriptPrefix(compilationUnits);

            if (String.IsNullOrEmpty(scriptPrefix) == false)
            {
                if (Utility.IsValidIdentifier(scriptPrefix) == false)
                {
                    string errorMessage = "The ScriptQualifier attribute referenced an invalid prefix '{0}'. Script prefix must be valid identifiers.";
                    _errorHandler.ReportError(String.Format(errorMessage, scriptPrefix), String.Empty);
                }
            }
            else
            {
                scriptPrefix = scriptName.Replace(".", String.Empty);
            }
            symbols.ScriptPrefix = scriptPrefix;

            string            assemblyScriptNamespace = GetAssemblyScriptNamespace(compilationUnits);
            List <TypeSymbol> types = new List <TypeSymbol>();

            // Build all the types first.
            // Types need to be loaded upfront so that they can be used in resolving types associated
            // with members.
            foreach (CompilationUnitNode compilationUnit in compilationUnits)
            {
                foreach (NamespaceNode namespaceNode in compilationUnit.Members)
                {
                    string namespaceName = namespaceNode.Name;

                    NamespaceSymbol namespaceSymbol = symbols.GetNamespace(namespaceName);

                    List <string> imports = null;
                    Dictionary <string, string> aliases = null;

                    ParseNodeList usingClauses = namespaceNode.UsingClauses;
                    if ((usingClauses != null) && (usingClauses.Count != 0))
                    {
                        foreach (ParseNode usingNode in namespaceNode.UsingClauses)
                        {
                            if (usingNode is UsingNamespaceNode)
                            {
                                if (imports == null)
                                {
                                    imports = new List <string>(usingClauses.Count);
                                }

                                string referencedNamespace = ((UsingNamespaceNode)usingNode).ReferencedNamespace;
                                if (imports.Contains(referencedNamespace) == false)
                                {
                                    imports.Add(referencedNamespace);
                                }
                            }
                            else
                            {
                                Debug.Assert(usingNode is UsingAliasNode);
                                if (aliases == null)
                                {
                                    aliases = new Dictionary <string, string>();
                                }
                                UsingAliasNode aliasNode = (UsingAliasNode)usingNode;
                                aliases[aliasNode.Alias] = aliasNode.TypeName;
                            }
                        }
                    }

                    // Add parent namespaces as imports in reverse order since they
                    // are searched in that fashion.
                    string[] namespaceParts = namespaceName.Split('.');
                    for (int i = namespaceParts.Length - 2; i >= 0; i--)
                    {
                        string partialNamespace;
                        if (i == 0)
                        {
                            partialNamespace = namespaceParts[0];
                        }
                        else
                        {
                            partialNamespace = String.Join(".", namespaceParts, 0, i + 1);
                        }

                        if (imports == null)
                        {
                            imports = new List <string>();
                        }

                        if (imports.Contains(partialNamespace) == false)
                        {
                            imports.Add(partialNamespace);
                        }
                    }

                    // Build type symbols for all user-defined types
                    foreach (TypeNode typeNode in namespaceNode.Members)
                    {
                        UserTypeNode userTypeNode = typeNode as UserTypeNode;
                        if (userTypeNode == null)
                        {
                            continue;
                        }

                        // Check if we have overriding script namespace for this type.
                        string typeScriptNamespace = GetScriptNamespace(userTypeNode.Attributes);
                        if (String.IsNullOrEmpty(typeScriptNamespace))
                        {
                            typeScriptNamespace = assemblyScriptNamespace;
                        }

                        ClassSymbol partialTypeSymbol = null;
                        bool        isPartial         = false;

                        if ((userTypeNode.Modifiers & Modifiers.Partial) != 0)
                        {
                            partialTypeSymbol = (ClassSymbol)((ISymbolTable)namespaceSymbol).FindSymbol(userTypeNode.Name, /* context */ null, SymbolFilter.Types);
                            if ((partialTypeSymbol != null) && partialTypeSymbol.IsApplicationType)
                            {
                                // This class will be considered as a partial class
                                isPartial = true;

                                // Merge code model information for the partial class onto the code model node
                                // for the primary partial class. Interesting bits of information include things
                                // such as base class etc. that is yet to be processed.
                                CustomTypeNode partialTypeNode = (CustomTypeNode)partialTypeSymbol.ParseContext;
                                partialTypeNode.MergePartialType((CustomTypeNode)userTypeNode);

                                // Merge interesting bits of information onto the primary type symbol as well
                                // representing this partial class
                                BuildType(partialTypeSymbol, userTypeNode);

                                if (String.IsNullOrEmpty(typeScriptNamespace) == false)
                                {
                                    partialTypeSymbol.ScriptNamespace = typeScriptNamespace;
                                }
                            }
                        }

                        TypeSymbol typeSymbol = BuildType(userTypeNode, namespaceSymbol);
                        if (typeSymbol != null)
                        {
                            typeSymbol.SetParseContext(userTypeNode);
                            typeSymbol.SetParentSymbolTable(symbols);
                            if (imports != null)
                            {
                                typeSymbol.SetImports(imports);
                            }
                            if (aliases != null)
                            {
                                typeSymbol.SetAliases(aliases);
                            }

                            if (String.IsNullOrEmpty(typeScriptNamespace) == false)
                            {
                                typeSymbol.ScriptNamespace = typeScriptNamespace;
                            }

                            if (isPartial == false)
                            {
                                namespaceSymbol.AddType(typeSymbol);
                            }
                            else
                            {
                                // Partial types don't get added to the namespace, so we don't have
                                // duplicated named items. However, they still do get instantiated
                                // and processed as usual.
                                //
                                // The members within partial classes refer to the partial type as their parent,
                                // and hence derive context such as the list of imports scoped to the
                                // particular type.
                                // However, the members will get added to the primary partial type's list of
                                // members so they can be found.
                                // Effectively the partial class here gets created just to hold
                                // context of type-symbol level bits of information such as the list of
                                // imports, that are consumed when generating code for the members defined
                                // within a specific partial class.
                                ((ClassSymbol)typeSymbol).SetPrimaryPartialClass(partialTypeSymbol);
                            }

                            types.Add(typeSymbol);
                        }
                    }
                }
            }

            // Build inheritance chains
            foreach (TypeSymbol typeSymbol in types)
            {
                if (typeSymbol.Type == SymbolType.Class)
                {
                    BuildTypeInheritance((ClassSymbol)typeSymbol);
                }
            }

            // Import members
            foreach (TypeSymbol typeSymbol in types)
            {
                BuildMembers(typeSymbol);
            }

            // Associate interface members with interface member symbols
            foreach (TypeSymbol typeSymbol in types)
            {
                if (typeSymbol.Type == SymbolType.Class)
                {
                    BuildInterfaceAssociations((ClassSymbol)typeSymbol);
                }
            }

            // Load resource values
            if (_symbols.HasResources)
            {
                foreach (TypeSymbol typeSymbol in types)
                {
                    if (typeSymbol.Type == SymbolType.Resources)
                    {
                        BuildResources((ResourcesSymbol)typeSymbol);
                    }
                }
            }

            // Load documentation
            if (_options.EnableDocComments)
            {
                Stream docCommentsStream = options.DocCommentFile.GetStream();
                if (docCommentsStream != null)
                {
                    try {
                        XmlDocument docComments = new XmlDocument();
                        docComments.Load(docCommentsStream);

                        symbols.SetComments(docComments);
                    }
                    finally {
                        options.DocCommentFile.CloseStream(docCommentsStream);
                    }
                }
            }

            return(types);
        }
Пример #4
0
        private void ImportType(MetadataSource mdSource, TypeDefinition type, bool inScriptCoreAssembly, string assemblyScriptNamespace, string assemblyScriptName)
        {
            if (type.IsPublic == false)
            {
                return;
            }
            if (inScriptCoreAssembly && (MetadataHelpers.ShouldImportScriptCoreType(type) == false))
            {
                return;
            }

            string name            = type.Name;
            string namespaceName   = type.Namespace;
            string scriptNamespace = MetadataHelpers.GetScriptNamespace(type);
            string scriptName      = MetadataHelpers.GetScriptName(type);

            if (String.IsNullOrEmpty(scriptNamespace) && (String.IsNullOrEmpty(assemblyScriptNamespace) == false))
            {
                scriptNamespace = assemblyScriptNamespace;
            }

            NamespaceSymbol namespaceSymbol = _symbols.GetNamespace(namespaceName);
            TypeSymbol      typeSymbol      = null;

            if (type.IsInterface)
            {
                typeSymbol = new InterfaceSymbol(name, namespaceSymbol);
            }
            else if (MetadataHelpers.IsEnum(type))
            {
                // NOTE: We don't care about the flags bit on imported enums
                //       because this is only consumed by the generation logic.
                typeSymbol = new EnumerationSymbol(name, namespaceSymbol, /* flags */ false);
                if (MetadataHelpers.ShouldUseEnumNames(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNamedValues();
                }
                else if (MetadataHelpers.ShouldUseEnumValues(type))
                {
                    ((EnumerationSymbol)typeSymbol).SetNumericValues();
                }
            }
            else if (MetadataHelpers.IsDelegate(type))
            {
                typeSymbol = new DelegateSymbol(name, namespaceSymbol);
                typeSymbol.SetTransformedName("Function");
            }
            else
            {
                if (MetadataHelpers.ShouldTreatAsRecordType(type))
                {
                    typeSymbol = new RecordSymbol(name, namespaceSymbol);
                }
                else
                {
                    typeSymbol = new ClassSymbol(name, namespaceSymbol);

                    string mixinRoot;
                    if (MetadataHelpers.ShouldGlobalizeMembers(type, out mixinRoot))
                    {
                        ((ClassSymbol)typeSymbol).SetGlobalMethods(mixinRoot);
                    }
                }
            }

            if (typeSymbol != null)
            {
                if (type.HasGenericParameters)
                {
                    List <GenericParameterSymbol> genericArguments = new List <GenericParameterSymbol>();
                    foreach (GenericParameter genericParameter in type.GenericParameters)
                    {
                        GenericParameterSymbol arg =
                            new GenericParameterSymbol(genericParameter.Position, genericParameter.Name,
                                                       /* typeArgument */ true,
                                                       _symbols.GlobalNamespace);
                        genericArguments.Add(arg);
                    }

                    typeSymbol.AddGenericParameters(genericArguments);
                }

                typeSymbol.SetImported(assemblyScriptName);
                typeSymbol.SetMetadataToken(type, inScriptCoreAssembly);

                bool ignoreNamespace = MetadataHelpers.ShouldIgnoreNamespace(type);
                if (ignoreNamespace)
                {
                    typeSymbol.SetIgnoreNamespace();
                }
                typeSymbol.SetPublic();

                if (String.IsNullOrEmpty(scriptNamespace) == false)
                {
                    typeSymbol.ScriptNamespace = scriptNamespace;
                }

                if (String.IsNullOrEmpty(scriptName) == false)
                {
                    typeSymbol.SetTransformedName(scriptName);
                }

                namespaceSymbol.AddType(typeSymbol);
                _importedTypes.Add(typeSymbol);
            }
        }