public void TestCode()
        {
            var codeFile = new CodeDocument {TabCharacter = "  "};

            codeFile.Namespace("Test")
                .Class("public", "TestClass", "")
                    ._()
                    ._("private string _value;")
                    ._()
                    .Function("public", "TestClass", "string value")
                        ._("_value = value;")
                    .End()
                    ._()
                    .Function("public void ", "TestMethod", "")
                        ._("_value = 5;")
                    .End()
                    ._()
                    ._()
                    .Interface("public", "TestInterface", "")
                        ._("void TestMethod();")
                    .End()
                .End()
            .End();

            Debug.WriteLine(codeFile.ToString());

            Assert.IsTrue(true);
        }
        public void TestStateCodeGeneration()
        {
            ICodeBlock codeBlock = new CodeDocument(0);
            
            mButtonInButtonList.CurrentState = "InvalidState";

            StateCodeGenerator.WriteSetStateOnNamedObject(mButtonInButtonList, codeBlock);
            string result = codeBlock.ToString();
            if (result.Contains(mButtonInButtonList.CurrentState))
            {
                throw new Exception("Code generation for NamedObjects is generating state setting code when states don't really exist");
            }

            // Make sure generation doesn't mess up on a entity with a "" base (instead of null)
            StateCodeGenerator scg = new StateCodeGenerator();
            EntitySave entitySave = new EntitySave();

            entitySave.States.Add(new StateSave());

            entitySave.BaseEntity = "";
            scg.GenerateFields(codeBlock, entitySave);
        }
Exemple #3
0
        internal static void GenerateUsings(StringBuilder stringBuilder, IElement saveObject)
        {
            if (stringBuilder.Contains("// Generated Usings"))
            {
                ICodeBlock usings = new CodeDocument();

                UsingsCodeGenerator.GenerateUsingStatements(usings, saveObject);

                int startOfUsingSection = GetIndexAfter("// Generated Usings", stringBuilder);
                stringBuilder.Insert(startOfUsingSection, usings.ToString());
            }
        }
