예제 #1
0
        internal static CodeCompileUnit MergeCodeCompileUnit(CodeCompileUnit mergedCodeCompileUnit, CodeCompileUnit compileUnit, CodeCompileUnit designerCompileUnit)
        {
            // Create the merged CodeCompileUnit
            if (mergedCodeCompileUnit == null)
            {
                mergedCodeCompileUnit = new CodeCompileUnit();
            }
            //
            CodeNamespace       designerNamespace;
            CodeTypeDeclaration designerClass = FindDesignerClass(designerCompileUnit, out designerNamespace);

            if (designerClass != null)
            {
                // Do the same with the form
                CodeNamespace       nameSpace;
                CodeTypeDeclaration className;
                BooCodeDomHelper.HasPartialClass(compileUnit, out nameSpace, out className);
                // and merge only if ...
                if ((String.Compare(designerNamespace.Name, nameSpace.Name, true) == 0) &&
                    (String.Compare(designerClass.Name, className.Name, true) == 0))
                {
                    // Ok, same Namespace & same Class : Merge !

                    // So, the "main" class is...
                    CodeTypeDeclaration mergedType = new CodeTypeDeclaration(className.Name);
                    // And does inherit from
                    mergedType.BaseTypes.AddRange(className.BaseTypes);
                    mergedType.TypeAttributes = className.TypeAttributes;
                    // Now, read members from each side, and put a stamp on each
                    foreach (CodeTypeMember member in designerClass.Members)
                    {
                        member.UserData[USERDATA_FROMDESIGNER] = true;
                        mergedType.Members.Add(member);
                    }
                    foreach (CodeTypeMember member in className.Members)
                    {
                        member.UserData[BooCodeDomHelper.USERDATA_FROMDESIGNER] = false;
                        mergedType.Members.Add(member);
                    }
                    // A class is always in a NameSpace
                    CodeNamespace mergedNamespace = new CodeNamespace(nameSpace.Name);
                    mergedNamespace.Types.Add(mergedType);
                    // Now, add it to the CompileUnit
                    mergedCodeCompileUnit.Namespaces.Clear();
                    mergedCodeCompileUnit.Namespaces.Add(mergedNamespace);
                    //
                }
                else
                {
                    // Something went wrong, return the designer CodeCompileUnit
                    mergedCodeCompileUnit = designerCompileUnit;
                }
            }
            else
            {
                // Sorry, no designer class
                mergedCodeCompileUnit = designerCompileUnit;
            }
            return(mergedCodeCompileUnit);
        }
예제 #2
0
        public override CodeCompileUnit Parse(TextReader codeStream)
        {
            //
            string mainFilePath = GetFilePath();
            // Are we are from the Designer ?
            var ddtr = codeStream as DocDataTextReader;

            if (ddtr != null)
            {
                this.FileName = mainFilePath;
                // Do the parse
                // If the TextReader is a DocDataTextReader, we should be running from VisualStudio, called by the designer
                // So, we will guess the FileName to check if we have a .Designer.boo file at the same place.
                // If so, we will have to build both .boo files to produce the CodeCompileUnit
                // Now, we should check if we have a partial Class inside, if so, that's a Candidate for .Designer.boo
                // Ok, so get the Filename, to get the companion file
                var    dd         = ((IServiceProvider)ddtr).GetService(typeof(DocData)) as DocData;
                String ddFileName = dd.Name;
                // Build the Designer FileName
                var    baseIsDesignForm = ddFileName.EndsWith(".Designer.boo");
                String companionFile    = baseIsDesignForm
                    ? BooCodeDomHelper.BuildNonDesignerFileName(ddFileName)
                    : BooCodeDomHelper.BuildDesignerFileName(ddFileName);
                if (File.Exists(companionFile))
                {
                    // Ok, we have a candidate !!!
                    DocData           docdata = new DocData(ddtr, companionFile);
                    DocDataTextReader reader  = new DocDataTextReader(docdata);
                    // so parse
                    var result = base.Parse(new TextReader[] { codeStream, reader }, new[] { ddFileName, companionFile });
                    BooCodeDomHelper.AnnotateCompileUnit(result);
                    result.UserData[BooCodeDomHelper.USERDATA_HASDESIGNER] = true;
                    result.UserData[BooCodeDomHelper.USERDATA_FILENAME]    = ddFileName;
                    return(result);
                }
            }
            return(base.Parse(codeStream));
        }
