private SyntaxTree processTrees(SyntaxTree[] trees, CSharpParseOptions parseoptions) { // this method gives us the ability to check all the generated syntax trees, // add generated constructors to partial classes when none of the parts has a constructor // merge accesses and assigns from different source files into one property etc. // we pass the usings from the compilation units along because the new compilation unit will // have to the same (combined) list of usings // When compiling in VO/Vulcan dialect we also collect the literal symbols from the compilation unit. // When we have one or more of these then we create a symbol table in the class "Xs$SymbolTable" var partialClasses = new Dictionary <string, List <PartialPropertyElement> >(XSharpString.Comparer); var symbolTable = new Dictionary <string, FieldDeclarationSyntax>(); var pszTable = new Dictionary <string, Tuple <string, FieldDeclarationSyntax> >(); foreach (var tree in trees) { var compilationunit = tree.GetRoot() as Syntax.CompilationUnitSyntax; if (compilationunit.NeedsProcessing) { foreach (var member in compilationunit.Members) { if (member is Syntax.NamespaceDeclarationSyntax) { processNameSpace(member as Syntax.NamespaceDeclarationSyntax, partialClasses, compilationunit.Usings); } else { var node = member.Green as CSharpSyntaxNode; if (node.XNode is XP.EntityContext) { processType(node.XNode as XP.EntityContext, partialClasses, compilationunit.Usings); } } } } if (_options.HasRuntime) { if (compilationunit.LiteralSymbols.Count > 0) { foreach (var pair in compilationunit.LiteralSymbols) { if (!symbolTable.ContainsKey(pair.Key)) { symbolTable.Add(pair.Key, pair.Value); } } compilationunit.LiteralSymbols.Clear(); } if (compilationunit.LiteralPSZs.Count > 0) { foreach (var pair in compilationunit.LiteralPSZs) { if (!pszTable.ContainsKey(pair.Key)) { pszTable.Add(pair.Key, pair.Value); } } compilationunit.LiteralSymbols.Clear(); } } } if (partialClasses.Count > 0 || symbolTable.Count > 0 || pszTable.Count > 0) { // Create a new tree which shall have the generated constructors and properties // and return this tree to the caller. // we copy the attributes, modifiers etc from one of the class instances to make sure that // do not specify a conflicting modifier. var trans = CreateTransform(null, _options, _pool, _syntaxFactory, _fileName); SyntaxListBuilder <UsingDirectiveSyntax> usingslist = _pool.Allocate <UsingDirectiveSyntax>(); var members = _pool.Allocate <MemberDeclarationSyntax>(); var clsmembers = _pool.Allocate <MemberDeclarationSyntax>(); foreach (var element in partialClasses) { var name = element.Key; bool hasctor = false; bool haspartialprop = false; XP.IPartialPropertyContext ctxt = null; XP.Namespace_Context xns; foreach (var val in element.Value) { var xnode = val.Type; ctxt = xnode; if (xnode.Data.HasInstanceCtor) { hasctor = true; } if (xnode.Data.PartialProps) { haspartialprop = true; } } if (ctxt.CsNode is InterfaceDeclarationSyntax) { var ifdecl = ctxt.Get <InterfaceDeclarationSyntax>(); // ctxt.Parent is XP.EntityContext // ctxt.Parent.Parent may be XP.Namespace_Context xns = ctxt.Parent.Parent as XP.Namespace_Context; if (haspartialprop) { clsmembers.Clear(); var props = GeneratePartialProperties(element.Value, usingslist, trans); if (props != null) { foreach (var prop in props) { clsmembers.Add(prop); } } if (clsmembers.Count > 0) { var decl = _syntaxFactory.InterfaceDeclaration( default(SyntaxList <AttributeListSyntax>), ifdecl.Modifiers, ifdecl.Keyword, ifdecl.Identifier, ifdecl.TypeParameterList, ifdecl.BaseList, ifdecl.ConstraintClauses, ifdecl.OpenBraceToken, clsmembers, ifdecl.CloseBraceToken, null); ifdecl.XGenerated = true; members.Add(WrapInNamespace(trans, decl, xns, _options.DefaultNamespace)); } } } else if (ctxt.CsNode is StructDeclarationSyntax) { var strucdecl = ctxt.Get <StructDeclarationSyntax>(); // ctxt.Parent is XP.EntityContext // ctxt.Parent.Parent may be XP.Namespace_Context xns = ctxt.Parent.Parent as XP.Namespace_Context; if (haspartialprop) { clsmembers.Clear(); var props = GeneratePartialProperties(element.Value, usingslist, trans); if (props != null) { foreach (var prop in props) { clsmembers.Add(prop); } } if (clsmembers.Count > 0) { var decl = _syntaxFactory.StructDeclaration( default(SyntaxList <AttributeListSyntax>), strucdecl.Modifiers, strucdecl.Keyword, strucdecl.Identifier, strucdecl.TypeParameterList, strucdecl.BaseList, strucdecl.ConstraintClauses, strucdecl.OpenBraceToken, clsmembers, strucdecl.CloseBraceToken, null); strucdecl.XGenerated = true; members.Add(WrapInNamespace(trans, decl, xns, _options.DefaultNamespace)); } } } else if (ctxt.CsNode is ClassDeclarationSyntax) { // ctxt.Parent is XP.EntityContext // ctxt.Parent.Parent may be XP.Namespace_Context xns = ctxt.Parent.Parent as XP.Namespace_Context; if (!hasctor || haspartialprop) { clsmembers.Clear(); var classdecl = ctxt.Get <ClassDeclarationSyntax>(); if (!hasctor && !classdecl.IsStatic() && _options.VOClipperConstructors && trans != null) { var ctor = trans.GenerateDefaultCtor(classdecl.Identifier, ctxt as XP.Class_Context); if (ctor != null) { clsmembers.Add(ctor); } } if (haspartialprop) { var props = GeneratePartialProperties(element.Value, usingslist, trans); if (props != null) { foreach (var prop in props) { clsmembers.Add(prop); } } } if (clsmembers.Count > 0) { var decl = _syntaxFactory.ClassDeclaration( default(SyntaxList <AttributeListSyntax>), classdecl.Modifiers, classdecl.Keyword, classdecl.Identifier, classdecl.TypeParameterList, classdecl.BaseList, classdecl.ConstraintClauses, classdecl.OpenBraceToken, clsmembers, classdecl.CloseBraceToken, null); decl.XGenerated = true; members.Add(WrapInNamespace(trans, decl, xns, _options.DefaultNamespace)); } } } } if (symbolTable.Count > 0) { // build internal static symbol table class members.Add(_generateSymbolsClass(symbolTable, trans)); } if (pszTable.Count > 0) { // build internal static psz table class members.Add(_generatePszClass(pszTable, trans)); } var eof = SyntaxFactory.Token(SyntaxKind.EndOfFileToken); var result = _syntaxFactory.CompilationUnit( default(SyntaxList <ExternAliasDirectiveSyntax>), usingslist, default(SyntaxList <AttributeListSyntax>), members, eof); result.XGenerated = true; var tree = (CSharpSyntaxTree)CSharpSyntaxTree.Create((Syntax.CompilationUnitSyntax)result.CreateRed(), parseoptions); tree.Generated = true; _pool.Free(members); _pool.Free(usingslist); _pool.Free(clsmembers); return(tree); } return(null); }
internal PartialPropertyElement(XP.IPartialPropertyContext type, IEnumerable <Syntax.UsingDirectiveSyntax> usings) { Type = type; Usings = usings; }