public string Header_ClassBase; // Parent Class public static ClassNTHeader_ Create(List <string> sourceLines, out int ii, ClassNTStats_ statistics) { var result = new ClassNTHeader_(); // {Name = name, Value = value}; // Execute static method to populate result parameters var isClass = ClassNTHeader_Methods.Parse_ClassHeader(sourceLines, out ii, statistics, out result.NameSpace_UsingLines, out result.NameSpace_AttributeLines, out result.NameSpace_Name, out result.Header_Comment, out result.Header_CommentLines); if (isClass) { ClassNTHeader_Methods.Parse_ClassDefinition(sourceLines[ii++], result.NameSpace_Name, out result.Header_ClassKind, out result.Header_ClassScope, out result.ClassName, out result.Header_ClassBase, out result.ClassName_Group, out result.ClassName_ShortVersion); ClassNTHeader_Methods.ClassNameBreakdown(result.ClassName, out result.ClassName1, out result.ClassName2); result.Namespace_Attributes = ClassNTAttributes_.Create(result.NameSpace_AttributeLines); } else { result = null; } return(result); }
/// <summary> /// Setups the ClassHeader_ class. /// </summary> /// <param name="sourceLines">The source lines list</param> /// <param name="ii">The ii indexer reference variable</param> /// <param name="statistics">The class source statistics</param> /// <param name="Using">The using.</param> /// <param name="attributes">The attributes.</param> /// <param name="nameSpace">The name space.</param> /// <param name="commentSummary">The comment summary.</param> /// <param name="commentLines">The comment lines.</param> public static bool Parse_ClassHeader(List <string> sourceLines, out int ii, ClassNTStats_ statistics, out List <string> Using, out List <string> attributes, out string nameSpace, out string commentSummary, out List <string> commentLines) { // Set initial parameters // ========================== var lamed = LamedalCore_.Instance; // Create new instance of the blueprint library nameSpace = ""; Using = new List <string>(); attributes = new List <string>(); string ctiCodeLine = ""; commentSummary = null; commentLines = null; ii = 0; bool classHelp = false; // Header ========================= for (; ii < sourceLines.Count; ii++) { string line = sourceLines[ii]; if (statistics.zParse_IsBlankLine(line)) { continue; // <-------------------------------------------------- } // using if (line.Contains("using ")) { string using1 = line.zvar_Value("using ").zSubStr_RemoveStrAtEnd(";"); Using.Add(using1); //statistics.ClassTotalCodeLines++; continue; } // namespace if (line.Contains("namespace ")) { nameSpace = lamed.Types.String.Search.Var_Value(line, "namespace "); classHelp = true; } #region -[Help & Attributes // Lines here may contain help (between 'namespace' and 'class') /* * /// <summary> * /// Class Table_Key. This class cannot be inherited. |Key| * /// </summary> */ if (classHelp && line.Contains("/// ") || (line.Contains("[") && line.Contains("//") == false)) { int iiSave = ii; string returnLine; MethodNTComment_Methods.Documentation_Parts(sourceLines, ref ii, statistics, out commentLines, out commentSummary, out attributes, out returnLine, out ctiCodeLine); line = sourceLines[ii]; } #endregion // Class header line definition ===============================> if (line.Contains(" class ") && line.zContains_Any("/// ", "// ") == false) { return(true); } } return(false); }
public void ClassNTHeader_Test2() { int ii = 0; var stats = new ClassNTStats_(); ClassNTHeader_ header; List <string> source; #region Test1: enum test // =========================================== source = new List <string> { "namespace Access2System.domain.Enumerals", "{", " public enum enTodoTime", " {", " Hours,", " Days,", " Weeks", " }", "}" }; ii = 0; header = ClassNTHeader_.Create(source, out ii, stats); Assert.Equal(null, header); #endregion #region Test2: public sealed class Types_Money // =========================================== source = new List <string> { "using System;", "", "namespace Blueprint.lib.Rules.Types", "{", " /// <summary>", " /// Money convertions", " /// </summary>", " [BlueprintRule_(enClassNetwork.Node_Action)]", " [BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", " public sealed class Types_Money", " {", " /// <summary>", " /// A Double extension method that converts the @this to a money.", " /// </summary>", " /// <param name=\"this\">The @this to act on.</param>", " /// <returns>@this as a Double.</returns>", " public Double ToMoney(Double @this)", " {", " return Math.Round(@this, 2);", " }", " }", "}", "" }; header = ClassNTHeader_.Create(source, out ii, stats); Assert.Equal("System", header.NameSpace_UsingLines[0]); Assert.Equal("Blueprint.lib.Rules.Types", header.NameSpace_Name); Assert.Equal("Money convertions", header.Header_Comment); Assert.Equal("[BlueprintRule_(enClassNetwork.Node_Action)]", header.NameSpace_AttributeLines[0]); Assert.Equal("[BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", header.NameSpace_AttributeLines[1]); Assert.Equal("Types_Money", header.ClassName); Assert.Equal("Types", header.ClassName1); Assert.Equal("Money", header.ClassName2); #endregion }
public static void Parse_ClassHeader_Test() { int ii = 0; ClassNTStats_ stats; List <string> source; List <string> Using, attributes, commentLines; string nameSpace, comment; bool isClass; #region Test1: public sealed class Types_Money // =========================================== source = new List <string> { "using System;", "", "namespace Blueprint.lib.Rules.Types", "{", " /// <summary>", " /// Money convertions", " /// </summary>", " [BlueprintRule_(enClassNetwork.Node_Action)]", " [BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", " public sealed class Types_Money", " {", " /// <summary>", " /// A Double extension method that converts the @this to a money.", " /// </summary>", " /// <param name=\"this\">The @this to act on.</param>", " /// <returns>@this as a Double.</returns>", " public Double ToMoney(Double @this)", " {", " return Math.Round(@this, 2);", " }", " }", "}", "" }; stats = new ClassNTStats_(); isClass = ClassNTHeader_Methods.Parse_ClassHeader(source, out ii, stats, out Using, out attributes, out nameSpace, out comment, out commentLines); Assert.True(isClass); Assert.Equal("System", Using[0]); Assert.Equal("Blueprint.lib.Rules.Types", nameSpace); Assert.Equal("Money convertions", comment); Assert.Equal("<summary>Money convertions</summary>", commentLines[0]); Assert.Equal(1, commentLines.Count); // Attributes ========================== Assert.Equal(2, attributes.Count); Assert.Equal("[BlueprintRule_(enClassNetwork.Node_Action)]", attributes[0]); Assert.Equal("[BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", attributes[1]); // Statistics =================== Assert.Equal(10, stats.ClassTotalLines); Assert.Equal(3, stats.ClassTotalCommentLines); Assert.Equal(5, stats.ClassTotalCodeLines); Assert.Equal(1, stats.ClassTotalBlankLines); Assert.Equal(2, stats.TotalAttributes); // =========================== Assert.Equal(9, ii); #endregion #region Test2: enum test // =========================================== source = new List <string> { "namespace Access2System.domain.Enumerals", "{", " public enum enTodoTime", " {", " [Description = \"Test\"]", " Hours,", " Days,", " Weeks", " }", "}" }; stats = new ClassNTStats_(); isClass = ClassNTHeader_Methods.Parse_ClassHeader(source, out ii, stats, out Using, out attributes, out nameSpace, out comment, out commentLines); Assert.False(isClass); Assert.Equal(source.Count, ii); Assert.Equal(10, stats.ClassTotalLines); Assert.Equal(10, stats.ClassTotalCodeLines); Assert.Equal(0, stats.ClassTotalCommentLines); Assert.Equal(1, stats.TotalAttributes); Assert.Equal(1, stats.TotalEnumerals); #endregion #region Test3: delegate test // =========================================== source = new List <string> { "using System;", "using System.Data;", "", "namespace Blueprint.domain.Events", "{", " /// <summary>", " /// This event should fire after the submit to DB has failed. The idea is to take the user on his word and just commit the data. If the DB ", " /// constraints do not allow the data to be entered, we look at reasons why.", " /// </summary>", " /// <param name=\"sender\">The sender will be the grid (Infragistics or DevX) that the data tabel is linked to</param>", " /// <param name=\"table\">The data table trying to submit the data</param>", " /// <param name=\"ex\">The exception thrown during the update</param>", " /// <param name=\"reason\">Str containing the reasons why the Commit failed</param>", " /// <returns></returns>", " public delegate bool evDataTable_Commit_PostError(object sender, DataTable table, Exception ex, out string reason);", "}", "" }; stats = new ClassNTStats_(); isClass = ClassNTHeader_Methods.Parse_ClassHeader(source, out ii, stats, out Using, out attributes, out nameSpace, out comment, out commentLines); Assert.False(isClass); Assert.Equal(source.Count, ii); Assert.Equal(2, stats.ClassTotalBlankLines); Assert.Equal(9, stats.ClassTotalCommentLines); Assert.Equal(source.Count, stats.ClassTotalLines); Assert.Equal(5, stats.ClassTotalCodeLines); #endregion #region Test4: interface test // =========================================== source = new List <string> { "using Blueprint.parts.AI.StateEngine;", "", "namespace Blueprint.domain.Interfaces", "{", " public interface IStateEngineTransition", " {", "", " /// <summary>", " /// Transition to the next state.", " /// </summary>", " /// <returns>state</returns>", " AI_StateEngine_ Transition_Next(AI_StateEngine_ state = null, bool moveToNextState = true);", "", " /// <summary>", " /// Transition to the previous state.", " /// </summary>", " /// <returns>state</returns>", " AI_StateEngine_ Transition_Previous(bool moveToNextState = true);", " }", "}" }; stats = new ClassNTStats_(); isClass = ClassNTHeader_Methods.Parse_ClassHeader(source, out ii, stats, out Using, out attributes, out nameSpace, out comment, out commentLines); Assert.False(isClass); Assert.Equal(source.Count, ii); #endregion }
public void ClassHeaderReadWrite_Test() { #region Test1: public sealed class Types_Money // =========================================== var source = new List <string> { "using System;", "", "namespace Blueprint.lib.Rules.Types", "{", " /// <summary>", " /// Money convertions", " /// </summary>", " [BlueprintRule_Class(enBlueprintClassNetworkType.Node_Action)]", " [BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", " public sealed class Types_Money", " {", " /// <summary>", " /// A Double extension method that converts the @this to a money.", " /// </summary>", " /// <param name=\"this\">The @this to act on.</param>", " /// <returns>@this as a Double.</returns>", " public Double ToMoney(Double @this)", " {", " return Math.Round(@this, 2);", " }", " }", "}" }; // Write the lines var folderPath = Test_Config.TestFolder() + @"Text/ClassNT/"; //@"C:\test\stream\header.txt"; _lamed.lib.IO.Folder.Create(folderPath); var file = folderPath + "Types_Money.txt"; _lamed.lib.IO.RW.File_Write(file, source.ToArray(), true); // Reading the lines back var sourceRead = _lamed.lib.IO.RW.File_Read2StrArray(file).ToList(); Assert.Equal(source, sourceRead); #endregion #region Test3: Create header class int ii; ClassNTStats_ stats = ClassNTStats_.Create(); var header1 = ClassNTHeader_.Create(source, out ii, stats); Assert.Equal("System", header1.NameSpace_UsingLines[0]); Assert.Equal("Blueprint.lib.Rules.Types", header1.NameSpace_Name); Assert.Equal("Money convertions", header1.Header_Comment); Assert.Equal("[BlueprintRule_Class(enBlueprintClassNetworkType.Node_Action)]", header1.NameSpace_AttributeLines[0]); Assert.Equal("[BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", header1.NameSpace_AttributeLines[1]); Assert.Equal("Types_Money", header1.ClassName); Assert.Equal("Types", header1.ClassName1); Assert.Equal("Money", header1.ClassName2); #endregion #region Test4: Write, Read and re-Create the header class file = folderPath + "ClassNTHeader.txt"; string json1 = _lamed.lib.Test.Object_2JsonStr(header1); 1f.zIO().RW.File_Write(file, json1, overwrite: true); // Read the object and test it string json2 = 1f.zIO().RW.File_Read2Str(file); var header2 = _lamed.lib.Test.Object_FromJsonStr <ClassNTHeader_>(json2); // Testing Assert.Equal(json1, json2); Assert.Equal("System", header2.NameSpace_UsingLines[0]); Assert.Equal("Blueprint.lib.Rules.Types", header2.NameSpace_Name); Assert.Equal("Money convertions", header2.Header_Comment); Assert.Equal("[BlueprintRule_Class(enBlueprintClassNetworkType.Node_Action)]", header2.NameSpace_AttributeLines[0]); Assert.Equal("[BlueprintCodeInjection_(typeof(Controller_BlueprintLogger), true)]", header2.NameSpace_AttributeLines[1]); Assert.Equal("Types_Money", header2.ClassName); Assert.Equal("Types", header2.ClassName1); Assert.Equal("Money", header2.ClassName2); #endregion }
/// <summary> /// Converts the method's documentation to intermediate lines list. /// </summary> /// <param name="sourceLines">The header lines list</param> /// <param name="ii">The ii indexer reference variable</param> /// <param name="statistics"></param> /// <param name="commentLines">The documentation lines.</param> /// <param name="summaryLine">The summary line.</param> /// <param name="attributeLines">The attribute lines.</param> /// <param name="returnLine">The return line.</param> /// <param name="ctiCodeLine">The cti code line.</param> public static void Documentation_Parts(List <string> sourceLines, ref int ii, ClassNTStats_ statistics, out List <string> commentLines, out string summaryLine, out List <string> attributeLines, out string returnLine, out string ctiCodeLine) { // <summary>Determines whether the specified input string contains index. This is supposed to be faster than IndexOf()</summary> bool summaryStart = false; bool returnStart = false; //bool codeStart = false; commentLines = new List <string>(); attributeLines = new List <string>(); returnLine = ""; summaryLine = ""; ctiCodeLine = ""; string line = sourceLines[ii].Trim(); while (line == "" || line.Contains("///") || line.Substring(0, 1) == "[") { statistics.ClassTotalLines++; if (line.Substring(0, 1) == "[") { // Attributes attributeLines.AddRange(ClassNTAttributes_Methods.Attributes_FromCodeLine(line)); statistics.TotalAttributes++; statistics.ClassTotalCodeLines++; } else if (line.Contains("////") == false && line != "") { // This is not a comment or this is an empty line -> This is the documentation statistics.ClassTotalCommentLines++; line = line.Replace("///", "").Trim(); #region Summary ======================================================= if (summaryStart) { summaryLine += line; if (line.Contains("</summary>")) { summaryStart = false; line = summaryLine; } } else if (line.Contains("<summary>")) { summaryLine = line; if (line.Contains("</summary>") == false) { summaryStart = true; } } #endregion #region Return ====================================================== if (returnStart) { returnLine += line; if (line.Contains("</returns>")) { returnStart = false; line = returnLine; } } else if (line.Contains("<returns>")) { returnLine = line; if (line.Contains("</returns>") == false) { returnStart = true; } } #endregion ============================================================== #region Code ====================================================== // Code tag is no longer used //if (codeStart) //{ // ctiCodeLine += line; // if (ctiCodeLine.Contains("</code>")) // { // codeStart = false; // line = ctiCodeLine; // } //} //else //if (line.Contains("<code ")) //{ // ctiCodeLine = line; // if (line.Contains("</code>") == false) codeStart = true; //} #endregion ============================================================== // Only add the line if we know what the return value is -> we want to compress the XML to viewer lines as it is then more readable if (summaryStart == false && returnStart == false) { commentLines.Add(line); } } ii++; line = sourceLines[ii].Trim(); // Move to the next line } summaryLine = summaryLine.zConvert_XML_ValueBetweenTags("summary"); }
/// <summary> /// Parses the specified sourceLines. /// </summary> /// <param name="sourceLines">The sourceLines.</param> /// <param name="ii">The ii.</param> /// <param name="classRef">The class reference.</param> /// <param name="error">if set to <c>true</c> [error].</param> /// <param name="classHeader">The class header.</param> /// <param name="methods">The tag_ methods.</param> /// <param name="properties">The tag_ properties.</param> /// <param name="statistics">The statistics.</param> /// <param name="blueprintRule">The blueprint rule.</param> public static void Parse_Class(List <string> sourceLines, ref int ii, ClassNT_ classRef, out bool error, out ClassNTHeader_ classHeader, out List <MethodNT_> methods, out List <PropertyNT_> properties, out ClassNTStats_ statistics, out ClassNTBlueprintRule_ blueprintRule) { // ======================================================================================= // Note: The ii parameter is not used but is required by the ISourceCodeTemplate interface // ======================================================================================= // Create property classes methods = new List <MethodNT_>(); // Methods contained in the class properties = new List <PropertyNT_>(); blueprintRule = null; var Setup_RegionStack = new Stack <Tuple <string, int, bool> >(); // Region name, line no, //Setup_SourceCode = sourceLines; // Variables needed to parse the body error = false; int iBlocks = 0; //bool header = true; bool methodStart = false; bool commentStart = false; statistics = ClassNTStats_.Create(); statistics.ClassTotalLines = sourceLines.Count; //// Parse the header information //_Header = new sourceClassHeader_(sourceLines, ref ii, Tag_Statistics); classHeader = ClassNTHeader_.Create(sourceLines, out ii, statistics); if (classHeader != null) { blueprintRule = ClassNTBlueprintRule_.Create(classHeader.NameSpace_AttributeLines); } //ii++; //bool classHelp = false; string methodScope = ""; int iiMethodStart = ii; int iiMethodEnd = 0; // Body ==================================== for (; ii < sourceLines.Count; ii++) { string line = sourceLines[ii]; if (iBlocks == 0) { #region -[regions if (line.Contains("#region")) { var region = line; "#region ".zVar_Next(ref region); if (region == "") { region = "region"; // Needs unit test } Setup_RegionStack.Push(Tuple.Create(region, ii, true)); // True indicate that a new region was found } if (line.Contains("#endregion")) { Setup_RegionStack.Pop(); if (Setup_RegionStack.Count > 0) // Needs unit test { Tuple <string, int, bool> region = Setup_RegionStack.Pop(); Setup_RegionStack.Push(Tuple.Create(region.Item1, region.Item2, false)); // Change value to false of top item on stack } } #endregion if (!commentStart) { if (line.Contains("/// ") && !line.Contains("////")) { commentStart = true; iiMethodStart = ii; } } if (methodStart == false) { #region -[Method Start if (line.zContains_Any("(", ")") && // Most methods will have this line.zContains_Any(out methodScope, StringComparison.CurrentCulture, "private", "public", "internal") && // Most methods will have this line.zContains_All("=", "new") == false && // Methods will not have this line.zContains_Any("/// ", " class ", " get ") == false && // Methods header line will not have these line.Trim().Substring(0, 1) != "[") // This is a flag { if (line.zContains_All("(", "=") == false || line.IndexOf("=") >= line.IndexOf("(")) // If there is a '(' and '=' --> '(' must always be first { methodStart = true; if (commentStart == false) { iiMethodStart = ii; } //iBlocks = 0; } // For a method the ';' will always follow the '(' and the ')' if (line.zContains_All("(", ";") && line.IndexOf(";") <= line.IndexOf("(")) // Needs unit test { methodStart = false; } } else if (commentStart && (line.Contains("/// ") == false && line.Contains("[Pure]") == false)) { commentStart = false; } if (line.zContains_All("{", "}") == false) { continue; //<================================ } #endregion } } // This is a simple property if (line.zContains_All("get", "{", "??", "}") && line.Contains(".zContains_All") == false) // Ignore this line in myself { var test = line.Trim(); if (test.Length <= 2 || test.Substring(0, 2) != "//") // Make sure line is not commented out { var propertyLine = sourceLines[ii - 2].Trim(); var property = PropertyNT_.Create(propertyLine); properties.Add(property); } } // ================================================Method Body if (line.Contains("{")) { iBlocks++; commentStart = false; } #region -[Method End if (line.Contains("}") || (line.zContains_Any("private", "public", "internal") && line.Contains(");"))) // or contains private / public with ); // private static extern bool SetForegroundWindow(IntPtr hWnd); { if (line.Contains("}")) { iBlocks--; } if (iBlocks == 0) { iiMethodEnd = ii; #region debug //var debug = false; //if (debug) // || methodStart == false //{ // var source = LamedalCore_.Instance.Types.List.String.ToString(sourceLines, "".NL(), false, iiMethodStart,iiMethodEnd + 1); // ("Class Method found:" + source).zException_Show(action: enExceptionAction.ShowMessage); // break; //} #endregion if (methodStart == true) { methodStart = false; var method = MethodNT_.Create(sourceLines, ref iiMethodStart, iiMethodEnd, classRef); methods.Add(method); statistics.zUpdate(method); } } } #endregion } }