Exemple #4
0
        public static void GenerateCode(IElement element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            string template;

            if (element is ScreenSave)
            {
                template = mScreenTemplateGeneratedCode;
            }
            else
            {
                template = mEntityTemplateGeneratedCode;
            }

            // Since anything can modify an enumeration value we want to make sure that
            // it's proper before generating code for it:

            // If enumeration values don't work property let's just print some output and carry on
            try
            {
                element.FixEnumerationValues();
            }
            catch (Exception e)
            {
                PluginManager.ReceiveError("Error fixing enumerations for " + element + ": " + e.ToString());
            }

            // Do this before doing anything else since 
            // these reusable entire file RFS's are used 
            // in other code.
            RefreshReusableEntireFileRfses(element);

            EventCodeGenerator.GenerateEventGeneratedFile(element);

            if (element.Events.Count != 0)
            {
                var sharedCodeFullFileName = 
                    EventResponseSave.GetSharedCodeFullFileName(element, FileManager.GetDirectory(ProjectManager.GlueProjectFileName));

                EventCodeGenerator.CreateEmptyCodeIfNecessary(element,
                    sharedCodeFullFileName, false);
            }



            EventCodeGenerator.AddStubsForCustomEvents(element);

            CreateGeneratedFileIfNecessary(element);

            StringBuilder stringBuilder = new StringBuilder(template);

            foreach (PluginManager pluginManager in PluginManager.GetInstances())
            {
                CodeGeneratorPluginMethods.CallCodeGenerationStart(pluginManager, element);
            }

            if (ContentLoadWriter.SuppressGlobalContentDictionaryRefresh == false)
            {
                ReferencedFileSaveCodeGenerator.RefreshGlobalContentDictionary();
            }

            if (ReferencedFileSaveCodeGenerator.GlobalContentFilesDictionary == null)
            {
                throw new Exception("Global content files dictionary should not be null");
            }

            string objectName = FileManager.RemovePath(element.Name);

            string projectNamespace = ProjectManager.ProjectNamespace;

            if (element is EntitySave)
            {
                string directory = FileManager.MakeRelative(FileManager.GetDirectory(element.Name));

                if (directory.ToLower() != "Entities/".ToLower())
                {
                    string relativeDirectory = FileManager.MakeRelative(directory);
                    relativeDirectory = relativeDirectory.Substring(0, relativeDirectory.Length - 1);
                    relativeDirectory = relativeDirectory.Replace('/', '.');

                    projectNamespace += "." + relativeDirectory;
                }
            }
            else if (element is ScreenSave)
            {
                projectNamespace += ".Screens";
            }

            string contentManagerName = element.UseGlobalContent ? "\"Global\"" : null;
            ScreenSave asScreenSave = element as ScreenSave;
            if (asScreenSave != null &&
                !string.IsNullOrEmpty(asScreenSave.ContentManagerMethod))
            {
                contentManagerName = asScreenSave.ContentManagerMethod;
            }

            var whatToInheritFrom = GetInheritance(element);
            CodeWriter.SetClassNameAndNamespace(
                projectNamespace,
                objectName,
                stringBuilder,
                !string.IsNullOrEmpty(contentManagerName),
                contentManagerName,
                whatToInheritFrom
                );

            #region Make Activity, Initialize, PostInitalize, and Destroy "override" if necessary

            if ( element.InheritsFromElement())
            {

                if (stringBuilder.Contains("virtual void Initialize"))
                {
                    stringBuilder.Replace("virtual void Initialize", "override void Initialize");
                }

                if (stringBuilder.Contains("virtual void Activity"))
                {
                    stringBuilder.Replace("virtual void Activity", "override void Activity");
                }

                if (stringBuilder.Contains("virtual void Destroy"))
                {
                    stringBuilder.Replace("virtual void Destroy", "override void Destroy");
                }
            }

            #endregion

            try
            {
                CodeWriter.GenerateUsings(stringBuilder, element);
            }
            catch (Exception e)
            {
                string stackTrace = e.StackTrace;

                throw new Exception("Error trying to generate using statements for " + element + "\n\n" + stackTrace, e);
            }

            #region Generate Fields

            ICodeBlock fieldsSection = CodeWriter.GenerateFields(element);
            int startOfFieldsSection = CodeWriter.GetIndexAfter("// Generated Fields", stringBuilder);
            stringBuilder.Insert(startOfFieldsSection, fieldsSection.ToString());

            #endregion


            #region Generate Initialize

            ICodeBlock initializeSection = CodeWriter.GenerateInitialize(element);
            int startOfInitializeSection = CodeWriter.GetIndexAfter("// Generated Initialize", stringBuilder);
            stringBuilder.Insert(startOfInitializeSection, initializeSection.ToString());

            #endregion


            #region Generate AddToManagers

            int startOfAddToManagers = CodeWriter.GetIndexAfter("// Generated AddToManagers", stringBuilder);
            ICodeBlock addToManagersSection = CodeWriter.GenerateAddToManagers(element);
            stringBuilder.Insert(startOfAddToManagers, addToManagersSection.ToString());


            #endregion


            #region GenerateActivity



            ICodeBlock activityBlock = new CodeDocument(3);
            ICodeBlock currentBlock = activityBlock;

            currentBlock = CodeWriter.GenerateActivity(currentBlock, element);
            currentBlock = CodeWriter.GenerateAfterActivity(currentBlock, element);

            int startOfActivity = CodeWriter.GetIndexAfter("// Generated Activity", stringBuilder);
            stringBuilder.Insert(startOfActivity, activityBlock.ToString());


            #endregion

            #region Generate Destroy

            ICodeBlock destroySection = CodeWriter.GenerateDestroy(element);
            int startOfDestroySection = CodeWriter.GetIndexAfter("// Generated Destroy", stringBuilder);
            stringBuilder.Insert(startOfDestroySection, destroySection.ToString());

            #endregion


            #region Generate Methods

            ICodeBlock methodsSection = new CodeDocument(2);

            CodeWriter.GenerateMethods(methodsSection, element);

            int startOfMethodsSection = CodeWriter.GetIndexAfter("// Generated Methods", stringBuilder);
            stringBuilder.Insert(startOfMethodsSection, methodsSection.ToString());

            #endregion


            #region Extra Classes
            CodeBlockBase codeBlock = new CodeBlockBase(null);

            foreach (var codeGenerator in CodeGenerators)
            {
                codeGenerator.GenerateAdditionalClasses(codeBlock, element);
            }


            string extraClasses = codeBlock.ToString();

            if (!string.IsNullOrEmpty(extraClasses))
            {
                const string extraClassesComment = "// Extra classes";
                int indexToReplace = stringBuilder.LastIndexOf(extraClassesComment);

                stringBuilder.Remove(indexToReplace, extraClassesComment.Length);

                stringBuilder.Insert(indexToReplace, extraClasses);

            }
            #endregion

            string generatedCodeFileName = element.Name + ".Generated.cs";



            CodeWriter.SaveFileContents(stringBuilder.ToString(), FileManager.RelativeDirectory + generatedCodeFileName, true);


            #region Extra stuff if it's a ScreenSave

            if (element is ScreenSave)
            {
                bool inherits = !string.IsNullOrEmpty(element.BaseElement) && element.BaseElement != "<NONE>";
                if (inherits)
                {
                    #region Set the inheritance to the proper class

                    string fileContents;
                    string nameWithoutPath = FileManager.RemovePath(element.Name);

                    fileContents = FileManager.FromFileText(FileManager.RelativeDirectory + element.Name + ".Generated.cs");

                    #endregion

                    #region Replace the ContentManagerName

                    contentManagerName =
                        (element as ScreenSave).ContentManagerForCodeGeneration;

                    if (fileContents.Contains("base(" + contentManagerName + ")"))
                    {
                        // use the lower-case contentManagerName since that's the argument that's given to
                        // the base class' constructor.
                        fileContents = fileContents.Replace("base(" + contentManagerName + ")",
                            "base()");
                    }

                    #endregion

                    EliminateCall("\tInitialize();", ref fileContents);
                    EliminateCall(" Initialize();", ref fileContents);

                    CodeWriter.SaveFileContents(fileContents, FileManager.RelativeDirectory + element.Name + ".Generated.cs", true);
                }
            }

            #endregion

            #region Extra stuff if it's an EntitySave

            if (element is EntitySave)
            {
                EntitySave entitySave = element as EntitySave;

                string fileContents = stringBuilder.ToString();
                string fileName = FileManager.RelativeDirectory + element.Name + ".Generated.cs";
                bool shouldSave = false;

                #region Ok, the code is generated, but we may still need to give it a base class


                bool inherits;

                

                EntitySave rootEntitySave;
                List<string> inheritanceList = InheritanceCodeWriter.Self.GetInheritanceList(element, entitySave, out inherits, out rootEntitySave);
                InheritanceCodeWriter.Self.RemoveCallsForInheritance(entitySave, inherits, rootEntitySave, ref fileContents, ref shouldSave);

                #endregion

                #region If this thing is created by other entities, then we should make it IPoolable

                if (entitySave.CreatedByOtherEntities)
                {
                    FactoryCodeGenerator.UpdateFactoryClass(entitySave);
                }

                #endregion

                #region If this uses global content, then make it use global content regardless of what is passed in

                if (entitySave.UseGlobalContent)
                {
                    fileContents = fileContents.Replace("ContentManagerName = contentManagerName;", "ContentManagerName = FlatRedBall.FlatRedBallServices.GlobalContentManager;");
                    shouldSave = true;
                }

                #endregion


                #region If a change was made to the fileContents, let's save it

                if (shouldSave)
                {
                    bool tryAgain = true;

                    CodeWriter.SaveFileContents(fileContents, fileName, tryAgain);
                }

                #endregion
            }
            #endregion


        }
		private static string GetBehaviorContents(string behaviorName)
		{
		    ICodeBlock codeBlock = new CodeDocument();
            string fileName = BehaviorFolder + behaviorName + ".cs";

            if (File.Exists(fileName))
            {

                string behaviorContents = FileManager.FromFileText(fileName
                    );

                codeBlock.Line(behaviorContents);
            }
            else
            {
                codeBlock.Line("// There is an invalid behavior reference to behavior " + behaviorName);
            }

		    return codeBlock.ToString();
		}
        public void CodeGenerationStart(IElement element)
        {
            var stateChainCollection = GlueCommands.TreeNodeCommands.GetProperty<StateChainCollection>(element, PropertyName);

            if(stateChainCollection == null) return;

            var elementNameWithoutPath = FileManager.RemovePath(element.Name);
            var document = new CodeDocument();
            ICodeBlock codeBlock = document;


            if (stateChainCollection.StateChains.Count <= 0)
            {
                return;
            }


            codeBlock = codeBlock
                .Line("using FlatRedBall.Instructions;")
                .Namespace(GlueCommands.GenerateCodeCommands.GetNamespaceForElement(element))
                    .Class("public partial ", element.ClassName, "");


            //Create Enum
            codeBlock = codeBlock
                .Enum("public", "StateChains")
                    .Line("None = 0,");

            for (int i = 0; i < stateChainCollection.StateChains.Count; i++)
            {
                if (i == stateChainCollection.StateChains.Count - 1)
                    codeBlock.Line(stateChainCollection.StateChains[i].Name);
                else
                    codeBlock.Line(stateChainCollection.StateChains[i].Name + ",");
            }

            codeBlock = codeBlock.End();

            //Private members
            codeBlock
                ._()
                .Line("private StateChains _currentStateChain = StateChains.None;")
                .Line("private int _index;")
                .Line("private Instruction _instruction;")
                ._();

            //CurrentStateChain Property
            codeBlock = codeBlock
                .Property("public StateChains", "CurrentStateChain")
                    .Get()
                        .Line("return _currentStateChain;")
                    .End()
                    .Set()
                        .Line("StopStateChain();")
                        ._()
                        .Line("_currentStateChain = value;")
                        .Line("_index = 0;")
                        ._()
                        .Switch("_currentStateChain");

            foreach (var stateChain in stateChainCollection.StateChains)
            {
                codeBlock
                    .Case("StateChains." + stateChain.Name)
                        .Line("StartNextState" + stateChain.Name + "();");
            }

            codeBlock = codeBlock
                        .End()
                    .End()
                .End();

            codeBlock._();

            //ManageStateChains
            codeBlock = codeBlock
                .Function("public void", "ManageStateChains", "")
                    .If("CurrentStateChain == StateChains.None")
                        .Line("return;")
                    .End()
                    ._()
                    .Switch("CurrentStateChain");

            foreach (var stateChain in stateChainCollection.StateChains)
            {
                var index = 0;

                codeBlock = codeBlock
                    .Case("StateChains." + stateChain.Name);

                foreach (var stateChainState in
                    stateChain.StateChainStates.Where(stateChainState => !string.IsNullOrEmpty(stateChainState.State)))
                {
                    if (index == 0)
                    {
                        codeBlock
                            .If("_index == 0 && CurrentState == VariableState." + stateChainState.State)
                            .Line("_index++;")
                            .Line("StartNextState" + stateChain.Name + "();");
                    }
                    else
                    {
                        codeBlock
                            .ElseIf("_index == " + index + " && CurrentState == VariableState." +
                                    stateChainState.State)
                            .Line("_index++;")
                            .Line("StartNextState" + stateChain.Name + "();");
                    }

                    index++;
                }

                codeBlock = codeBlock
                    .End();
            }

            codeBlock = codeBlock
                        .End()
                    .End();

            codeBlock._();

            //StopStateChain
            codeBlock = codeBlock
                .Function("public void", "StopStateChain", "")
                    .If("CurrentStateChain == StateChains.None")
                        .Line("return;")
                    .End()
                    ._()
                    .Switch("CurrentStateChain");

            foreach (var stateChain in stateChainCollection.StateChains)
            {
                var index = 0;

                codeBlock = codeBlock
                    .Case("StateChains." + stateChain.Name);

                foreach (var stateChainState in stateChain.StateChainStates)
                {
                    if (index == 0)
                    {
                        codeBlock
                            .If("_index == 0")
                                .Line("Instructions.Remove(_instruction);")
                                .Line("StopStateInterpolation(VariableState." + stateChainState.State + ");")
                            .End();
                    }else
                    {
                        codeBlock
                            .ElseIf("_index == " + index)
                                .Line("Instructions.Remove(_instruction);")
                                .Line("StopStateInterpolation(VariableState." + stateChainState.State + ");")
                            .End();
                    }

                    index++;
                }

                codeBlock = codeBlock
                    .End();
            }

            codeBlock = codeBlock
                        .End()
                    .Line("_instruction = null;")
                .End();

            codeBlock._();

            //StartNextState*****
            foreach (var stateChain in stateChainCollection.StateChains)
            {
                codeBlock = codeBlock
                    .Function("private void", "StartNextState" + stateChain.Name, "")
                        .If("_index < 0")
                            .Line("_index = 0;")
                        .End()
                        ._()
                        .If("_index >= " + stateChain.StateChainStates.Count)
                            .Line("_index = 0;")
                        .End()
                        ._()
                        .Switch("_index");

                var index = 0;

                foreach (var stateChainState in stateChain.StateChainStates)
                {
                    codeBlock
                        .Case(index.ToString())
                            .Line("_instruction = InterpolateToState(VariableState." + stateChainState.State + ", " + stateChainState.Time / 1000 + ");");

                    index++;
                }

                codeBlock = codeBlock
                        .End()
                    .End()
                    ._();
            }

            GlueCommands.ProjectCommands.CreateAndAddPartialFile(element, "StateChains", document.ToString());
        }
        public static void CreateEmptyCodeIfNecessary(IElement currentElement, string fullFileName, bool forceRegenerateContents)
        {
            bool doesFileExist = File.Exists(fullFileName);

            if (!doesFileExist)
            {
                PluginManager.ReceiveOutput("Forcing a regneration of " + fullFileName + " because Glue can't find it anywhere.");

                // There is no shared code file for this event, so we need to make one
                ProjectManager.CodeProjectHelper.CreateAndAddPartialCodeFile(fullFileName, true);
            }

            if (!doesFileExist || forceRegenerateContents)
            {
                string namespaceString = GlueCommands.Self.GenerateCodeCommands.GetNamespaceForElement(currentElement);


                ICodeBlock templateCodeBlock = new CodeDocument();

                EventCodeGenerator.AddUsingStatementsToBlock(templateCodeBlock);

                ICodeBlock namespaceCB = templateCodeBlock.Namespace(namespaceString);

                ICodeBlock classCB = namespaceCB.Class("public partial", currentElement.ClassName, null);

                classCB
                    ._()
                    .End()
                .End();

                string templateToSave = templateCodeBlock.ToString();
                FlatRedBall.Glue.IO.FileWatchManager.IgnoreNextChangeOnFile(fullFileName);
                FileManager.SaveText(templateToSave, fullFileName);
            }

            // Add if it isn't part of the project
            const bool saveFile = false; // don't save it - we just want to make sure it's part of the project
            ProjectManager.CodeProjectHelper.CreateAndAddPartialCodeFile(fullFileName, saveFile);

        }
        /// <summary>
        /// Injects the insideOfMethod into an event for the argument 
        /// </summary>
        /// <param name="currentElement">The IElement containing the EventResponseSave.</param>
        /// <param name="eventResponseSave">The EventResponseSave which should have its contents set or replaced.</param>
        /// <param name="insideOfMethod">The inside of the methods to assign.</param>
        /// <returns>The full file name which contains the method contents.</returns>
        public static string InjectTextForEventAndSaveCustomFile(IElement currentElement, EventResponseSave eventResponseSave, string insideOfMethod)
        {
            // In case the user passes null we don't want to have null reference exceptions:
            if (insideOfMethod == null)
            {
                insideOfMethod = "";
            }

            ParsedMethod parsedMethod =
                eventResponseSave.GetParsedMethodFromAssociatedFile();


            string fullFileName = eventResponseSave.GetSharedCodeFullFileName();

            bool forceRegenerate = false;

            string fileContents = null;

            if (File.Exists(fullFileName))
            {
                fileContents = FileManager.FromFileText(fullFileName);
                forceRegenerate = fileContents.Contains("public partial class") == false && fileContents.Contains("{") == false;

                if (forceRegenerate)
                {
                    GlueGui.ShowMessageBox("Forcing a regneration of " + fullFileName + " because it appears to be empty.");
                }
            }

            CreateEmptyCodeIfNecessary(currentElement, fullFileName, forceRegenerate);

            fileContents = FileManager.FromFileText(fullFileName);

            int indexToAddAt = 0;

            if (parsedMethod != null)
            {
                int startIndex;
                int endIndex;
                GetStartAndEndIndexForMethod(parsedMethod, fileContents, out startIndex, out endIndex);
                // We want to include the \r\n at the end, so add 2
                endIndex += 2;
                string whatToRemove = fileContents.Substring(startIndex, endIndex - startIndex);

                fileContents = fileContents.Replace(whatToRemove, null);

                indexToAddAt = startIndex;
                // remove the method to re-add it
            }
            else
            {
                indexToAddAt = EventManager.GetLastLocationInClass(fileContents, startOfLine:true);
            }
            ICodeBlock codeBlock = new CodeDocument(2);
            codeBlock.TabCharacter = "    ";

            insideOfMethod = "" + insideOfMethod.Replace("\r\n", "\r\n            ");
            codeBlock = EventCodeGenerator.FillWithCustomEventCode(codeBlock, eventResponseSave, insideOfMethod, currentElement);

            string methodContents = codeBlock.ToString();


            fileContents = fileContents.Insert(indexToAddAt, codeBlock.ToString());

            eventResponseSave.Contents = null;
            try
            {
                FlatRedBall.Glue.IO.FileWatchManager.IgnoreNextChangeOnFile(fullFileName);
                FileManager.SaveText(fileContents, fullFileName);
            }
            catch (Exception e)
            {
                PluginManager.ReceiveError("Could not save file to " + fullFileName);
            }
            return fullFileName;
        }