예제 #3
0
        // Called by the WinForms designer at save time
        public override void GenerateCodeFromCompileUnit(CodeCompileUnit compileUnit, TextWriter writer, CodeGeneratorOptions options)
        {
            // Does that CodeCompileUnit comes from a "Merged" unit ?
            if (compileUnit.UserData.Contains(BooCodeDomHelper.USERDATA_HASDESIGNER))
            {
                // Retrieve the Form Class
                CodeTypeDeclaration designerClass = BooCodeDomHelper.LimitToDesignerClass(compileUnit);
                // and retrieve the filename of the prg file
                String prgFileName = (string)compileUnit.UserData[BooCodeDomHelper.USERDATA_FILENAME];
                // Build the Designer FileName
                String designerPrgFile = BooCodeDomHelper.BuildDesignerFileName(prgFileName);
                var    newMethods      = new List <CodeMemberMethod>();
                //
                // Retrieve Both CodeCompileUnit
                // Now, split the members
                foreach (CodeTypeMember ctm in designerClass.Members.Cast <CodeTypeMember>().ToArray())
                {
                    var li = ctm.UserData["LexicalInfo"] as LexicalInfo;
                    // Was it a member that we have found in the original code ?
                    if (li != null)
                    {
                        if (!li.FileName.Equals(designerPrgFile))
                        {
                            //This was in the form file
                            designerClass.Members.Remove(ctm);
                        }
                    }
                    else
                    {
                        // This must be a member generated by the Designer !
                        // So we will move Methods to the Form and all others to the Designer
                        var cmm = ctm as CodeMemberMethod;
                        if (cmm != null)
                        {
                            newMethods.Add(cmm);
                            designerClass.Members.Remove(cmm);
                        }
                    }
                }
                if (newMethods.Count > 0)
                {
                    WriteNewMethods(newMethods, designerPrgFile, designerClass.Name);
                }
                // now, we must save both CodeCompileUnit
                // The received TextWriter is pointing to the Form
                // so we must create our own TextWriter for the Designer
                // First, let's make in Memory
                String       generatedSource;
                MemoryStream inMemory       = new MemoryStream();
                StreamWriter designerStream = new StreamWriter(inMemory, Encoding.UTF8);
                //
                base.GenerateCodeFromCompileUnit(compileUnit, designerStream, options);
                // and force Flush
                designerStream.Flush();
                // Reset and read to String
                inMemory.Position = 0;
                StreamReader reader = new StreamReader(inMemory, Encoding.UTF8, true);
                generatedSource = reader.ReadToEnd();
                Encoding realencoding = reader.CurrentEncoding;
                reader.Close();
                designerStream.Close();
                // and now write the "real" file
                designerStream = new StreamWriter(designerPrgFile, false, realencoding);
                designerStream.Write(generatedSource);
                designerStream.Flush();
                designerStream.Close();
                NormalizeLineEndings(designerPrgFile);

                /*
                 * // The problem here, is that we "may" have some new members, like EvenHandlers, and we need to update their position (line/col)
                 * var parser = CreateParser();
                 * //                parser.TabSize = provider.TabSize;
                 * //                parser.FileName = designerPrgFile;
                 * CodeCompileUnit resultDesigner = parser.Parse(new StringReader(generatedSource));
                 * CodeTypeDeclaration resultClass = BooCodeDomHelper.FindDesignerClass(resultDesigner);
                 * // just to be sure...
                 * if (resultClass != null)
                 * {
                 *  // Now push all elements from resultClass to designClass
                 *  designClass.Members.Clear();
                 *  foreach (CodeTypeMember ctm in resultClass.Members)
                 *  {
                 *      ctm.UserData[BooCodeDomHelper.USERDATA_FROMDESIGNER] = true;
                 *      designClass.Members.Add(ctm);
                 *  }
                 * }
                 * // Ok,we MUST do the same thing for the Form file
                 * base.GenerateCodeFromCompileUnit(formCCU, writer, options);
                 * // BUT, the writer is hold by the Form Designer, don't close  it !!
                 * writer.Flush();
                 * NormalizeLineEndings(prgFileName);
                 * // Now, we must re-read it and parse again
                 * IServiceProvider provider = (DocDataTextWriter)writer;
                 * DocData docData = (DocData)provider.GetService(typeof(DocData));
                 * DocDataTextReader ddtr = new DocDataTextReader(docData);
                 * // Retrieve
                 * generatedSource = ddtr.ReadToEnd();
                 * // normalize the line endings
                 * generatedSource = generatedSource.Replace("\n", "");
                 * generatedSource = generatedSource.Replace("\r", "\r\n");
                 * // Don't forget to set the name of the file where the source is...
                 * resultDesigner = parser.Parse(new StringReader(generatedSource));
                 * resultClass = BooCodeDomHelper.FindFirstClass(resultDesigner);
                 * // just to be sure...
                 * if (resultClass != null)
                 * {
                 *  // Now push all elements from resultClass to formClass
                 *  formClass.Members.Clear();
                 *  foreach (CodeTypeMember ctm in resultClass.Members)
                 *  {
                 *      ctm.UserData[BooCodeDomHelper.USERDATA_FROMDESIGNER] = false;
                 *      formClass.Members.Add(ctm);
                 *  }
                 * }
                 * // Ok, it should be ok....
                 * // We have updated the file and the types that are stored inside each CCU that have been merged in compileUnit
                 * //BooCodeDomHelper.MergeCodeCompileUnit(compileUnit, formCCU, designCCU);
                 * // And update...
                 * designerClass.Members.Clear();
                 * foreach (CodeTypeMember m in designClass.Members)
                 * {
                 *  designerClass.Members.Add(m);
                 * }
                 * foreach (CodeTypeMember m in formClass.Members)
                 * {
                 *  designerClass.Members.Add(m);
                 * }
                 */
            }
            else
            {
                // suppress generating the "generated code" header
                compileUnit.UserData[BooCodeDomHelper.USERDATA_NOHEADER] = true;
                base.GenerateCodeFromCompileUnit(compileUnit, writer, options);
                writer.Flush();
                // Designer gave us these informations
                CodeTypeDeclaration formClass = BooCodeDomHelper.FindFirstClass(compileUnit);
                // Now, we must re-read it and parse again
                IServiceProvider  provider = (DocDataTextWriter)writer;
                DocData           docData  = (DocData)provider.GetService(typeof(DocData));
                DocDataTextReader ddtr     = new DocDataTextReader(docData);
                // Retrieve
                string generatedSource = ddtr.ReadToEnd();

                var                 parser      = CreateParser();
                CodeCompileUnit     resultCcu   = parser.Parse(new StringReader(generatedSource));
                CodeTypeDeclaration resultClass = BooCodeDomHelper.FindFirstClass(resultCcu);
                // just to be sure...
                if (resultClass != null)
                {
                    // Now push all elements from resultClass to formClass
                    formClass.Members.Clear();
                    foreach (CodeTypeMember ctm in resultClass.Members)
                    {
                        formClass.Members.Add(ctm);
                    }
                }
            }
        }