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); } } } }
private void ImportMethods(TypeSymbol typeSymbol) { // NOTE: We do not import parameters for imported members. // Parameters are used in the script model generation phase to populate // symbol tables, which is not done for imported methods. TypeDefinition type = (TypeDefinition)typeSymbol.MetadataReference; foreach (MethodDefinition method in type.Methods) { if (method.IsSpecialName) { continue; } if (method.IsPrivate || method.IsAssembly || method.IsFamilyAndAssembly) { continue; } string methodName = method.Name; if (typeSymbol.GetMember(methodName) != null) { // Ignore if its an overload since we don't care about parameters // for imported methods, overloaded ctors don't matter. // We just care about return values pretty much, and existence of the // method. continue; } TypeSymbol returnType = ResolveType(method.MethodReturnType.ReturnType); if (returnType == null) { continue; } // skip symbol generation for members decorated with [ScriptIgnore] if (MetadataHelpers.IsIgnored(method)) { continue; } MethodSymbol methodSymbol = new MethodSymbol( methodName, typeSymbol, returnType, MetadataHelpers.IsExtensionMethod(method)); if (MetadataHelpers.ShouldIgnoreMethodGeneratedTypeArguments(method)) { methodSymbol.IgnoreGeneratedTypeArguments = true; } methodSymbol.SetParseContext(method); ImportMemberDetails(methodSymbol, method, method); if (method.HasGenericParameters) { List <GenericParameterSymbol> genericArguments = new List <GenericParameterSymbol>(); foreach (GenericParameter genericParameter in method.GenericParameters) { GenericParameterSymbol arg = new GenericParameterSymbol(genericParameter.Position, genericParameter.Name, /* typeArgument */ false, symbols.GlobalNamespace); genericArguments.Add(arg); } methodSymbol.AddGenericArguments(genericArguments); } if (method.IsAbstract) { // NOTE: We're ignoring the override scenario - it doesn't matter in terms // of the compilation and code generation methodSymbol.SetImplementationState(SymbolImplementationFlags.Abstract); } if (MetadataHelpers.ShouldSkipFromScript(method)) { methodSymbol.SetSkipGeneration(); } string transformedName = MetadataHelpers.GetTransformedName(method); if (string.IsNullOrEmpty(transformedName) == false) { methodSymbol.SetTransformName(transformedName); } string scriptName = MetadataHelpers.GetScriptName(method, out _, out _); if (string.IsNullOrEmpty(scriptName) == false && !methodSymbol.IsTransformed) { methodSymbol.SetTransformedName(scriptName); } string selector = MetadataHelpers.GetScriptMethodSelector(method); if (string.IsNullOrEmpty(selector) == false) { methodSymbol.SetSelector(selector); } if (MetadataHelpers.ShouldTreatAsConditionalMethod(method, out ICollection <string> conditions)) { methodSymbol.SetConditions(conditions); } typeSymbol.AddMember(methodSymbol); } }
private TypeSymbol ResolveType(TypeReference type, TypeSymbol parentSymbol = null) { int arrayDimensions = 0; while (type is ArrayType arrayType) { arrayDimensions++; type = arrayType.ElementType; } GenericInstanceType genericType = type as GenericInstanceType; if (genericType != null) { type = genericType.ElementType; } string name = ProcessNestedTypeName(type); if (string.CompareOrdinal(name, MscorlibTypeNames.System_ValueType) == 0) { // Ignore this type - it is the base class for enums, and other primitive types // but we don't import it since it is not useful in script return(null); } TypeSymbol typeSymbol; if (type is GenericParameter genericParameter) { typeSymbol = new GenericParameterSymbol(genericParameter.Position, genericParameter.Name, genericParameter.Owner.GenericParameterType == GenericParameterType.Type, symbols.GlobalNamespace); if (parentSymbol != null) { ((GenericParameterSymbol)typeSymbol).Owner = parentSymbol; } } else { typeSymbol = (TypeSymbol)((ISymbolTable)symbols).FindSymbol(name, null, SymbolFilter.Types); if (typeSymbol == null) { //TODO: Improve this error and provide context as to what type is missing from where errorHandler.ReportMissingReferenceError(name); resolveError = true; } } if (genericType != null) { List <TypeSymbol> typeArgs = new List <TypeSymbol>(); foreach (TypeReference argTypeRef in genericType.GenericArguments) { TypeSymbol argType = ResolveType(argTypeRef, typeSymbol); typeArgs.Add(argType); } typeSymbol = symbols.CreateGenericTypeSymbol(typeSymbol, typeArgs); Debug.Assert(typeSymbol != null); } if (arrayDimensions != 0) { for (int i = 0; i < arrayDimensions; i++) { typeSymbol = symbols.CreateArrayTypeSymbol(typeSymbol); } } return(typeSymbol); }
private TypeSymbol ResolveType(TypeReference type) { int arrayDimensions = 0; while (type is ArrayType) { arrayDimensions++; type = ((ArrayType)type).ElementType; } GenericInstanceType genericType = type as GenericInstanceType; if (genericType != null) { type = genericType.ElementType; } string name = type.FullName; if (String.CompareOrdinal(name, "System.ValueType") == 0) { // Ignore this type - it is the base class for enums, and other primitive types // but we don't import it since it is not useful in script return(null); } TypeSymbol typeSymbol; GenericParameter genericParameter = type as GenericParameter; if (genericParameter != null) { typeSymbol = new GenericParameterSymbol(genericParameter.Position, genericParameter.Name, (genericParameter.Owner.GenericParameterType == GenericParameterType.Type), _symbols.GlobalNamespace); } else { typeSymbol = (TypeSymbol)((ISymbolTable)_symbols).FindSymbol(name, null, SymbolFilter.Types); if (typeSymbol == null) { _errorHandler.ReportError("Unable to resolve referenced type '" + name + "'. Make sure all needed assemblies have been explicitly referenced.", String.Empty); _resolveError = true; } } if (genericType != null) { List <TypeSymbol> typeArgs = new List <TypeSymbol>(); foreach (TypeReference argTypeRef in genericType.GenericArguments) { TypeSymbol argType = ResolveType(argTypeRef); typeArgs.Add(argType); } typeSymbol = _symbols.CreateGenericTypeSymbol(typeSymbol, typeArgs); Debug.Assert(typeSymbol != null); } if (arrayDimensions != 0) { for (int i = 0; i < arrayDimensions; i++) { typeSymbol = _symbols.CreateArrayTypeSymbol(typeSymbol); } } return(typeSymbol); }
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); } }
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); } }