internal static int MapNamespaces(NamespaceInfoMap nsInfoMap, IAssemblySymbol assSymbol, bool isRef) { var count = 0; foreach (AttributeData attData in assSymbol.GetAttributes()) { if (attData.AttributeClass.FullNameEquals(isRef ? __CompilerSchemaNamespaceAttributeNameParts : SchemaNamespaceAttributeNameParts)) { var ctorArgs = attData.ConstructorArguments; string uri = null, dottedString = null; var ctorArgsLength = ctorArgs.Length; if (ctorArgsLength >= 2) { uri = ctorArgs[0].Value as string; if (uri != null) { dottedString = ctorArgs[1].Value as string; } } if (dottedString == null) { if (isRef) { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.Invalid__CompilerSchemaNamespaceAttribute, assSymbol.Identity.Name), default(TextSpan)); } else { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.InvalidSchemaNamespaceAttribute), GetTextSpan(attData)); } } NamespaceInfo nsInfo; if (!nsInfoMap.TryGetValue(uri, out nsInfo)) { if (isRef) { continue; } else { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.InvalidSchemaNamespaceAttributeUri, uri), GetTextSpan(attData)); } } if (nsInfo.DottedName != null) { if (isRef) { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.Duplicate__CompilerSchemaNamespaceAttributeUri, uri, assSymbol.Identity.Name), default(TextSpan)); } else { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.DuplicateSchemaNamespaceAttributeUri, uri), GetTextSpan(attData)); } } CSDottedName dottedName; if (!CSDottedName.TryParse(dottedString, out dottedName)) { if (isRef) { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.Invalid__CompilerSchemaNamespaceAttributeNamespaceName, dottedString, assSymbol.Identity.Name), default(TextSpan)); } else { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.InvalidSchemaNamespaceAttributeNamespaceName, dottedString), GetTextSpan(attData)); } } nsInfo.DottedName = dottedName; nsInfo.IsRef = isRef; ++count; if (isRef) { if (ctorArgsLength >= 4) { var ca2 = ctorArgs[2]; var ca3 = ctorArgs[3]; nsInfo.SetRefData(ca2.IsNull ? null : ca2.Values.Select(i => i.Value as string), ca3.IsNull ? null : ca3.Values.Select(i => i.Value as string)); } else { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.Invalid__CompilerSchemaNamespaceAttribute, assSymbol.Identity.Name), default(TextSpan)); } } } } return count; }
public static bool Compile(IReadOnlyList<string> schemaFileList, IReadOnlyList<string> csFileList, IReadOnlyList<string> csPpList, IReadOnlyList<MetadataReference> csRefList, string csAssemblyName, out LoadingContext context, out string csCode) { context = null; csCode = _csGeneratedFileBanner; if (schemaFileList == null || schemaFileList.Count == 0) { return true; } try { context = CompilerContext.Current = new CompilerContext(); var cuList = new List<CompilationUnitNode>(); foreach (var schemaFile in schemaFileList) { using (var reader = new StreamReader(schemaFile)) { CompilationUnitNode cuNode; if (Parser.Parse(schemaFile, reader, context, out cuNode)) { cuList.Add(cuNode); } else { return false; } } } var nsList = new List<NamespaceNode>(); foreach (var cu in cuList) { nsList.AddRange(cu.NamespaceList); } if (nsList.Count == 0) { return true; } var nsInfoMap = new NamespaceInfoMap(); foreach (var ns in nsList) { var uri = ns.UriValue; NamespaceInfo nsInfo; if (!nsInfoMap.TryGetValue(uri, out nsInfo)) { nsInfo = new NamespaceInfo(uri); nsInfoMap.Add(uri, nsInfo); } nsInfo.NamespaceNodeList.Add(ns); ns.NamespaceInfo = nsInfo; } foreach (var ns in nsList) { ns.ResolveImports(nsInfoMap); } foreach (var nsInfo in nsInfoMap.Values) { nsInfo.CheckDuplicateGlobalTypeNodes(); } foreach (var ns in nsList) { ns.Resolve(); } foreach (var ns in nsList) { ns.CreateInfos(); } // if (csFileList == null || csFileList.Count == 0) { return true; } var parseOpts = new CSharpParseOptions(preprocessorSymbols: csPpList, documentationMode: DocumentationMode.None); var compilation = CSharpCompilation.Create( assemblyName: "__TEMP__", syntaxTrees: csFileList.Select(csFile => CSharpSyntaxTree.ParseText(text: File.ReadAllText(csFile), options: parseOpts, path: csFile)), references: csRefList, options: _csCompilationOptions); if (csRefList != null) { foreach (var csRef in csRefList) { if (csRef.Properties.Kind == MetadataImageKind.Assembly) { var assSymbol = compilation.GetAssemblyOrModuleSymbol(csRef) as IAssemblySymbol; if (assSymbol != null) { CSEX.MapNamespaces(nsInfoMap, assSymbol, true); } } } } var compilationAssSymbol = compilation.Assembly; if (CSEX.MapNamespaces(nsInfoMap, compilationAssSymbol, false) == 0) { return true; } foreach (var nsInfo in nsInfoMap.Values) { if (nsInfo.DottedName == null) { CompilerContext.ErrorAndThrow(new DiagMsgEx(DiagCodeEx.SchemaNamespaceAttributeRequired, nsInfo.Uri), default(TextSpan)); } } CSEX.MapGlobalTypes(nsInfoMap, compilationAssSymbol.GlobalNamespace); foreach (var nsInfo in nsInfoMap.Values) { nsInfo.SetGlobalTypeDottedNames(); } foreach (var nsInfo in nsInfoMap.Values) { nsInfo.MapGlobalTypeMembers(); } var cuAttListSyntaxList = new List<AttributeListSyntax>(); var cuMemberSyntaxList = new List<MemberDeclarationSyntax>(); var globalTypeMdRefSyntaxList = new List<ExpressionSyntax>(); foreach (var nsInfo in nsInfoMap.Values) { if (!nsInfo.IsRef) { List<string> dottedPropertyNames; var dottedTypeNames = nsInfo.GetRefData(out dottedPropertyNames); cuAttListSyntaxList.Add(CS.AttributeList("assembly", CSEX.__CompilerSchemaNamespaceAttributeName, SyntaxFactory.AttributeArgument(CS.Literal(nsInfo.Uri)), SyntaxFactory.AttributeArgument(CS.Literal(nsInfo.DottedName.ToString())), SyntaxFactory.AttributeArgument(CS.NewArrOrNullExpr(CS.StringArrayType, dottedTypeNames.Select(i => CS.Literal(i)))), SyntaxFactory.AttributeArgument(CS.NewArrOrNullExpr(CS.StringArrayType, dottedPropertyNames.Select(i => CS.Literal(i)))) )); nsInfo.GetSyntax(cuMemberSyntaxList, globalTypeMdRefSyntaxList); } } var sdataProgramName = CSEX.SDataProgramName(csAssemblyName); //>public static class SData_XX { //> public static void Initialize() { } //> static SData_XX() { //> SData.ProgramMd.AddGlobalTypes(new GlobalTypeMd[]{ ... }); //> } //>} cuMemberSyntaxList.Add(CS.Class(null, CS.PublicStaticTokenList, sdataProgramName, null, CS.Method(CS.PublicStaticTokenList, CS.VoidType, "Initialize", null, null), CS.Constructor(CS.StaticTokenList, sdataProgramName, null, null, CS.ExprStm(CS.InvoExpr(CS.MemberAccessExpr(CSEX.ProgramMdExpr, "AddGlobalTypes"), CS.NewArrOrNullExpr(CSEX.GlobalTypeMdArrayType, globalTypeMdRefSyntaxList)))))); csCode = _csGeneratedFileBanner + SyntaxFactory.CompilationUnit(default(SyntaxList<ExternAliasDirectiveSyntax>), default(SyntaxList<UsingDirectiveSyntax>), SyntaxFactory.List(cuAttListSyntaxList), SyntaxFactory.List(cuMemberSyntaxList)).NormalizeWhitespace().ToString(); return true; } catch (LoadingException) { } catch (Exception ex) { context.AddDiagnostic(DiagnosticSeverity.Error, (int)DiagCodeEx.InternalCompilerError, "Internal compiler error: " + ex.ToString(), default(TextSpan)); } return false; }