[
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\r\n## files generated by popular Visual Studio add-ons.\r\n##\r\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\r\n\r\n# User-specific files\r\n*.suo\r\n*.user\r\n*.userosscache\r\n*.sln.docstates\r\n\r\n# User-specific files (MonoDevelop/Xamarin Studio)\r\n*.userprefs\r\n\r\n# Build results\r\n[Dd]ebug/\r\n[Dd]ebugPublic/\r\n[Rr]elease/\r\n[Rr]eleases/\r\nx64/\r\nx86/\r\nbld/\r\n[Bb]in/\r\n[Oo]bj/\r\n[Ll]og/\r\n\r\n# Visual Studio 2015 cache/options directory\r\n.vs/\r\n# Uncomment if you have tasks that create the project's static files in wwwroot\r\n#wwwroot/\r\n\r\n# MSTest test Results\r\n[Tt]est[Rr]esult*/\r\n[Bb]uild[Ll]og.*\r\n\r\n# NUNIT\r\n*.VisualState.xml\r\nTestResult.xml\r\n\r\n# Build Results of an ATL Project\r\n[Dd]ebugPS/\r\n[Rr]eleasePS/\r\ndlldata.c\r\n\r\n# .NET Core\r\nproject.lock.json\r\nproject.fragment.lock.json\r\nartifacts/\r\n**/Properties/launchSettings.json\r\n\r\n*_i.c\r\n*_p.c\r\n*_i.h\r\n*.ilk\r\n*.meta\r\n*.obj\r\n*.pch\r\n*.pdb\r\n*.pgc\r\n*.pgd\r\n*.rsp\r\n*.sbr\r\n*.tlb\r\n*.tli\r\n*.tlh\r\n*.tmp\r\n*.tmp_proj\r\n*.log\r\n*.vspscc\r\n*.vssscc\r\n.builds\r\n*.pidb\r\n*.svclog\r\n*.scc\r\n\r\n# Chutzpah Test files\r\n_Chutzpah*\r\n\r\n# Visual C++ cache files\r\nipch/\r\n*.aps\r\n*.ncb\r\n*.opendb\r\n*.opensdf\r\n*.sdf\r\n*.cachefile\r\n*.VC.db\r\n*.VC.VC.opendb\r\n\r\n# Visual Studio profiler\r\n*.psess\r\n*.vsp\r\n*.vspx\r\n*.sap\r\n\r\n# TFS 2012 Local Workspace\r\n$tf/\r\n\r\n# Guidance Automation Toolkit\r\n*.gpState\r\n\r\n# ReSharper is a .NET coding add-in\r\n_ReSharper*/\r\n*.[Rr]e[Ss]harper\r\n*.DotSettings.user\r\n\r\n# JustCode is a .NET coding add-in\r\n.JustCode\r\n\r\n# TeamCity is a build add-in\r\n_TeamCity*\r\n\r\n# DotCover is a Code Coverage Tool\r\n*.dotCover\r\n\r\n# Visual Studio code coverage results\r\n*.coverage\r\n*.coveragexml\r\n\r\n# NCrunch\r\n_NCrunch_*\r\n.*crunch*.local.xml\r\nnCrunchTemp_*\r\n\r\n# MightyMoose\r\n*.mm.*\r\nAutoTest.Net/\r\n\r\n# Web workbench (sass)\r\n.sass-cache/\r\n\r\n# Installshield output folder\r\n[Ee]xpress/\r\n\r\n# DocProject is a documentation generator add-in\r\nDocProject/buildhelp/\r\nDocProject/Help/*.HxT\r\nDocProject/Help/*.HxC\r\nDocProject/Help/*.hhc\r\nDocProject/Help/*.hhk\r\nDocProject/Help/*.hhp\r\nDocProject/Help/Html2\r\nDocProject/Help/html\r\n\r\n# Click-Once directory\r\npublish/\r\n\r\n# Publish Web Output\r\n*.[Pp]ublish.xml\r\n*.azurePubxml\r\n# TODO: Comment the next line if you want to checkin your web deploy settings\r\n# but database connection strings (with potential passwords) will be unencrypted\r\n*.pubxml\r\n*.publishproj\r\n\r\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\r\n# checkin your Azure Web App publish settings, but sensitive information contained\r\n# in these scripts will be unencrypted\r\nPublishScripts/\r\n\r\n# NuGet Packages\r\n*.nupkg\r\n# The packages folder can be ignored because of Package Restore\r\n**/packages/*\r\n# except build/, which is used as an MSBuild target.\r\n!**/packages/build/\r\n# Uncomment if necessary however generally it will be regenerated when needed\r\n#!**/packages/repositories.config\r\n# NuGet v3's project.json files produces more ignorable files\r\n*.nuget.props\r\n*.nuget.targets\r\n\r\n# Microsoft Azure Build Output\r\ncsx/\r\n*.build.csdef\r\n\r\n# Microsoft Azure Emulator\r\necf/\r\nrcf/\r\n\r\n# Windows Store app package directories and files\r\nAppPackages/\r\nBundleArtifacts/\r\nPackage.StoreAssociation.xml\r\n_pkginfo.txt\r\n\r\n# Visual Studio cache files\r\n# files ending in .cache can be ignored\r\n*.[Cc]ache\r\n# but keep track of directories ending in .cache\r\n!*.[Cc]ache/\r\n\r\n# Others\r\nClientBin/\r\n~$*\r\n*~\r\n*.dbmdl\r\n*.dbproj.schemaview\r\n*.jfm\r\n*.pfx\r\n*.publishsettings\r\norleans.codegen.cs\r\n\r\n# Since there are multiple workflows, uncomment next line to ignore bower_components\r\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\r\n#bower_components/\r\n\r\n# RIA/Silverlight projects\r\nGenerated_Code/\r\n\r\n# Backup & report files from converting an old project file\r\n# to a newer Visual Studio version. Backup files are not needed,\r\n# because we have git ;-)\r\n_UpgradeReport_Files/\r\nBackup*/\r\nUpgradeLog*.XML\r\nUpgradeLog*.htm\r\n\r\n# SQL Server files\r\n*.mdf\r\n*.ldf\r\n*.ndf\r\n\r\n# Business Intelligence projects\r\n*.rdl.data\r\n*.bim.layout\r\n*.bim_*.settings\r\n\r\n# Microsoft Fakes\r\nFakesAssemblies/\r\n\r\n# GhostDoc plugin setting file\r\n*.GhostDoc.xml\r\n\r\n# Node.js Tools for Visual Studio\r\n.ntvs_analysis.dat\r\nnode_modules/\r\n\r\n# Typescript v1 declaration files\r\ntypings/\r\n\r\n# Visual Studio 6 build log\r\n*.plg\r\n\r\n# Visual Studio 6 workspace options file\r\n*.opt\r\n\r\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\r\n*.vbw\r\n\r\n# Visual Studio LightSwitch build output\r\n**/*.HTMLClient/GeneratedArtifacts\r\n**/*.DesktopClient/GeneratedArtifacts\r\n**/*.DesktopClient/ModelManifest.xml\r\n**/*.Server/GeneratedArtifacts\r\n**/*.Server/ModelManifest.xml\r\n_Pvt_Extensions\r\n\r\n# Paket dependency manager\r\n.paket/paket.exe\r\npaket-files/\r\n\r\n# FAKE - F# Make\r\n.fake/\r\n\r\n# JetBrains Rider\r\n.idea/\r\n*.sln.iml\r\n\r\n# CodeRush\r\n.cr/\r\n\r\n# Python Tools for Visual Studio (PTVS)\r\n__pycache__/\r\n*.pyc\r\n\r\n# Cake - Uncomment if you are using it\r\n# tools/**\r\n# !tools/packages.config\r\n\r\n# Telerik's JustMock configuration file\r\n*.jmconfig\r\n\r\n# BizTalk build output\r\n*.btp.cs\r\n*.btm.cs\r\n*.odx.cs\r\n*.xsd.cs\r\nsrc/BuildTask/nuget/\r\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# .NET Object Model Diagram Generator\n\nA cross-platform Roslyn-based tool that generates an object model diagram of a set of C# source files and/or .NET assemblies\n\n## Sponsoring\n\nIf you like this library and use it a lot, consider sponsoring me. Anything helps and encourages me to keep going.\n\nSee here for details: https://github.com/sponsors/dotMorten\n\n\n### Install\n\nRun the following command from commandline (requires .NET Core 2.1 installed):\n```\ndotnet tool install --global dotMorten.OmdGenerator\n```\n\n\n### Usage:\n```\ngenerateomd /source=[source folder] /compareSource=[oldSourceFolder] /preprocessors=[defines] /format=[html|image] /showPrivate /showInternal\n\nRequired parameters:\n  source            Specifies the folder of source files to include for the object model.\n                    Separate with ; for multiple folders\nor\n  assemblies        Specifies a set of assemblies to include for the object model.\n                    Separate with ; for multiple assemblies, or use wildcards\n\t\t\t\t\nOptional parameters:\n  compareSource     Specifies a folder of old source to compare and generate a diff model\n                    This can be useful for finding API changes or compare branches\n  compareAssemblies Specifies a set of old assemblies to compare and generate a adiff model.\n                    Separate with; for multiple assemblies, or use wildcards\n  format            Format to generate: \n                       'html' a single html output (html is default)\n                       'md' for markdown you can copy-paste to for instance GitHub.\n\t\t       Specify multiple with a semicolon seperator, and use an output filename without extension\n  preprocessors     Define a set of preprocessors values. Use ; to separate multiple\n  exclude           Defines one or more strings that can't be part of the path Ie '*/Samples/*;*/UnitTests/*'\n                    (use forward slash for folder separators)\n  regexfilter       Defines a regular expression for filtering on full file names in the source\n  showPrivate       Show private members (default is false)\n  showInternal      Show internal members (default is false)\n  output            Filename to write the output to (extension is optional, but exclude the extension if you specify multiple formats)\n```\n\n\n### NuGet\nAs an alternative you can also reference a [NuGet package](https://www.nuget.org/packages/dotMorten.OmdGenerator/) to your class library, and set up a post-build script to generate an Object Model Diagram HTML file:\n\n```\nInstall-Package dotMorten.OmdGenerator \n```\n\nAdd the following to your project:\n```xml\n  <Target Name=\"GenerateObjectModel\" AfterTargets=\"Compile\">\n    <Exec Command=\"dotnet &quot;$(DotNetOMDGeneratorToolPath)&quot; /source=&quot;@(Compile)&quot; /preprocessors=&quot;$(DefineConstants)&quot; /output=&quot;$(OutputPath)$(TargetName)&quot;\" WorkingDirectory=\"$(ProjectDir)\" />\n  </Target>\n \n```\n\n\nAn example of a generated output for all of .NET Core can be found [here](http://www.sharpgis.net/Tests/corefx.html).\n\nIt can also be used to compare two folders (for instance two separate branches) and only show changes to the API. [Here's an example of .NET CoreFX v2.0 vs Master](http://www.sharpgis.net/Tests/corefx_new.html).\n\n[![Screenshot](Screenshot.png)](http://www.sharpgis.net/Tests/corefx.html)\n\n\n### Examples\n\nGenerate OMD for .NET Core FX source code, and ignore ref and test folders:\n```\ngenerateomd /source=c:\\github\\dotnet\\corefx\\src /exclude=\"*/ref/*;*/tests/*;*/perftests/*\"\n```\n\nCompare .NET CoreFX Master with v2.0.0 repo branches directly from their Github zipped downloads:\n\n```\ngenerateomd /source=https://github.com/dotnet/corefx/archive/master.zip /compareSource=https://github.com/dotnet/corefx/archive/release/2.0.0.zip /exclude=\"*/ref/*;*/tests/*;*/perftests/*\"\n```\n\nWhat's new in Xamarin.Forms? Compare assemblies from the nuget cache:\n```\ngenerateomd /assemblies=%USERPROFILE%\\.nuget\\packages\\xamarin.forms\\3.3.0.912540\\lib\\netstandard2.0\\*.dll /compareAsssemblies=%USERPROFILE%\\.nuget\\packages\\xamarin.forms\\3.2.0.871581\\lib\\netstandard2.0\\*.dll\n```\n\n\n"
  },
  {
    "path": "TestCode/NewCode/Class1.cs",
    "content": "using System;\nusing System.Threading.Tasks;\n\npublic namespace RootNamespace \n{\n   public class BaseClass\n   {\n       public abstract void SomeBaseMethod();\n       public void AVoidMethod() { }\n   }\n   \n   public class MyClass : BaseClass, IDisposable\n   {\n\n        MyClass() { }\n        [Obsolete]\n        MyClass(int obseleteOverload) { }\n        public Task<int> ATaskReturningGenericMethod() { }\n        public double ProtectedSetProperty { get; protected set; }\n        public double WritableProperty { get; set; }\n        public double ReadOnlyProperty { get; }\n        public double SetOnlyProperty { set; }\n        [Obsolete]\n        public void AlreadyObsoletedMethod();\n        [Obsolete]\n        public void ObsoletedMethod();\n        [Obsolete]\n        public double ObsoletedProperty { set; }\n        public event EventHandler SimpleEvent;\n        public event EventHandler<double> GenericEvent;\n        [Obsolete]\n        public event EventHandler ObsoletedEvent { set; }\n        public void Dispose() { }\n        public override void SomeBaseMethod() {}\n   }\n   [Obsolete]\n   public class ObsoletedClass {}\n}"
  },
  {
    "path": "TestCode/NewCode/Enum1.cs",
    "content": "using System;\n\npublic namespace RootNamespace \n{\n    public enum ShortEnum : short\n    {\n        Zero=0, One=1, Two=2\n    }\n    public enum SimpleEnum\n    {\n        Unknown=-1, One=1, /*Two=2,*/ Three = 3\n    }\n\n    [Flags]\n    public enum FlagsEnum\n    {\n        Zero = 0,\n\tOne = 1,\n\tTwo = 2,\n\tFour = 4,\n\t[Obsolete]\n\tObsolete = 5,\n\tAll = 255,\n    }\n}"
  },
  {
    "path": "TestCode/NewCode/Interface1.cs",
    "content": "using System;\nusing System.Threading.Tasks;\n\npublic namespace RootNamespace \n{\n   public interface Interface1\n   {\n\t   void Method();\n   }\n\n   public interface DerivedInterface : Interface1\n   {\n\t   void Method2();\n   }\n}\n"
  },
  {
    "path": "TestCode/NewCode/NmeaParser.xml",
    "content": "<?xml version=\"1.0\"?>\n<doc>\n    <assembly>\n        <name>NmeaParser</name>\n    </assembly>\n    <members>\n        <member name=\"T:NmeaParser.BufferedStreamDevice\">\n            <summary>\n            An abstract generic NMEA device that reads a stream at a decreased pace,\n            mostly used to emulate NMEA input from files and strings.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.#ctor\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice\"/> class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.#ctor(System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice\"/> class.\n            </summary>\n            <param name=\"readSpeed\">The time to wait between each group of lines being read in milliseconds</param>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.GetStreamAsync\">\n            <summary>\n            Gets the stream to perform buffer reads on.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.OpenStreamAsync\">\n            <summary>\n            Opens the stream asynchronous.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream asynchronous.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.#ctor(System.IO.StreamReader,System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice.BufferedStream\"/> class.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <param name=\"readSpeed\">The read speed in milliseconds.</param>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanRead\">\n            <summary>\n            Gets a value indicating whether this instance can read.\n            </summary>\n            <value>\n              <c>true</c> if this instance can read; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanSeek\">\n            <summary>\n            Gets a value indicating whether this instance can seek.\n            </summary>\n            <value>\n              <c>true</c> if this instance can seek; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanWrite\">\n            <summary>\n            Gets a value indicating whether this instance can write.\n            </summary>\n            <value>\n              <c>true</c> if this instance can write; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Flush\">\n            <summary>\n            Flushes this instance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.Length\">\n            <summary>\n            Gets the length.\n            </summary>\n            <value>\n            The length.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.Position\">\n            <summary>\n            Gets or sets the position.\n            </summary>\n            <value>\n            The position.\n            </value>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Read(System.Byte[],System.Int32,System.Int32)\">\n            <summary>\n            Reads the specified buffer.\n            </summary>\n            <param name=\"buffer\">The buffer.</param>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"count\">The count.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Seek(System.Int64,System.IO.SeekOrigin)\">\n            <summary>\n            Seeks the specified offset.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"origin\">The origin.</param>\n            <returns></returns>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.SetLength(System.Int64)\">\n            <summary>\n            Sets the length.\n            </summary>\n            <param name=\"value\">The value.</param>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Write(System.Byte[],System.Int32,System.Int32)\">\n            <summary>\n            Writes the specified buffer to the device.\n            </summary>\n            <param name=\"buffer\">The buffer.</param>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"count\">The count.</param>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n        <member name=\"P:NmeaParser.IMultiPartMessage.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.IMultiPartMessage.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.NmeaDevice\">\n            <summary>\n            A generic abstract NMEA device\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.#ctor\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaDevice\"/> class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.OpenAsync\">\n            <summary>\n            Opens the device connection.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.OpenStreamAsync\">\n            <summary>\n            Creates the stream the NmeaDevice is working on top off.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.CloseAsync\">\n            <summary>\n            Closes the device.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream the NmeaDevice is working on top off.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"E:NmeaParser.NmeaDevice.MessageReceived\">\n            <summary>\n            Occurs when an NMEA message is received.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.Dispose\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n        <member name=\"P:NmeaParser.NmeaDevice.IsOpen\">\n            <summary>\n            Gets a value indicating whether this device is open.\n            </summary>\n            <value>\n              <c>true</c> if this instance is open; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.NmeaMessageReceivedEventArgs\">\n            <summary>\n            Event argument for the <see cref=\"E:NmeaParser.NmeaDevice.MessageReceived\" />\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.Message\">\n            <summary>\n            Gets the nmea message.\n            </summary>\n            <value>\n            The nmea message.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.IsMultipart\">\n            <summary>\n            Gets a value indicating whether this instance is a multi part message.\n            </summary>\n            <value>\n            <c>true</c> if this instance is multi part; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.MessageParts\">\n            <summary>\n            Gets the message parts if this is a multi-part message and all message parts has been received.\n            </summary>\n            <value>\n            The message parts.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.NmeaFileDevice\">\n            <summary>\n            A file-based NMEA device reading from a NMEA log file.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.#ctor(System.String)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaFileDevice\"/> class.\n            </summary>\n            <param name=\"fileName\"></param>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.#ctor(System.String,System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaFileDevice\"/> class.\n            </summary>\n            <param name=\"fileName\"></param>\n            <param name=\"readSpeed\">The time to wait between each group of lines being read in milliseconds</param>\n        </member>\n        <member name=\"P:NmeaParser.NmeaFileDevice.FileName\">\n            <summary>\n            Gets the name of the nmea file this device is using.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.GetStreamAsync\">\n            <summary>\n            Gets the stream to perform buffer reads on.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Galileo.Gagsv\">\n            <summary>\n             GALILEO Satellites in view\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gga\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gga.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.FixTime\">\n            <summary>\n            Time of day fix was taken\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.Quality\">\n            <summary>\n            Fix Quality\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.NumberOfSatellites\">\n            <summary>\n            Number of satellites being tracked\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.Hdop\">\n            <summary>\n            Horizontal Dilution of Precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.Altitude\">\n            <summary>\n            Altitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.AltitudeUnits\">\n            <summary>\n            Altitude units ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.HeightOfGeoid\">\n            <summary>\n            Height of geoid (mean sea level) above WGS84\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.HeightOfGeoidUnits\">\n            <summary>\n            Altitude units ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.TimeSinceLastDgpsUpdate\">\n            <summary>\n            Time since last DGPS update\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gga.DgpsStationId\">\n            <summary>\n            DGPS Station ID Number\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gll\">\n            <summary>\n             Geographic position, latitude / longitude\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gll.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gll.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gll.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gll.FixTime\">\n            <summary>\n            Time since last DGPS update\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gll.DataActive\">\n            <summary>\n            Gets a value indicating whether data is active.\n            </summary>\n            <value>\n              <c>true</c> if data is active; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Glonass.Glgns\">\n            <summary>\n            Fix data for GLONASS satellite navigation systems\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Glonass.Glgsv\">\n            <summary>\n             GLONASS Satellites in view\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gns\">\n            <summary>\n            Fixes data for single or combined (GPS, GLONASS, possible future satellite systems, and systems combining these) satellite navigation systems\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gns.Mode\">\n            <summary>\n            GNS Mode Indicator\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.NoFix\">\n            <summary>\n            No fix. Satellite system not used in position fix, or fix not valid\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Autonomous\">\n            <summary>\n            Autonomous. Satellite system used in non-differential mode in position fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Differential\">\n            <summary>\n            Differential (including all OmniSTAR services). Satellite system used in differential mode in position fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Precise\">\n            <summary>\n            Precise. Satellite system used in precision mode. Precision mode is defined as no deliberate degradation (such as Selective Availability) and higher resolution code (P-code) is used to compute position fix.\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.RealTimeKinematic\">\n            <summary>\n             Real Time Kinematic. Satellite system used in RTK mode with fixed integers\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.FloatRtk\">\n            <summary>\n            Float RTK. Satellite system used in real time kinematic mode with floating integers\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Estimated\">\n            <summary>\n            Estimated (dead reckoning) mode\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Manual\">\n            <summary>\n            Manual input mode\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.Mode.Simulator\">\n            <summary>\n            Simulator mode\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gns.NavigationalStatus\">\n            <summary>\n            Navigational status\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.NavigationalStatus.NotValid\">\n            <summary>\n            Not valid for navigation\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.NavigationalStatus.Safe\">\n            <summary>\n            Safe\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.NavigationalStatus.Caution\">\n            <summary>\n            Caution\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gns.NavigationalStatus.Unsafe\">\n            <summary>\n            Unsafe\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gns.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.FixTime\">\n            <summary>\n            Time of day fix was taken\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.GpsModeIndicator\">\n            <summary>\n            Mode indicator for GPS\n            </summary>\n            <seealso cref=\"P:NmeaParser.Nmea.Gns.GlonassModeIndicator\"/>\n            <see cref=\"P:NmeaParser.Nmea.Gns.FutureModeIndicator\"/>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.GlonassModeIndicator\">\n            <summary>\n            Mode indicator for GLONASS\n            </summary>\n            <seealso cref=\"P:NmeaParser.Nmea.Gns.GpsModeIndicator\"/>\n            <see cref=\"P:NmeaParser.Nmea.Gns.FutureModeIndicator\"/>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.FutureModeIndicator\">\n            <summary>\n            Mode indicator for future constallations\n            </summary>\n            <seealso cref=\"P:NmeaParser.Nmea.Gns.GlonassModeIndicator\"/>\n            <seealso cref=\"P:NmeaParser.Nmea.Gns.GpsModeIndicator\"/>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.NumberOfSatellites\">\n            <summary>\n            Number of satellites (SVs) in use\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.Hdop\">\n            <summary>\n            Horizontal Dilution of Precision (HDOP), calculated using all the satellites (GPS, GLONASS, and any future satellites) used in computing the solution reported in each GNS sentence.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.OrhometricHeight\">\n            <summary>\n            Orthometric height in meters (MSL reference)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.GeoidalSeparation\">\n            <summary>\n            Geoidal separation in meters - the difference between the earth ellipsoid surface and mean-sea-level (geoid) surface defined by the reference datum used in the position solution<br/>\n            '-' = mean-sea-level surface below ellipsoid.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.TimeSinceLastDgpsUpdate\">\n            <summary>\n             Age of differential data - <see cref=\"F:System.TimeSpan.MaxValue\"/> if talker ID is GN, additional GNS messages follow with GP and/or GL Age of differential data\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.DgpsStationId\">\n            <summary>\n            eference station ID1, range 0000-4095 - Null if talker ID is GN, additional GNS messages follow with GP and/or GL Reference station ID\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gns.Status\">\n            <summary>\n            Navigational status\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gngga\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gngll\">\n            <summary>\n             Geographic position, latitude / longitude\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gngsa\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gngst\">\n            <summary>\n            Position error statistics \n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gnrmc\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gngns\">\n            <summary>\n            Fixes data for single or combined (GPS, GLONASS, possible future satellite systems, and systems combining these) satellite navigation systems\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrme\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Garmin.Pgrme.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.HorizontalError\">\n            <summary>\n            Estimated horizontal position error in meters (HPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.HorizontalErrorUnits\">\n            <summary>\n            Horizontal Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.VerticalError\">\n            <summary>\n            Estimated vertical position error in meters (VPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.VerticalErrorUnits\">\n            <summary>\n            Vertical Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.SphericalError\">\n            <summary>\n            Overall spherical equivalent position error (EPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.SphericalErrorUnits\">\n            <summary>\n            Spherical Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz\">\n            <summary>\n            Altitude Information\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit\">\n            <summary>\n            Altitude unit\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit.Feet\">\n            <summary>\n            Feet\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType\">\n            <summary>\n            Position Fix Dimension\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.NoFix\">\n            <summary>\n            No fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Fix2D\">\n            <summary>\n            2D Fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Fix3D\">\n            <summary>\n            3D Fix\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Garmin.Pgrmz.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.Altitude\">\n            <summary>\n            Current altitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.Unit\">\n            <summary>\n            Horizontal Error unit ('f' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.FixType\">\n            <summary>\n            Fix type\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpbod\">\n            <summary>\n            Bearing Origin to Destination\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpbod.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.TrueBearing\">\n            <summary>\n            True Bearing from start to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.MagneticBearing\">\n            <summary>\n            Magnetic Bearing from start to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.OriginId\">\n            <summary>\n            Name of origin\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.DestinationId\">\n            <summary>\n            Name of destination\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgga\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgga.FixQuality\">\n            <summary>\n            Fix quality\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Invalid\">\n            <summary>Invalid</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.GpsFix\">\n            <summary>GPS</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.DgpsFix\">\n            <summary>Differential GPS</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.PpsFix\">\n            <summary>Precise Positioning Service</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Rtk\">\n            <summary>Real Time Kinematic (Fixed)</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.FloatRtk\">\n            <summary>Real Time Kinematic (Floating)</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Estimated\">\n            <summary>Estimated</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.ManualInput\">\n            <summary>Manual input</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Simulation\">\n            <summary>Simulation</summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgll\">\n            <summary>\n             Geographic position, latitude / longitude\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgns\">\n            <summary>\n            Fixes data for GPS satellite navigation systems\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection\">\n            <summary>\n            Mode selection\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection.Auto\">\n            <summary>\n            Auto\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection.Manual\">\n            <summary>\n            Manual mode\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa.Mode\">\n            <summary>\n            Fix Mode\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.NotAvailable\">\n            <summary>\n            Not available\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.Fix2D\">\n            <summary>\n            2D Fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.Fix3D\">\n            <summary>\n            3D Fix\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgst\">\n            <summary>\n            Position error statistics\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsv\">\n            <summary>\n             GLONASS Satellites in view\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.SatelliteVehicle\">\n            <summary>\n            Satellite vehicle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.PrnNumber\">\n            <summary>\n            SV PRN number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.Elevation\">\n            <summary>\n            Elevation in degrees, 90 maximum\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.Azimuth\">\n            <summary>\n            Azimuth, degrees from true north, 000 to 359\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.SignalToNoiseRatio\">\n            <summary>\n            Signal-to-Noise ratio, 0-99 dB (-1 when not tracking) \n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.System\">\n            <summary>\n            Satellite system\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.SatelliteSystem\">\n            <summary>\n            Satellite system\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Gps\">\n            <summary>\n            GPS - Global Positioning System (NAVSTAR)\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Waas\">\n            <summary>\n            WAAS - Wide Area Augmentation System\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Glonass\">\n            <summary>\n            GLONASS - Globalnaya navigatsionnaya sputnikovaya sistema\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Galileo\">\n            <summary>\n            Galileo\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmb\">\n            <summary>\n            Recommended minimum navigation information\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmb.DataStatus\">\n            <summary>\n            Data status\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprmb.DataStatus.Ok\">\n            <summary>\n            Ok\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprmb.DataStatus.Warning\">\n            <summary>\n            Warning\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprmb.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Status\">\n            <summary>\n            Data Status\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.CrossTrackError\">\n            <summary>\n            Cross-track error (steer left when negative, right when positive)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.OriginWaypointId\">\n            <summary>\n            Origin waypoint ID\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationWaypointId\">\n            <summary>\n            Destination waypoint ID\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationLatitude\">\n            <summary>\n            Destination Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationLongitude\">\n            <summary>\n            Destination Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.RangeToDestination\">\n            <summary>\n            Range to destination in nautical miles\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.TrueBearing\">\n            <summary>\n            True bearing to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Velocity\">\n            <summary>\n            Velocity towards destination in knots\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Arrived\">\n            <summary>\n            Arrived (<c>true</c> if arrived)\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmc\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprte\">\n            <summary>\n             Routes\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprte.WaypointListType\">\n            <summary>\n            Waypoint tpe\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprte.WaypointListType.CompleteWaypointsList\">\n            <summary>\n            Complete list of waypoints\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprte.WaypointListType.RemainingWaypointsList\">\n            <summary>\n            List of remaining waypoints\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.ListType\">\n            <summary>\n            Gets the type of the list.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.RouteId\">\n            <summary>\n            Gets the route identifier.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.Waypoints\">\n            <summary>\n            Waypoints\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.System#Collections#Generic#IEnumerable{System#String}#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through the collection.\n            </summary>\n            <returns> A System.Collections.Generic.IEnumerator{T} that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.System#Collections#IEnumerable#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through a collection.\n            </summary>\n            <returns> An System.Collections.IEnumerator object that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gsa\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gsa.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.GpsMode\">\n            <summary>\n            Mode\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.FixMode\">\n            <summary>\n            Mode\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.SVs\">\n            <summary>\n            IDs of SVs used in position fix\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.Pdop\">\n            <summary>\n            Dilution of precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.Hdop\">\n            <summary>\n            Horizontal dilution of precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsa.Vdop\">\n            <summary>\n            Vertical dilution of precision\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gst\">\n            <summary>\n            Position error statistics\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gst.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.FixTime\">\n            <summary>\n            UTC of position fix\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.Rms\">\n            <summary>\n            RMS value of the pseudorange residuals; includes carrier phase residuals during periods of RTK (float) and RTK (fixed) processing\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.SemiMajorError\">\n            <summary>\n            Error ellipse semi-major axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.SemiMinorError\">\n            <summary>\n            Error ellipse semi-minor axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.ErrorOrientation\">\n            <summary>\n            Error ellipse orientation, degrees from true north\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.SigmaLatitudeError\">\n            <summary>\n            Latitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.SigmaLongitudeError\">\n            <summary >\n            Longitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gst.SigmaHeightError\">\n            <summary >\n            Height 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gsv\">\n            <summary>\n             GPS Satellites in view\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gsv.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsv.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsv.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsv.SVsInView\">\n            <summary>\n            Total number of SVs in view\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gsv.SVs\">\n            <summary>\n            Dilution of precision\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gsv.GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through the collection.\n            </summary>\n            <returns> A System.Collections.Generic.IEnumerator{SatelliteVehicle} that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gsv.System#Collections#IEnumerable#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through a collection.\n            </summary>\n            <returns> An System.Collections.IEnumerator object that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.LaserRangeMessage\">\n            <summary>\n            Laser Range Measurement\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.LaserRange.LaserRangeMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalVector\">\n            <summary>\n            Gets the horizontal vector.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistance\">\n            <summary>\n            Gets the horizontal distance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistanceUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistance\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngle\">\n            <summary>\n            Gets the horizontal angle.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngleUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngle\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngle\">\n            <summary>\n            Gets the vertical angle.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngleUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngle\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistance\">\n            <summary>\n            Gets the slope distance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistanceUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistance\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.LaserTech.Pltit\">\n            <summary>\n            Laser Range \n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.Trimble.Ptnla\">\n            <summary>\n            Burden finder\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb\">\n            <summary>\n            Tree Measurement\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.TreeHeight\">\n            <summary>\n            Gets the height of the tree.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeight\">\n            <summary>\n            Gets the message height of the tree.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeightUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeight\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.TreeDiameter\">\n            <summary>\n            Gets the tree diameter.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameter\">\n            <summary>\n            Gets the measured tree diameter.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameterUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameter\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.NmeaMessageTypeAttribute\">\n            <summary>\n            Nmea message attribute type used on concrete <see cref=\"T:NmeaParser.Nmea.NmeaMessage\"/> implementations.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessageTypeAttribute.#ctor(System.String)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.Nmea.NmeaMessageTypeAttribute\"/> class.\n            </summary>\n            <param name=\"nmeaType\">The type.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessageTypeAttribute.NmeaType\">\n            <summary>\n            Gets or sets the NMEA message type.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.NmeaMessage\">\n            <summary>\n            NMEA Message base class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.Parse(System.String)\">\n            <summary>\n            Parses the specified NMEA message.\n            </summary>\n            <param name=\"message\">The NMEA message string.</param>\n            <returns></returns>\n            <exception cref=\"T:System.ArgumentException\">\n            Invalid nmea message: Missing starting character '$'\n            or checksum failure\n            </exception>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.MessageParts\">\n            <summary>\n            Gets the NMEA message parts.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.MessageType\">\n            <summary>\n            Gets the NMEA type id for the message.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n            <remarks>\n            Implement this method to create a custom NMEA message.\n            </remarks>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.ToString\">\n            <summary>\n            Returns a <see cref=\"T:System.String\" /> that represents this instance.\n            </summary>\n            <returns>\n            A <see cref=\"T:System.String\" /> that represents this instance.\n            </returns>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.Checksum\">\n            <summary>\n            Gets the checksum value of the message.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Rmc\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Rmc.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.FixTime\">\n            <summary>\n            Fix Time\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.Active\">\n            <summary>\n            Gets a value whether the device is active\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.Speed\">\n            <summary>\n            Speed over the ground in knots\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.Course\">\n            <summary>\n            Track angle in degrees True\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Rmc.MagneticVariation\">\n            <summary>\n            Magnetic Variation\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.UnknownMessage\">\n            <summary>\n            Represents an unknown message type\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.UnknownMessage.Values\">\n            <summary>\n            Gets the nmea value array.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.UnknownMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"T:NmeaParser.StreamDevice\">\n            <summary>\n            Generic stream device\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.#ctor(System.IO.Stream)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.StreamDevice\"/> class.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.OpenStreamAsync\">\n            <summary>\n            Opens the stream asynchronous.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream asynchronous.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n    </members>\n</doc>\n"
  },
  {
    "path": "TestCode/OldCode/Class1.cs",
    "content": "using System;\nusing System.Threading.Tasks;\n\npublic namespace RootNamespace \n{\n   public class BaseClass\n   {\n           public abstract void SomeBaseMethod();\n   }\n   \n   public class MyClass : IDisposable\n   {\n        MyClass() { }\n        MyClass(int obseleteOverload) { }\n        public void AVoidMethod() { }\n        public Task<int> ATaskReturningGenericMethod() { }\n        public double ProtectedSetProperty { get; protected set; }\n        public double WritableProperty { get; set; }\n        public double ReadOnlyProperty { get; }\n        public double SetOnlyProperty { set; }\n        [Obsolete]\n        public void AlreadyObsoletedMethod();\n        public double ObsoletedProperty { set; }\n        public void ObsoletedMethod();\n        public event EventHandler SimpleEvent;\n        public event EventHandler<double> GenericEvent;\n        public event EventHandler ObsoletedEvent { set; }\n        public void Dispose() { }\n   }\n   public class ObsoletedClass {}\n}"
  },
  {
    "path": "TestCode/OldCode/Enum1.cs",
    "content": "using System;\n\npublic namespace RootNamespace \n{\n    public enum ShortEnum : long\n    {\n        Zero=0, One=1, Two=2\n    }\n    public enum SimpleEnum\n    {\n        Unknown=0, One=1, Two=2\n    }\n\n    [Flags]\n    public enum FlagsEnum\n    {\n        Zero = 0,\n\tOne = 1,\n\tTwo = 2,\n\tFour = 4,\n\tObsolete = 5,\n\tAll = 255,\n    }\n}"
  },
  {
    "path": "TestCode/OldCode/Interface1.cs",
    "content": "using System;\nusing System.Threading.Tasks;\n\npublic namespace RootNamespace \n{\n   public interface Interface1\n   {\n\t   void Method();\n   }\n\n   public interface DerivedInterface : Interface1\n   {\n\t   void Method2();\n   }\n}\n"
  },
  {
    "path": "TestCode/OldCode/NmeaParser.xml",
    "content": "<?xml version=\"1.0\"?>\n<doc>\n    <assembly>\n        <name>NmeaParser</name>\n    </assembly>\n    <members>\n        <member name=\"T:NmeaParser.BufferedStreamDevice\">\n            <summary>\n            An abstract generic NMEA device that reads a stream at a decreased pace,\n            mostly used to emulate NMEA input from files and strings.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.#ctor\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice\"/> class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.#ctor(System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice\"/> class.\n            </summary>\n            <param name=\"readSpeed\">The time to wait between each group of lines being read in milliseconds</param>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.GetStreamAsync\">\n            <summary>\n            Gets the stream to perform buffer reads on.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.OpenStreamAsync\">\n            <summary>\n            Opens the stream asynchronous.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream asynchronous.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.#ctor(System.IO.StreamReader,System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.BufferedStreamDevice.BufferedStream\"/> class.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <param name=\"readSpeed\">The read speed in milliseconds.</param>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanRead\">\n            <summary>\n            Gets a value indicating whether this instance can read.\n            </summary>\n            <value>\n              <c>true</c> if this instance can read; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanSeek\">\n            <summary>\n            Gets a value indicating whether this instance can seek.\n            </summary>\n            <value>\n              <c>true</c> if this instance can seek; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.CanWrite\">\n            <summary>\n            Gets a value indicating whether this instance can write.\n            </summary>\n            <value>\n              <c>true</c> if this instance can write; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Flush\">\n            <summary>\n            Flushes this instance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.Length\">\n            <summary>\n            Gets the length.\n            </summary>\n            <value>\n            The length.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.BufferedStreamDevice.BufferedStream.Position\">\n            <summary>\n            Gets or sets the position.\n            </summary>\n            <value>\n            The position.\n            </value>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Read(System.Byte[],System.Int32,System.Int32)\">\n            <summary>\n            Reads the specified buffer.\n            </summary>\n            <param name=\"buffer\">The buffer.</param>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"count\">The count.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Seek(System.Int64,System.IO.SeekOrigin)\">\n            <summary>\n            Seeks the specified offset.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"origin\">The origin.</param>\n            <returns></returns>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.SetLength(System.Int64)\">\n            <summary>\n            Sets the length.\n            </summary>\n            <param name=\"value\">The value.</param>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Write(System.Byte[],System.Int32,System.Int32)\">\n            <summary>\n            Writes the specified buffer to the device.\n            </summary>\n            <param name=\"buffer\">The buffer.</param>\n            <param name=\"offset\">The offset.</param>\n            <param name=\"count\">The count.</param>\n            <exception cref=\"T:System.NotSupportedException\"></exception>\n        </member>\n        <member name=\"M:NmeaParser.BufferedStreamDevice.BufferedStream.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n        <member name=\"P:NmeaParser.IMultiPartMessage.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.IMultiPartMessage.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.NmeaDevice\">\n            <summary>\n            A generic abstract NMEA device\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.#ctor\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaDevice\"/> class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.OpenAsync\">\n            <summary>\n            Opens the device connection.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.OpenStreamAsync\">\n            <summary>\n            Creates the stream the NmeaDevice is working on top off.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.CloseAsync\">\n            <summary>\n            Closes the device.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream the NmeaDevice is working on top off.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"E:NmeaParser.NmeaDevice.MessageReceived\">\n            <summary>\n            Occurs when an NMEA message is received.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.Dispose\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaDevice.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n        <member name=\"P:NmeaParser.NmeaDevice.IsOpen\">\n            <summary>\n            Gets a value indicating whether this device is open.\n            </summary>\n            <value>\n              <c>true</c> if this instance is open; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.NmeaMessageReceivedEventArgs\">\n            <summary>\n            Event argument for the <see cref=\"E:NmeaParser.NmeaDevice.MessageReceived\" />\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.Message\">\n            <summary>\n            Gets the nmea message.\n            </summary>\n            <value>\n            The nmea message.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.IsMultipart\">\n            <summary>\n            Gets a value indicating whether this instance is a multi part message.\n            </summary>\n            <value>\n            <c>true</c> if this instance is multi part; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"P:NmeaParser.NmeaMessageReceivedEventArgs.MessageParts\">\n            <summary>\n            Gets the message parts if this is a multi-part message and all message parts has been received.\n            </summary>\n            <value>\n            The message parts.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.NmeaFileDevice\">\n            <summary>\n            A file-based NMEA device reading from a NMEA log file.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.#ctor(System.String)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaFileDevice\"/> class.\n            </summary>\n            <param name=\"fileName\"></param>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.#ctor(System.String,System.Int32)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.NmeaFileDevice\"/> class.\n            </summary>\n            <param name=\"fileName\"></param>\n            <param name=\"readSpeed\">The time to wait between each group of lines being read in milliseconds</param>\n        </member>\n        <member name=\"P:NmeaParser.NmeaFileDevice.FileName\">\n            <summary>\n            Gets the name of the nmea file this device is using.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.NmeaFileDevice.GetStreamAsync\">\n            <summary>\n            Gets the stream to perform buffer reads on.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gnss.Gngst\">\n            <summary>\n            Position error statistics \n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gnss.Gngst.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.FixTime\">\n            <summary>\n            UTC of position fix\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.Rms\">\n            <summary>\n            RMS value of the pseudorange residuals; includes carrier phase residuals during periods of RTK (float) and RTK (fixed) processing\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.SemiMajorError\">\n            <summary>\n            Error ellipse semi-major axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.SemiMinorError\">\n            <summary>\n            Error ellipse semi-minor axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.ErrorOrientation\">\n            <summary>\n            Error ellipse orientation, degrees from true north\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.SigmaLatitudeError\">\n            <summary>\n            Latitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.SigmaLongitudeError\">\n            <summary >\n            Longitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gnss.Gngst.SigmaHeightError\">\n            <summary >\n            Height 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrme\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Garmin.Pgrme.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.HorizontalError\">\n            <summary>\n            Estimated horizontal position error in meters (HPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.HorizontalErrorUnits\">\n            <summary>\n            Horizontal Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.VerticalError\">\n            <summary>\n            Estimated vertical position error in meters (VPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.VerticalErrorUnits\">\n            <summary>\n            Vertical Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.SphericalError\">\n            <summary>\n            Overall spherical equivalent position error (EPE)\n            </summary>\n            <remarks>Range: 0.0 to 999.9 meters</remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrme.SphericalErrorUnits\">\n            <summary>\n            Spherical Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz\">\n            <summary>\n            Altitude Information\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit\">\n            <summary>\n            Altitude unit\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.AltitudeUnit.Feet\">\n            <summary>\n            Feet\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType\">\n            <summary>\n            Position Fix Dimension\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.NoFix\">\n            <summary>\n            No fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Fix2D\">\n            <summary>\n            2D Fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixType.Fix3D\">\n            <summary>\n            3D Fix\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Garmin.Pgrmz.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.Altitude\">\n            <summary>\n            Current altitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.Unit\">\n            <summary>\n            Horizontal Error unit ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Garmin.Pgrmz.FixType\">\n            <summary>\n            Fix type\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpbod\">\n            <summary>\n            Bearing Origin to Destination\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpbod.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.TrueBearing\">\n            <summary>\n            True Bearing from start to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.MagneticBearing\">\n            <summary>\n            Magnetic Bearing from start to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.OriginId\">\n            <summary>\n            Name of origin\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpbod.DestinationId\">\n            <summary>\n            Name of destination\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgga\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgga.FixQuality\">\n            <summary>\n            Fix quality\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Invalid\">\n            <summary>Invalid</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.GpsFix\">\n            <summary>GPS</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.DgpsFix\">\n            <summary>Differential GPS</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.PpsFix\">\n            <summary>Precise Positioning Service</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Rtk\">\n            <summary>Real Time Kinematic (Fixed)</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.FloatRtk\">\n            <summary>Real Time Kinematic (Floating)</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Estimated\">\n            <summary>Estimated</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.ManualInput\">\n            <summary>Manual input</summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgga.FixQuality.Simulation\">\n            <summary>Simulation</summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgga.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.FixTime\">\n            <summary>\n            Time of day fix was taken\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.Quality\">\n            <summary>\n            Fix Quality\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.NumberOfSatellites\">\n            <summary>\n            Number of satellites being tracked\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.Hdop\">\n            <summary>\n            Horizontal Dilution of Precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.Altitude\">\n            <summary>\n            Altitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.AltitudeUnits\">\n            <summary>\n            Altitude units ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.HeightOfGeoid\">\n            <summary>\n            Height of geoid (mean sea level) above WGS84\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.HeightOfGeoidUnits\">\n            <summary>\n            Altitude units ('M' for Meters)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.TimeSinceLastDgpsUpdate\">\n            <summary>\n            Time since last DGPS update\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgga.DgpsStationId\">\n            <summary>\n            DGPS Station ID Number\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgll\">\n            <summary>\n             Geographic position, latitude / longitude\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgll.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgll.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgll.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgll.FixTime\">\n            <summary>\n            Time since last DGPS update\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgll.DataActive\">\n            <summary>\n            Gets a value indicating whether data is active.\n            </summary>\n            <value>\n              <c>true</c> if data is active; otherwise, <c>false</c>.\n            </value>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa\">\n            <summary>\n             Global Positioning System Fix Data\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection\">\n            <summary>\n            Mode selection\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection.Auto\">\n            <summary>\n            Auto\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.ModeSelection.Manual\">\n            <summary>\n            Manual mode\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsa.Mode\">\n            <summary>\n            Fix Mode\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.NotAvailable\">\n            <summary>\n            Not available\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.Fix2D\">\n            <summary>\n            2D Fix\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gpgsa.Mode.Fix3D\">\n            <summary>\n            3D Fix\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgsa.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.GpsMode\">\n            <summary>\n            Mode\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.FixMode\">\n            <summary>\n            Mode\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.SVs\">\n            <summary>\n            IDs of SVs used in position fix\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.Pdop\">\n            <summary>\n            Dilution of precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.Hdop\">\n            <summary>\n            Horizontal dilution of precision\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsa.Vdop\">\n            <summary>\n            Vertical dilution of precision\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgst\">\n            <summary>\n            Position error statistics\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgst.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.FixTime\">\n            <summary>\n            UTC of position fix\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.Rms\">\n            <summary>\n            RMS value of the pseudorange residuals; includes carrier phase residuals during periods of RTK (float) and RTK (fixed) processing\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.SemiMajorError\">\n            <summary>\n            Error ellipse semi-major axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.SemiMinorError\">\n            <summary>\n            Error ellipse semi-minor axis 1 sigma error, in meters\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.ErrorOrientation\">\n            <summary>\n            Error ellipse orientation, degrees from true north\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.SigmaLatitudeError\">\n            <summary>\n            Latitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.SigmaLongitudeError\">\n            <summary >\n            Longitude 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgst.SigmaHeightError\">\n            <summary >\n            Height 1 sigma error, in meters\n            </summary>\n            <remarks>\n            The error expressed as one standard deviation.\n            </remarks>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gpgsv\">\n            <summary>\n             GPS Satellites in view\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgsv.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsv.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsv.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsv.SVsInView\">\n            <summary>\n            Total number of SVs in view\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gpgsv.SVs\">\n            <summary>\n            Dilution of precision\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgsv.GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through the collection.\n            </summary>\n            <returns> A System.Collections.Generic.IEnumerator{SatelliteVehicle} that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gpgsv.System#Collections#IEnumerable#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through a collection.\n            </summary>\n            <returns> An System.Collections.IEnumerator object that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.SatelliteVehicle\">\n            <summary>\n            Satellite vehicle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.PrnNumber\">\n            <summary>\n            SV PRN number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.Elevation\">\n            <summary>\n            Elevation in degrees, 90 maximum\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.Azimuth\">\n            <summary>\n            Azimuth, degrees from true north, 000 to 359\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.SignalToNoiseRatio\">\n            <summary>\n            Signal-to-Noise ratio, 0-99 dB (-1 when not tracking) \n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.SatelliteVehicle.System\">\n            <summary>\n            Satellite system\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.SatelliteSystem\">\n            <summary>\n            Satellite system\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Unknown\">\n            <summary>\n            Unknown\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Gps\">\n            <summary>\n            GPS - Global Positioning System (NAVSTAR)\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Waas\">\n            <summary>\n            WAAS - Wide Area Augmentation System\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.SatelliteSystem.Glonass\">\n            <summary>\n            GLONASS - Globalnaya navigatsionnaya sputnikovaya sistema\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmb\">\n            <summary>\n            Recommended minimum navigation information\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmb.DataStatus\">\n            <summary>\n            Data status\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprmb.DataStatus.Ok\">\n            <summary>\n            Ok\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprmb.DataStatus.Warning\">\n            <summary>\n            Warning\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprmb.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Status\">\n            <summary>\n            Data Status\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.CrossTrackError\">\n            <summary>\n            Cross-track error (steer left when negative, right when positive)\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.OriginWaypointId\">\n            <summary>\n            Origin waypoint ID\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationWaypointId\">\n            <summary>\n            Destination waypoint ID\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationLatitude\">\n            <summary>\n            Destination Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.DestinationLongitude\">\n            <summary>\n            Destination Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.RangeToDestination\">\n            <summary>\n            Range to destination in nautical miles\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.TrueBearing\">\n            <summary>\n            True bearing to destination\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Velocity\">\n            <summary>\n            Velocity towards destination in knots\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmb.Arrived\">\n            <summary>\n            Arrived (<c>true</c> if arrived)\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprmc\">\n            <summary>\n             Recommended Minimum\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprmc.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.FixTime\">\n            <summary>\n            Fix Time\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.Active\">\n            <summary>\n            Gets a value whether the device is active\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.Latitude\">\n            <summary>\n            Latitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.Longitude\">\n            <summary>\n            Longitude\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.Speed\">\n            <summary>\n            Speed over the ground in knots\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.Course\">\n            <summary>\n            Track angle in degrees True\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprmc.MagneticVariation\">\n            <summary>\n            Magnetic Variation\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprte\">\n            <summary>\n             Routes\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.Gps.Gprte.WaypointListType\">\n            <summary>\n            Waypoint tpe\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprte.WaypointListType.CompleteWaypointsList\">\n            <summary>\n            Complete list of waypoints\n            </summary>\n        </member>\n        <member name=\"F:NmeaParser.Nmea.Gps.Gprte.WaypointListType.RemainingWaypointsList\">\n            <summary>\n            List of remaining waypoints\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.TotalMessages\">\n            <summary>\n            Total number of messages of this type in this cycle\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.MessageNumber\">\n            <summary>\n            Message number\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.ListType\">\n            <summary>\n            Gets the type of the list.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.RouteId\">\n            <summary>\n            Gets the route identifier.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.Gps.Gprte.Waypoints\">\n            <summary>\n            Waypoints\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.System#Collections#Generic#IEnumerable{System#String}#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through the collection.\n            </summary>\n            <returns> A System.Collections.Generic.IEnumerator{T} that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.Gps.Gprte.System#Collections#IEnumerable#GetEnumerator\">\n            <summary>\n            Returns an enumerator that iterates through a collection.\n            </summary>\n            <returns> An System.Collections.IEnumerator object that can be used to iterate through the collection.</returns>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.LaserRangeMessage\">\n            <summary>\n            Laser Range Measurement\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.LaserRange.LaserRangeMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalVector\">\n            <summary>\n            Gets the horizontal vector.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistance\">\n            <summary>\n            Gets the horizontal distance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistanceUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalDistance\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngle\">\n            <summary>\n            Gets the horizontal angle.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngleUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.HorizontalAngle\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngle\">\n            <summary>\n            Gets the vertical angle.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngleUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.VerticalAngle\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistance\">\n            <summary>\n            Gets the slope distance.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistanceUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.LaserRangeMessage.SlopeDistance\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.LaserTech.Pltit\">\n            <summary>\n            Laser Range \n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.Trimble.Ptnla\">\n            <summary>\n            Burden finder\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb\">\n            <summary>\n            Tree Measurement\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.TreeHeight\">\n            <summary>\n            Gets the height of the tree.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeight\">\n            <summary>\n            Gets the message height of the tree.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeightUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeHeight\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.TreeDiameter\">\n            <summary>\n            Gets the tree diameter.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameter\">\n            <summary>\n            Gets the measured tree diameter.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameterUnits\">\n            <summary>\n            Gets the units of the <see cref=\"P:NmeaParser.Nmea.LaserRange.Trimble.Ptnlb.MeasuredTreeDiameter\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.NmeaMessageTypeAttribute\">\n            <summary>\n            Nmea message attribute type used on concrete <see cref=\"T:NmeaParser.Nmea.NmeaMessage\"/> implementations.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessageTypeAttribute.#ctor(System.String)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.Nmea.NmeaMessageTypeAttribute\"/> class.\n            </summary>\n            <param name=\"nmeaType\">The type.</param>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessageTypeAttribute.NmeaType\">\n            <summary>\n            Gets or sets the NMEA message type.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.NmeaMessage\">\n            <summary>\n            NMEA Message base class.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.Parse(System.String)\">\n            <summary>\n            Parses the specified NMEA message.\n            </summary>\n            <param name=\"message\">The NMEA message string.</param>\n            <returns></returns>\n            <exception cref=\"T:System.ArgumentException\">\n            Invalid nmea message: Missing starting character '$'\n            or checksum failure\n            </exception>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.MessageParts\">\n            <summary>\n            Gets the NMEA message parts.\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.MessageType\">\n            <summary>\n            Gets the NMEA type id for the message.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n            <remarks>\n            Implement this method to create a custom NMEA message.\n            </remarks>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.NmeaMessage.ToString\">\n            <summary>\n            Returns a <see cref=\"T:System.String\" /> that represents this instance.\n            </summary>\n            <returns>\n            A <see cref=\"T:System.String\" /> that represents this instance.\n            </returns>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.NmeaMessage.Checksum\">\n            <summary>\n            Gets the checksum value of the message.\n            </summary>\n        </member>\n        <member name=\"T:NmeaParser.Nmea.UnknownMessage\">\n            <summary>\n            Represents an unknown message type\n            </summary>\n        </member>\n        <member name=\"P:NmeaParser.Nmea.UnknownMessage.Values\">\n            <summary>\n            Gets the nmea value array.\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.Nmea.UnknownMessage.OnLoadMessage(System.String[])\">\n            <summary>\n            Called when the message is being loaded.\n            </summary>\n            <param name=\"message\">The NMEA message values.</param>\n        </member>\n        <member name=\"T:NmeaParser.StreamDevice\">\n            <summary>\n            Generic stream device\n            </summary>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.#ctor(System.IO.Stream)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:NmeaParser.StreamDevice\"/> class.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.OpenStreamAsync\">\n            <summary>\n            Opens the stream asynchronous.\n            </summary>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.CloseStreamAsync(System.IO.Stream)\">\n            <summary>\n            Closes the stream asynchronous.\n            </summary>\n            <param name=\"stream\">The stream.</param>\n            <returns></returns>\n        </member>\n        <member name=\"M:NmeaParser.StreamDevice.Dispose(System.Boolean)\">\n            <summary>\n            Releases unmanaged and - optionally - managed resources.\n            </summary>\n            <param name=\"disposing\"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\n        </member>\n    </members>\n</doc>\n"
  },
  {
    "path": "src/Generator/ArgumentParser.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Collections.Specialized;\r\nusing System.Text;\r\nusing System.Text.RegularExpressions;\r\n\r\nnamespace Generator\r\n{\r\n    static class ArgumentParser\r\n    {\r\n        // Based on https://www.codeproject.com/Articles/3111/C-NET-Command-Line-Arguments-Parser\r\n        public static StringDictionary Parse(string[] arguments)\r\n        {\r\n            StringDictionary Parameters = new StringDictionary();\r\n            Regex Spliter = new Regex(@\"^-{1,2}|^/|=|:\",\r\n                RegexOptions.IgnoreCase | RegexOptions.Compiled);\r\n\r\n            Regex Remover = new Regex(@\"^['\"\"]?(.*?)['\"\"]?$\",\r\n                RegexOptions.IgnoreCase | RegexOptions.Compiled);\r\n\r\n            string Parameter = null;\r\n            string[] Parts;\r\n\r\n            // Valid parameters forms:\r\n            // {-,/,--}param{ ,=,:}((\",')value(\",'))\r\n            // Examples: \r\n            // -param1 value1 --param2 /param3:\"Test-:-work\" \r\n            //   /param4=happy -param5 '--=nice=--'\r\n            foreach (string Txt in arguments)\r\n            {\r\n                // Look for new parameters (-,/ or --) and a\r\n                // possible enclosed value (=,:)\r\n                Parts = Spliter.Split(Txt, 3);\r\n\r\n                switch (Parts.Length)\r\n                {\r\n                    // Found a value (for the last parameter \r\n                    // found (space separator))\r\n                    case 1:\r\n                        if (Parameter != null)\r\n                        {\r\n                            if (!Parameters.ContainsKey(Parameter))\r\n                            {\r\n                                Parts[0] =\r\n                                    Remover.Replace(Parts[0], \"$1\");\r\n\r\n                                Parameters.Add(Parameter, Parts[0]);\r\n                            }\r\n                            Parameter = null;\r\n                        }\r\n                        // else Error: no parameter waiting for a value (skipped)\r\n                        break;\r\n\r\n                    // Found just a parameter\r\n                    case 2:\r\n                        // The last parameter is still waiting. \r\n                        // With no value, set it to true.\r\n                        if (Parameter != null)\r\n                        {\r\n                            if (!Parameters.ContainsKey(Parameter))\r\n                                Parameters.Add(Parameter, \"true\");\r\n                        }\r\n                        Parameter = Parts[1];\r\n                        break;\r\n\r\n                    // Parameter with enclosed value\r\n                    case 3:\r\n                        // The last parameter is still waiting. \r\n                        // With no value, set it to true.\r\n                        if (Parameter != null)\r\n                        {\r\n                            if (!Parameters.ContainsKey(Parameter))\r\n                                Parameters.Add(Parameter, \"true\");\r\n                        }\r\n\r\n                        Parameter = Parts[1];\r\n\r\n                        // Remove possible enclosing characters (\",')\r\n                        if (!Parameters.ContainsKey(Parameter))\r\n                        {\r\n                            Parts[2] = Remover.Replace(Parts[2], \"$1\");\r\n                            Parameters.Add(Parameter, Parts[2]);\r\n                        }\r\n\r\n                        Parameter = null;\r\n                        break;\r\n                }\r\n            }\r\n            if (Parameter != null)\r\n            {\r\n                if (!Parameters.ContainsKey(Parameter))\r\n                    Parameters.Add(Parameter, \"true\");\r\n            }\r\n            return Parameters;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/Generator.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net6.0</TargetFramework>\n    <LangVersion>latest</LangVersion>\n    <PackAsTool>true</PackAsTool>\n    <PackageTypes>DotnetTool,DotNetCliTool</PackageTypes>\n    <ToolCommandName>generateomd</ToolCommandName>\n    <PackageOutputPath>./../nupkg</PackageOutputPath>\n    <PackageId>dotMorten.OmdGenerator</PackageId>\n    <Version>1.5.2</Version>\n    <Authors>Morten Nielsen</Authors>\n    <Product>OMD Generator</Product>\n    <Description>Automatically generates an HTML Document with an object model diagram for your C# library&lt;</Description>\n    <Copyright>Copyright © 2018 Morten Nielsen</Copyright>\n    <PackageProjectUrl>https://github.com/dotMorten/DotNetOMDGenerator</PackageProjectUrl>\n    <RepositoryUrl>https://github.com/dotMorten/DotNetOMDGenerator</RepositoryUrl>\n    <PackageTags>OMD Diagram CSharp Roslyn</PackageTags>\n    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>\n    <AssemblyName>generateomd</AssemblyName>\n    <RollForward>Major</RollForward>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Remove=\"Generators\\OMDGenerator.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Remove=\"dotMorten.OmdGenerator.targets\" />\n    <None Remove=\"Generators\\HtmlOmdFooter.html\" />\n    <None Remove=\"Generators\\HtmlOmdHeader.html\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Include=\"dotMorten.OmdGenerator.targets\" Pack=\"true\" PackagePath=\"build\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <EmbeddedResource Include=\"Generators\\HtmlOmdFooter.html\" />\n    <EmbeddedResource Include=\"Generators\\HtmlOmdHeader.html\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"2.7.0\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp.Workspaces\" Version=\"2.7.0\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.Workspaces.Common\" Version=\"2.7.0\" />\n    <PackageReference Include=\"NuGet.Configuration\" Version=\"6.14.0\" />\n    <PackageReference Include=\"NuGet.Protocol\" Version=\"6.14.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Generator/Generators/HtmlOmdFooter.html",
    "content": "﻿<br /><br /><hr style=\"clear:both;\" />\nGenerated with <a href=\"https://github.com/dotMorten/DotNetOMDGenerator\">.NET Object Model Diagram Generator</a><br /><br />\n<script>var acc = document.getElementsByClassName(\"expander\"); var i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener(\"click\", function () { var active = this.classList.toggle(\"active\"); var panel = this.nextElementSibling; panel.classList.toggle(\"collapse\"); }); }</script>\n</body>\n</html>"
  },
  {
    "path": "src/Generator/Generators/HtmlOmdGenerator.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing Microsoft.CodeAnalysis;\r\n\r\nnamespace Generator.Generators\r\n{\r\n    internal class HtmlOmdGenerator : ICodeGenerator, ICodeDiffGenerator\r\n    {\r\n        private System.IO.StreamWriter sw;\r\n        private List<INamedTypeSymbol> allSymbols;\r\n        private List<INamedTypeSymbol> oldSymbols;\r\n        private string currentNamespace;\r\n\r\n        public void Initialize(List<INamedTypeSymbol> allSymbols) => Initialize(allSymbols, null);\r\n\r\n        public void Initialize(List<INamedTypeSymbol> allSymbols, List<INamedTypeSymbol> oldSymbols)\r\n        {\r\n            this.allSymbols = allSymbols;\r\n            this.oldSymbols = oldSymbols;\r\n            var outLocation = GeneratorSettings.OutputLocation;\r\n            if (string.IsNullOrEmpty(new System.IO.FileInfo(outLocation).Extension))\r\n                outLocation += \".html\";\r\n            sw = new System.IO.StreamWriter(outLocation);\r\n            using (var s = typeof(HtmlOmdGenerator).Assembly.GetManifestResourceStream(\"Generator.Generators.HtmlOmdHeader.html\"))\r\n            {\r\n                s.CopyTo(sw.BaseStream);\r\n            }\r\n        }\r\n\r\n        public void Complete()\r\n        {\r\n            if (currentNamespace != null)\r\n            {\r\n                //close the last namespace section\r\n                sw.WriteLine(\"</div></section>\");\r\n                sw.Flush();\r\n            }\r\n            sw.WriteLine(\"<hr style=\\\"clear: both; \\\" />Command line:<br/>\");\r\n            sw.WriteLine(\"<pre style=\\\"padding: 5px; background-color:#eee\\\">\");\r\n            sw.WriteLine(\"dotnet tool install --global dotMorten.OmdGenerator\");\r\n            sw.WriteLine(\"generateomd \" + Environment.CommandLine);\r\n            sw.WriteLine(\"</pre>\");\r\n            sw.Flush();\r\n            using (var s = typeof(HtmlOmdGenerator).Assembly.GetManifestResourceStream(\"Generator.Generators.HtmlOmdFooter.html\"))\r\n            {\r\n                s.CopyTo(sw.BaseStream);\r\n            }\r\n            sw.Flush();\r\n            sw.Close();\r\n            sw.Dispose();\r\n        }\r\n\r\n        public void WriteClass(INamedTypeSymbol type) => WriteClass(type, null);\r\n\r\n        public void WriteClass(INamedTypeSymbol type, INamedTypeSymbol oldType = null)\r\n        {\r\n            WriteType(type, oldType);\r\n        }\r\n\r\n        public void WriteType(INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            bool isTypeRemoved = type == null && oldType != null;\r\n            bool isTypeNew = type != null && oldType == null;\r\n            if (isTypeRemoved)\r\n                type = oldType;\r\n\r\n            string kind = \"\";\r\n            switch (type.TypeKind)\r\n            {\r\n                case TypeKind.Struct:\r\n                case TypeKind.Class: kind = \"class\"; break;\r\n                case TypeKind.Delegate: kind = \"delegate\"; break;\r\n                case TypeKind.Enum: kind = \"enum\"; break;\r\n                case TypeKind.Interface: kind = \"interface\"; break;\r\n                default:\r\n                    return; //Not supported\r\n            }\r\n            //When loading assemblies the kind isn't recognized\r\n            if(kind == \"class\" && type.BaseType.GetFullTypeName() ==\"System.Enum\")\r\n            {\r\n                kind = \"enum\";\r\n            }\r\n\r\n            var nsname = type.GetFullNamespace();\r\n            if (nsname != currentNamespace)\r\n            {\r\n                if(currentNamespace != null)\r\n                {\r\n                    //close the current namespace section\r\n                    sw.WriteLine(\"</div></section>\");\r\n                }\r\n                sw.WriteLine($\"<section id='{nsname}'>\");\r\n                currentNamespace = nsname;\r\n                sw.WriteLine($\"<h3 class='expander active'>{nsname}</h3><div>\");\r\n            }\r\n            bool wasObsoleted = type.IsObsolete() && oldType?.IsObsolete() != true;\r\n            sw.WriteLine($\"<div class='objectBox{(isTypeRemoved ? \" typeRemoved\" : \"\")}{(!isTypeNew ? \" typeExisting\" : \"\")}' id='{type.GetFullTypeName()}'>\");\r\n            bool isEmpty = true;\r\n            var memberBuilder = new StringBuilder();\r\n            {\r\n                //List out members\r\n                if (type.GetConstructors(oldType).Any())\r\n                {\r\n                    isEmpty = false;\r\n\r\n                    memberBuilder.AppendLine($\"<div class='members'>\");\r\n                    if (type.TypeKind != TypeKind.Delegate)\r\n                        memberBuilder.AppendLine($\"<h4>Constructors</h4>\");\r\n                    memberBuilder.AppendLine($\"<ul>\");\r\n                    foreach (var method in type.GetConstructors(oldType))\r\n                    {\r\n                        var str = FormatMember(method.symbol);\r\n                        if (method.wasRemoved)\r\n                            str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                        else if(method.wasObsoleted)\r\n                            str = $\"<span class='obsolete'>{str}</span>\";\r\n                        memberBuilder.AppendLine($\"{GetIcon(method.symbol, str)}\");\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul></div>\");\r\n                }\r\n                if (type.GetProperties(oldType).Any())\r\n                {\r\n                    isEmpty = false;\r\n                    memberBuilder.AppendLine($\"<div class='members'><h4>Properties</h4><ul>\");\r\n                    foreach (var method in type.GetProperties(oldType))\r\n                    {\r\n                        var str = FormatMember(method.symbol);\r\n                        if (method.wasRemoved)\r\n                            str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                        else if (method.wasObsoleted)\r\n                            str = $\"<span class='obsolete'>{str}</span>\";\r\n                        memberBuilder.AppendLine($\"{GetIcon(method.symbol, str)}\");\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul></div>\");\r\n                }\r\n                var methods = type.GetMethods(oldType).ToList();\r\n                if (methods.Any())\r\n                {\r\n                    isEmpty = false;\r\n                    memberBuilder.AppendLine($\"<div class='members'><h4>Methods</h4><ul>\");\r\n                    foreach (var method in methods)\r\n                    {\r\n                        var str = FormatMember(method.symbol);\r\n                        if (method.wasRemoved)\r\n                            str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                        else if (method.wasObsoleted)\r\n                            str = $\"<span class='obsolete'>{str}</span>\";\r\n                        memberBuilder.AppendLine($\"{GetIcon(method.symbol, str)}\");\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul></div>\");\r\n                }\r\n                if (type.GetEvents(oldType).Any())\r\n                {\r\n                    isEmpty = false;\r\n                    memberBuilder.AppendLine($\"<div class='members'><h4>Events</h4><ul>\");\r\n                    foreach (var method in type.GetEvents(oldType))\r\n                    {\r\n                        var str = FormatMember(method.symbol);\r\n                        if (method.wasRemoved)\r\n                            str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                        else if (method.wasObsoleted)\r\n                            str = $\"<span class='obsolete'>{str}</span>\";\r\n                        memberBuilder.AppendLine($\"{GetIcon(method.symbol, str)}\");\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul></div>\");\r\n                }\r\n                if (kind != \"enum\" && type.GetFields(oldType).Any())\r\n                {\r\n                    isEmpty = false;\r\n                    memberBuilder.AppendLine($\"<div class='members'><h4>Fields</h4><ul>\");\r\n                    foreach (var method in type.GetFields(oldType))\r\n                    {\r\n                        var str = FormatMember(method.symbol);\r\n                        if (method.wasRemoved)\r\n                            str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                        else if (method.wasObsoleted)\r\n                            str = $\"<span class='obsolete'>{str}</span>\";\r\n                        memberBuilder.AppendLine($\"{GetIcon(method.symbol, str)}\");\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul></div>\");\r\n                }\r\n                if (kind == \"enum\")\r\n                {\r\n                    isEmpty = false;\r\n                    memberBuilder.AppendLine(\"<ul class='members'>\");\r\n                    if (type.TypeKind == TypeKind.Enum)\r\n                    {\r\n                        foreach (var e in type.GetEnums(oldType).OrderBy(f => f.symbol.ConstantValue))\r\n                        {\r\n                            string str = Briefify(e.symbol);\r\n                            if (e.symbol.HasConstantValue)\r\n                                str += \" = \" + e.symbol.ConstantValue?.ToString();\r\n                            if (e.wasRemoved)\r\n                                str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                            else if (e.wasObsoleted)\r\n                                str = $\"<span class='obsolete'>{str}</span>\";\r\n                            memberBuilder.AppendLine($\"{GetIcon(e.symbol, str)}\");\r\n                        }\r\n                    }\r\n                    else if(type.TypeKind == TypeKind.Class)\r\n                    {\r\n                        foreach (var e in type.GetFields(oldType).Where(f=>f.symbol.HasConstantValue).OrderBy(f=>f.symbol.ConstantValue))\r\n                        {\r\n                            if (!e.symbol.HasConstantValue) continue;\r\n                            var str = Briefify(e.symbol) + \" = \" + e.symbol.ConstantValue?.ToString();\r\n                            if (e.wasRemoved)\r\n                                str = $\"<span class='memberRemoved'>{str}</span>\";\r\n                            else if (e.wasObsoleted)\r\n                                str = $\"<span class='obsolete'>{str}</span>\";\r\n                            memberBuilder.AppendLine($\"{GetIcon(e.symbol, str)}\");\r\n                        }\r\n                    }\r\n                    memberBuilder.AppendLine(\"</ul>\");\r\n                }\r\n            }\r\n\r\n            var symbols = Generator.GetChangedSymbols(\r\n                type == oldType ? Enumerable.Empty<INamedTypeSymbol>() : type.GetAllNestedTypes(),\r\n                oldType == null ? Enumerable.Empty<INamedTypeSymbol>() : oldType.GetAllNestedTypes());\r\n            if (isEmpty && symbols.Any())\r\n            {\r\n                isEmpty = false;\r\n            }\r\n            sw.WriteLine($\"<div class='header {kind}{(isEmpty ? \" noMembers\" : \"\")}{(wasObsoleted ? \" obsolete\" : \"\")}'>\");\r\n\r\n            //Write class name + Inheritance\r\n            var brief = type.GetDescription();\r\n            sw.Write($\"<span \");\r\n            if (!string.IsNullOrEmpty(brief))\r\n                sw.Write($\"title=\\\"{System.Web.HttpUtility.HtmlEncode(brief)}\\\"\");\r\n            sw.Write('>');\r\n            if (!isTypeNew && !isTypeRemoved) sw.Write($\"<span class='existing'>\");\r\n            sw.Write(System.Web.HttpUtility.HtmlEncode(type.Name));\r\n            if (!isTypeNew && !isTypeRemoved) sw.Write(\"</span>\");\r\n            if (type.BaseType != null && (type.BaseType.Name != \"Object\" || type.BaseType.ToDisplayString() != oldType?.BaseType.ToDisplayString()) && kind != \"enum\")\r\n            {\r\n                if (oldType == null || type.BaseType.ToDisplayString() != oldType.BaseType.ToDisplayString())\r\n                {\r\n                    if (oldType != null && oldType.BaseType.Name != \"Object\")\r\n                    {\r\n                        sw.Write($\" : <span class='memberRemoved'>{FormatType(oldType.BaseType)}</span>\");\r\n                        if (type.BaseType.Name != \"Object\") sw.Write($\"{FormatType(type.BaseType)}\");\r\n                    }\r\n                    else if (type.BaseType.Name != \"Object\")\r\n                        sw.Write($\" : {FormatType(type.BaseType)}\");\r\n                }\r\n            }\r\n            else if(kind == \"enum\")\r\n            {\r\n                if(type.TypeKind == TypeKind.Enum)\r\n                {\r\n                    INamedTypeSymbol enumType = type.EnumUnderlyingType;\r\n                    INamedTypeSymbol oldEnumType = oldType?.EnumUnderlyingType;\r\n                    if (oldEnumType == null || enumType.ToDisplayString() != oldEnumType.ToDisplayString())\r\n                    {\r\n                        sw.Write(\" : \");\r\n                        if (oldEnumType != null)\r\n                        {\r\n                            sw.Write($\"<span class='memberRemoved'>{FormatType(oldEnumType)}</span>\");\r\n                        }\r\n                        sw.Write(FormatType(enumType));\r\n                    }\r\n                }\r\n                else if (type.TypeKind == TypeKind.Class) //Happens when analyzing assemblies\r\n                {\r\n                    var fields = type.GetFields();\r\n                    var name = fields.FirstOrDefault()?.ConstantValue?.GetType().FullName;\r\n                    var oldname = oldType?.GetFields().FirstOrDefault()?.ConstantValue?.GetType().FullName;\r\n                    if (oldname == null || name != oldname)\r\n                    {\r\n                        sw.Write(\" : \");\r\n                        if (oldname != null)\r\n                        {\r\n                            sw.Write($\"<span class='memberRemoved'>oldname</span>\");\r\n                        }\r\n                        sw.Write(name);\r\n                    }\r\n                }\r\n            }\r\n            sw.WriteLine(\"</span>\");\r\n\r\n            //Document interfaces\r\n            if (type.GetInterfaces(oldType).Any())\r\n            {\r\n                isEmpty = false;\r\n                sw.Write(\"<br/>Implements \");\r\n                int i = 0;\r\n                foreach(var iface in type.GetInterfaces(oldType))\r\n                {\r\n                    if (i > 0)\r\n                        sw.Write(\", \");\r\n                    if (iface.wasRemoved) sw.Write(\"<span class='memberRemoved'>\");\r\n                    sw.Write(FormatType(iface.symbol));\r\n                    if (iface.wasRemoved) sw.Write(\"</span>\");\r\n                    i++;\r\n                }\r\n            }\r\n            sw.WriteLine(\"</div>\"); //End header box\r\n\r\n            sw.Write(memberBuilder.ToString());\r\n\r\n            if (symbols.Any())\r\n            {\r\n                sw.WriteLine($\"<div class='members'><h4>Nested Types</h4></div>\");\r\n                foreach (var t in symbols)\r\n                {\r\n                    WriteType(t.newSymbol, t.oldSymbol);\r\n                }\r\n            }\r\n\r\n            sw.WriteLine(\"</div>\");\r\n            sw.Flush();\r\n        }\r\n\r\n        private string GetIcon(ISymbol type, string content)\r\n        {\r\n            string icon = \"\";\r\n            if (type.DeclaredAccessibility == Accessibility.Public)\r\n                icon = \"pub\";\r\n            else if (type.DeclaredAccessibility == Accessibility.Protected)\r\n                icon = \"prot\";\r\n            else if (type.DeclaredAccessibility == Accessibility.Private)\r\n                icon = \"priv\";\r\n            else if (type.DeclaredAccessibility == Accessibility.ProtectedAndFriend)\r\n                icon = \"privprot\";\r\n            if (type.Kind == SymbolKind.Method)\r\n                icon += \"method\";\r\n            else if (type.Kind == SymbolKind.Property)\r\n                icon += \"property\";\r\n            else if (type.Kind == SymbolKind.Field)\r\n                icon += \"field\";\r\n            else if (type.Kind == SymbolKind.Event)\r\n                icon += \"event\";\r\n            if(type.IsStatic && (type.ContainingType?.TypeKind != TypeKind.Enum && !(type.ContainingType?.TypeKind == TypeKind.Class && type.ContainingType?.BaseType?.GetFullTypeName() == \"System.Enum\")))\r\n            {\r\n                content = \"<span class='static'></span>\" + content;\r\n            }\r\n            if (icon == \"\")\r\n                return content;\r\n            return $\"<li class='{icon}'>{content}</li>\";\r\n        }\r\n\r\n        public void WriteEnum(INamedTypeSymbol enm) => WriteEnum(enm, null);\r\n        public void WriteEnum(INamedTypeSymbol enm, INamedTypeSymbol oldType = null)\r\n        {\r\n            WriteType(enm, oldType);\r\n        }\r\n\r\n        public void WriteInterface(INamedTypeSymbol iface) => WriteInterface(iface, null);\r\n        public void WriteInterface(INamedTypeSymbol iface, INamedTypeSymbol oldType = null)\r\n        {\r\n            WriteType(iface, oldType);\r\n        }\r\n        public void WriteDelegate(INamedTypeSymbol del) => WriteDelegate(del, null);\r\n\r\n        public void WriteDelegate(INamedTypeSymbol del, INamedTypeSymbol oldDel = null)\r\n        {\r\n            WriteType(del, oldDel);\r\n        }\r\n\r\n        private string FormatType(ITypeSymbol type)\r\n        {\r\n            var f = SymbolDisplayFormat.MinimallyQualifiedFormat;\r\n            f.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters);\r\n            var parts = type.ToDisplayParts(f);\r\n            if (parts.Length > 1)\r\n            {\r\n                string t = \"\";\r\n                foreach (var p in parts)\r\n                {\r\n                    if (p.Kind == SymbolDisplayPartKind.Punctuation || p.Kind == SymbolDisplayPartKind.Space)\r\n                        t += System.Web.HttpUtility.HtmlEncode(p.ToString());\r\n                    else if (p.Symbol is ITypeSymbol its)\r\n                        t += LinkifyType(its, false);\r\n                    else\r\n                    {\r\n\r\n                    }\r\n                }\r\n                return t;\r\n            }\r\n            else {\r\n                return LinkifyType(type);\r\n            }\r\n        }\r\n\r\n        private string LinkifyType(ITypeSymbol type, bool includeGeneric = true)\r\n        {\r\n            if(type is INamedTypeSymbol nts && nts.IsGenericType && !includeGeneric)\r\n            {\r\n                type = nts.OriginalDefinition;\r\n            }\r\n            var name = includeGeneric ? type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) : type.Name;\r\n            if (allSymbols.Contains(type))\r\n                return $\"<a href='#{type.GetFullTypeName()}'>{System.Web.HttpUtility.HtmlEncode(name)}</a>\";\r\n            else \r\n                return Briefify(type, name);\r\n        }\r\n\r\n        private static string AccessorToString(Accessibility a)\r\n        {\r\n            switch(a)\r\n            {\r\n                case Accessibility.Public:\r\n                    return \"public\";\r\n                case Accessibility.Private:\r\n                    return \"private\";\r\n                case Accessibility.Internal:\r\n                    return \"internal\";\r\n                case Accessibility.Protected:\r\n                    return \"protected\";\r\n                case Accessibility.ProtectedOrInternal:\r\n                    return GeneratorSettings.ShowInternalMembers ? \"protected internal\" : \"protected\";\r\n                case Accessibility.ProtectedAndInternal:\r\n                    return \"private protected\";\r\n                default:\r\n                    return string.Empty;\r\n            }\r\n        }\r\n\r\n        private string FormatMember(ISymbol member)\r\n        {\r\n            var brief = member.GetDescription();\r\n            var name = member.Name;\r\n            if (name == \".ctor\")\r\n            {\r\n                name = member.ContainingType.Name;\r\n            }\r\n            name = Briefify(member, name);\r\n\r\n            if (member is IPropertySymbol p)\r\n            {\r\n                name += \" { \";\r\n                if (p.GetMethod != null && ((p.GetMethod.DeclaredAccessibility == Accessibility.Public || p.GetMethod.DeclaredAccessibility == Accessibility.Protected || p.GetMethod.DeclaredAccessibility == Accessibility.ProtectedOrInternal) ||\r\n                    (GeneratorSettings.ShowInternalMembers && p.GetMethod.DeclaredAccessibility == Accessibility.Internal || p.GetMethod.DeclaredAccessibility == Accessibility.ProtectedAndInternal) ||\r\n                    (GeneratorSettings.ShowPrivateMembers && p.GetMethod.DeclaredAccessibility == Accessibility.Private)))\r\n                {\r\n                    if(p.DeclaredAccessibility != p.GetMethod.DeclaredAccessibility)\r\n                    { \r\n                        name += AccessorToString(p.GetMethod.DeclaredAccessibility) + \" \";\r\n                    }\r\n                    name += \"get; \";\r\n                }\r\n                if (p.SetMethod != null && ((p.SetMethod.DeclaredAccessibility == Accessibility.Public || p.SetMethod.DeclaredAccessibility == Accessibility.Protected || p.SetMethod.DeclaredAccessibility == Accessibility.ProtectedOrInternal) ||\r\n                   (GeneratorSettings.ShowInternalMembers && p.SetMethod.DeclaredAccessibility == Accessibility.Internal || p.SetMethod.DeclaredAccessibility == Accessibility.ProtectedAndInternal) ||\r\n                   (GeneratorSettings.ShowPrivateMembers && p.SetMethod.DeclaredAccessibility == Accessibility.Private)))\r\n                {\r\n                    if (p.DeclaredAccessibility != p.SetMethod.DeclaredAccessibility)\r\n                    {\r\n                        name += AccessorToString(p.SetMethod.DeclaredAccessibility) + \" \";\r\n                    }\r\n                    name += \"set; \";\r\n                }\r\n\r\n                name += \"} : \" + FormatType(p.Type);\r\n            }\r\n            else if (member is IMethodSymbol m)\r\n            {\r\n                if (m.TypeArguments.Any())\r\n                {\r\n                    name += System.Web.HttpUtility.HtmlEncode(\"<\" + string.Join(\", \", m.TypeArguments.Select(t => t.ToDisplayString())) + \">\");\r\n                }\r\n\r\n                name += \"(\";\r\n                name += string.Join(\", \", m.Parameters.Select(pr => FormatType(pr.Type) + \" \" + Briefify(pr) + (pr.HasExplicitDefaultValue ? (\" = \" + (pr.ExplicitDefaultValue?.ToString() ?? \"null\")) : \"\")));\r\n                name += \")\";\r\n                if (!m.ReturnsVoid)\r\n                {\r\n                    name += \" : \" + FormatType(m.ReturnType);\r\n                }\r\n            }\r\n            else if (member is IEventSymbol e)\r\n            {\r\n                name += \" : \" + FormatType(e.Type);\r\n            }\r\n            else if (member is IFieldSymbol f)\r\n            {\r\n                name += \" : \" + FormatType(f.Type);\r\n            }\r\n            return name;\r\n        }\r\n\r\n        private static string Briefify(ISymbol symbol, string content = null)\r\n        {\r\n            if (content == null)\r\n                content = symbol.Name;\r\n            var brief = symbol.GetDescription();\r\n            if (!string.IsNullOrEmpty(brief))\r\n                return $\"<span title=\\\"{System.Web.HttpUtility.HtmlEncode(brief)}\\\">{System.Web.HttpUtility.HtmlEncode(content)}</span>\";\r\n            return System.Web.HttpUtility.HtmlEncode(content);\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/Generators/HtmlOmdHeader.html",
    "content": "﻿<!DOCTYPE html>\r\n\r\n<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n    <meta charset=\"utf-8\" />\r\n    <title>OMD</title>\r\n      <style>\r\n         body { padding: 0; }\r\n\t\t ul { list-style:none; padding-left: 20px; margin-right:10px; }\r\n         .objectBox { border-style:solid; border-width:1px; margin:10px; float:left; border-radius:10px;}\r\n         .objectBox > .header { font-size:10px; padding:10px; border-radius:10px 10px 0 0;}\r\n         .objectBox > .header.noMembers { border-radius: 10px; }\r\n         .objectBox > .header > span { font-size:20px; }\r\n\t\t .class {  background: linear-gradient(to right, rgb(211, 220, 239), white);  }\r\n         .struct { background: linear-gradient(to right, rgb(211, 220, 239), white); }\r\n         .enum { background: linear-gradient(to right, rgb(221, 214, 239), white); }\r\n         .interface { background: linear-gradient(to right, rgb(231, 240, 220), white); }\r\n         .delegate { background: linear-gradient(to right, rgb(237, 218, 220), white); }\r\n         \r\n         .members > h4 { font-size:14px; background:rgb(240, 242, 239); display:block; padding:5px; margin:0; font-weight:normal; }\r\n         .typeExisting { border-color:#ddd; }\r\n\t\t .existing { opacity: .5; }\r\n         .typeRemoved { border-color:red; border-style:dashed; border-width:3px; text-decoration: line-through;border-style:dashed; border-width:3px; }\r\n         .memberRemoved { color: red; text-decoration: line-through; }\r\n         .obsolete { text-decoration: line-through; opacity:.75; }\r\n         .static { background-image: url(data:image/gif;base64,R0lGODlhDQAKAPcPAOhfF/nXxfbDqOx9Q/GbbvOvi/Klffvh0+6HUe+RYOlpJutzNPjNtvzr4v718AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAA8ALAAAAAANAAoAAAhMAB8IDJBAAYCDBxccEGgAocODAQQ+LBCAQYEBER88RCDAgcCPBB4e5PjxgYABIgEQELjwQYOTDyUOMCAgQEiHElMeLCCw4MMFBCIGBAA7); background-repeat: no-repeat; background-position: left center; margin-left:-35px; padding-left:35px; }\r\n \r\n         .members li {  background-repeat: no-repeat; padding-left:20px; background-position: left center; }\r\n         .pubevent { background-image: url(data:image/gif;base64,R0lGODlhCgAMANU3APzksP7y2ebl4u+9kOvj1Pf39vDGkunm4V5HMIyCXOLd1a6XYN7YzpeDU+fQiZVvH+qwf6eUYFhTS8/Bofbv0/jz3vv6+Nva1Ih6SuilfObPienl36CLRsC5pKyXamtPKWpiSN3Mjp94HciyeIxoIumqfuXg1+mggefj3q2CIPXAbsq+n93FguXh2vn048a4kPLMlHlsRu7Cif/kf/rRdufIWeGHgv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADcALAAAAAAKAAwAAAZXwNvNFXJoWCPPRFgDzGQZm6Rwq9QCtJINJGACaBAbpnujXFU2zkV4q81msMHJhtjcFo1Ygmb7mNgWL3wkDGw3K3wPLYYEBjYiCoY3HQMpKJI3BBEHmDdBADs=); padding-left:20px; background-position: left center; }\r\n         .protevent { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZPAOGHgt28WvjYaOfIWaOALvrRdtO4f+7AL//kf8ipX49uIu3iyubl4vDr3//PMvzksO+9kP7y2a6XYN3Mjufj3umggaaFOJVvH93FgvDo1uTbxu7blvXssnlsRvv6+Pbv0/f39u7CiaCLRu7q3oyCXMiyeMuvdWtPKefQia2CIOjIXdva1OmqfvXrrufXs5eDU/by6V5HMOnl36eUYObPicq+n8a4kFhTS8Cyj+ilfOXh2oh6Ss/Bofn046yXauvj1OXTq4xrH4xoIuLd1eqwf+Xg1/71rPLMlN7Yzp94Hfjz3mpiSPXAbunm4fDGkv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAE8ALAAAAAAQABAAAAeRgE+Cg4SFhoM9Eyg0GCU+PIdPAw8IITkANyCHSgMRBSwASwyRkwVEADujhx+dTAAiK5GSCAhHEBUAMTKCCwYmCUASLx0kBQAnRbwGHAICFi4eNsZCSIMGLUZBAQ4ENcYXOoQGGwIBAQcETgBJQ4UZCQ4C6DgQKRSHGgECBCM/M02y9KGTNSiACgUNCAqCgVBhIAA7); }\r\n         .privevent { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZYAOGHgt/j6ufIWfrRdqy3y0FLWMnQ3crR3sjO2f/kf+Pm6vDy9PzksKCrwrK7zv7y2bjA0r7H1ubl4tLX4v///4h6Suqwf21/lvXAbunm4enl38a4kGpiSJCetN3Mjldqgp94Hfbv0/n044yCXHuJneLd1bvD1IxoIubPifLMlPjz3mR2jd7YzufQide4kpinvMTM2l5widva1HWFnOilfKeUZayXaqCLRumqfsTM2e7CiW+Al4eUpVhTS++9kJeDU+mggbvF1GdRPGR2jrG6zW5SLefj3sC4nuXh2t3Fgq2CIOXg13qKociyeE9jfGN1jb3G1qu3y3lsRs/BobjB0md3kE9ie5VvH////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFgALAAAAAAQABAAAAehgFiCg4SFhoMiHi0oSU02U4dYAgwJOjQAPRSHKgIPAzgAHBKRkwMWABWjhyGdGAA3MpqHAgkJKT5AAEIaggsHEEQENT9SIwMARUuDBwEEDVBMWBvHJyyDCzkvggQ7R8dXSIQKQR0GBitDLgAgJYUGAfABExFPSkaGJgEF+xMQPBmHCARAUAABAgckIjU4ACMCFQdRrERSMONClRgfnCiIFAgAOw==); }\r\n         .privprotevent { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZYAOGHgt/j6ufIWfrRdqy3y0FLWMnQ3crR3sjO2f/kf+Pm6vDy9PzksKCrwrK7zv7y2bjA0r7H1ubl4tLX4v///4h6Suqwf21/lvXAbunm4enl38a4kGpiSJCetN3Mjldqgp94Hfbv0/n044yCXHuJneLd1bvD1IxoIubPifLMlPjz3mR2jd7YzufQide4kpinvMTM2l5widva1HWFnOilfKeUZayXaqCLRumqfsTM2e7CiW+Al4eUpVhTS++9kJeDU+mggbvF1GdRPGR2jrG6zW5SLefj3sC4nuXh2t3Fgq2CIOXg13qKociyeE9jfGN1jb3G1qu3y3lsRs/BobjB0md3kE9ie5VvH////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFgALAAAAAAQABAAAAehgFiCg4SFhoMiHi0oSU02U4dYAgwJOjQAPRSHKgIPAzgAHBKRkwMWABWjhyGdGAA3MpqHAgkJKT5AAEIaggsHEEQENT9SIwMARUuDBwEEDVBMWBvHJyyDCzkvggQ7R8dXSIQKQR0GBitDLgAgJYUGAfABExFPSkaGJgEF+xMQPBmHCARAUAABAgckIjU4ACMCFQdRrERSMONClRgfnCiIFAgAOw==); }\r\n         \r\n         .pubmethod { background-image: url(data:image/gif;base64,R0lGODlhEAALANU/AM9p0Ky1rvDV8Pfwq/qY++6l79XVrLtvvPLb8n4ufqhQqZ48nunlq/Lg8/qr+3wtffqZ+9Vv1ZZSl92Y3tNu1Pqb++zS7LW7rY01jpikruTK5OKv4uuR7KlSqnEkcu3Y7e6+7vqf+8zOrPTm9I5Gj5BOkevR64qZrtFt0pU4lvDj8O6d7/Pj86dPqPqu++Xiq6ZQp+jR6Hore+aY55ynrubM5uOs48HErOmQ6n8wgKlQqn4wf3wufHUndc+Iz////yH5BAEAAD8ALAAAAAAQAAsAAAZmwJ9wSET4VMTk0GjzsZREgQ/k4vgaxIEhcPr5Ng4CAecbQX+wQ6FCgMxKvwHDcAtkfi2UOrSS8M4dABEHEyQLCUIDLyIXND8aCigUOwsYD2c/MToACSkyApg/Hwo5PSahQhYeNUJBADs=); }\r\n         .protmethod { background-image: url(data:image/gif;base64,R0lGODlhEQAQALMPAKdUqPCf8e3lq+rS68+0ePXq8+3l06WvrfXGMIIxg6SBMI5tIfjYaN28Ws+Iz////yH5BAEAAA8ALAAAAAARABAAAARk8MlJ33ClankD3tQ1BF5GCcJxFA7pfiDQugEgoan6yIALJKCdY+j4AR8GgpIwsABkiSgwKWAwFALOU9okoBYNhGIyMDYfXkYjPCYnzkgCgiE2BCWGxtV+l+jFfX4NC3x9BYR9EQA7); }\r\n         .privmethod { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZoAP///9/j6s+Iz9LX4kFLWKy3y8jO2bK7zuPm6srR3vDy9PqY+8nQ3ahQqdXVrO6l77tvvPfwq34ufrjA0r7H1qCrwvLb8u6+7uOs43UndalQqqy1rWFyiejR6Onlq+vR67jB0sTM2uTK5JinvLxwvVVnf6pVq+aY5/Lg89Nu1Ky0rq1crt2Y3o5Gj5ZSl2d3kN+w31dqgtVv1fDV8I01jtWY1ebM5pikrn4wf9Fq0oqZrnWFnHwufHEkcumQ6o2brfqu++6d72R2jZ88n/v7/Pqb+5U4lstnzJ+qu3wtffTm9NJr038wgPPj89PY2/DU8OzS7JBOkXore09jfLvD1L3G1l5wie3Y7fqr+/Dj8G1/lmR2jvqZ+5w8neKv4vqf++uR7MHErKpYq5CetNFt0nqInau3y29/lP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAGgALAAAAAAQABAAAAe4gGiCg4QWAlmEiYOGGAJNioRPAhdAYDUohBEOKjoAMF5YCws+AkoAkGIQD0ULXCdRABEeDmEbN2gmZKpfQS48p4orOTIkLC1dEgAKCRMHBU5oIg1LKThDNEkACQEFFQNIgh0aRxJGUjMKAyMAAFU/CoJXDUwZH2gIA2MMDEJbCINQetgQxCCAwQADKJSBhIZKAAIQB0w4w7BAAAMEDBg4wIFhhQQhKIA4YKYEQwQ7tLywEmMKEYaBAAA7); }\r\n         .privprotmethod { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZoAP///9/j6s+Iz9LX4kFLWKy3y8jO2bK7zuPm6srR3vDy9PqY+8nQ3ahQqdXVrO6l77tvvPfwq34ufrjA0r7H1qCrwvLb8u6+7uOs43UndalQqqy1rWFyiejR6Onlq+vR67jB0sTM2uTK5JinvLxwvVVnf6pVq+aY5/Lg89Nu1Ky0rq1crt2Y3o5Gj5ZSl2d3kN+w31dqgtVv1fDV8I01jtWY1ebM5pikrn4wf9Fq0oqZrnWFnHwufHEkcumQ6o2brfqu++6d72R2jZ88n/v7/Pqb+5U4lstnzJ+qu3wtffTm9NJr038wgPPj89PY2/DU8OzS7JBOkXore09jfLvD1L3G1l5wie3Y7fqr+/Dj8G1/lmR2jvqZ+5w8neKv4vqf++uR7MHErKpYq5CetNFt0nqInau3y29/lP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAGgALAAAAAAQABAAAAe4gGiCg4QWAlmEiYOGGAJNioRPAhdAYDUohBEOKjoAMF5YCws+AkoAkGIQD0ULXCdRABEeDmEbN2gmZKpfQS48p4orOTIkLC1dEgAKCRMHBU5oIg1LKThDNEkACQEFFQNIgh0aRxJGUjMKAyMAAFU/CoJXDUwZH2gIA2MMDEJbCINQetgQxCCAwQADKJSBhIZKAAIQB0w4w7BAAAMEDBg4wIFhhQQhKIA4YKYEQwQ7tLywEmMKEYaBAAA7); }\r\n\r\n         .pubproperty { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZ9AKKvxP/////9+0ZOVH2d3//rbqykj/b////taE1PVOjw/MHI0cHI0nBhSktPUnBhS/7//y4hAkxPUvnhcjMnFVOsQVlNV/3+/pmPeu3r5+LNeuz5/9+yMsSTFT+XKcjP2d7BYU86MNbl/9DIwtLi+Liso1t4We/0+3N1fImSp0GeMuq7MWBcXfbbaZWEU4BrV87Kwvnjf+Xk38ve/fL2/cDH0WdgUqq62s3Iv6TF/1FmQJm2k4XMheHw/6TTmuyoEffdatLq/zKMGPj7/qOXgIR1XhsQC4BxXClmHNzp/4mcadapLubu++Pt/39tW/PSWLWmgUxQU/bhg5adpNDi//q6IvrrsAoHEPj6/VA9QWVWT+3HS66YWH3BcLfK8dXq//ricvz+/qaiX/z+/45iFEtOUd7p+qytsPn7/3JcQcLJ0/LPVty9VN3Z1EtLTqCWgIyQUO3DQPTXZ7nJ5YtyUcS4ldPZ45OFc+np4uXThsiZHU1RVv/QH////wAAAAAAACH5BAEAAH0ALAAAAAAQABAAAAe+gH2Cg4SFhSV1bVBEbxh3Rzg+XYQjVk4FmGBybHRKPIQZLwhcBRNAa1tVYhUErTcGMS4IIS1PcSs/cCoEOXMGUg8aNghZHHodZDoeBF4GeQ8pDSAWfBRXEVomQgsBeEUyATANS0YsU4I7SNwCAgEBYWdpdk0DhDUB7AEXQzQKCkn1BqkJAAAAhIIIRQQUxACfgDFYTjAxQ4LKwj4NC6JBWHDGxQ8OD4jc0ONLkIso3CRYuSeKAwkOylw0RHNQIAA7); }\r\n         .protproperty { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeKAP///6KvxP/9+/jYaN28WqOALn2d39O4f//rbk1PVO7AL6ykj//taPb////PMnBhS/Dr349uIktPUsHI0XBhSsipX8HI0pmPesSTFeXTq87KwpWEU4BxXO3HS/j7/padpDKMGO7q3omSpylmHFt4Wf7//4BrV+Xk3+XThnJcQVFmQKe+pOjIXfz+/ktLTt3Z1FA9QfTXZ/bhg+/0+/fdavn7/8uvdeyoEaq62uHw/4mcaZOFc66YWN7BYWdgUsDH0a2urLnJ5dDIwv71rOzjqE86ME1RVvby6UxQUwoHEPnhcvLPVmVWT/rrsMiZHYxrH+3r5/rics3Iv+fXs1OsQdapLj+XKRsQC/q6Iunp4uLNellNV0xPUn9tW9y9VIR1Xvnjf+z5/zMnFcLJ07fK8fPSWMS4lXN1fPj6/YXMhaOXgPbbacbMxi4hAqCWgO3DQPLqsmBcXevhzerZleDayLWmgcjP2fL2/f3+/qbBrqytsN+yMv/QH45iFItyUaaFONTNuvz+/7iso+bu+6aiX+q7MUGeMpy4mYyQUKTF/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAIoALAAAAAAQABAAAAjsABUJVCTIzIs6atxc2MFByqE8AxUJadIFgcUoMbz40ZEmIhQTDHggUEJjSQcshKgYWIljAZgNDIqsKfOm0A1EhgwkCrJAxgMtPhjA2OMEQx8VVgyQWYDigQgKPbbwEZOkDRMSICYAyPLlBAANFKpcifNB4IoRWgUIAACghZ4UgA7YqJBB4A8AagHg8XCHzgE4Awb8maJoDIAAAUogDnCAyJAnBBwUUGQBr4BAaGYMOjBnAAECCiZXRlxjMZAKDgaElqPIjuUGsMPkYENgQIEQAs+4SMDbCBIJXCTUDh2x+EACLCJAMG78iPKBAQEAOw==); }\r\n         .privproperty { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeYAP///6KvxP/9+9/j6n2d36y3y//rbkFLWMjO2fb//6ykj//taE1PVMnQ3crR3rjA0uPm6r7H1rK7zsHI0nBhS3BhSqCrwtLX4sHI0YBxXPj7/uDl63WFnGR2jW1/lsLJ0+np4sSTFTMnFd3Z1OyoEZOFc9bY2JWEU+/0++3HS6u3y/TXZ66YWO3DQPj6/d7BYXqKoU9ie9y9VIBrV1FmQOjw/IXMhWVWTwoHEPLPVhsQC/nhcvrrsPnjf45iFImcaXN1fGBcXbvF1Liso//QH/bhg6TF/1OsQUtLTqq62vz+/zKMGOq7MZmPerfK8ffdasTM2r3G1vPSWPrick9jfLjB0sTM2fbbaUxQU1VogZinvG+Al11vh9jd5sjP2ZCetN+yMmd3kM3Iv39tW8iZHT+XKbnJ5Vt4WaaiX3JcQU1RVomSp1A9QZadpMS4leXk31dqgn1/goyQUEGeMqCWgGdgUotyUWN1jfz+/qOXgOLm7Pq6Ii4hAtapLk86MPL2/eXThqbBrs7KwuLNeqytsFlNV2R2jvn7//3+/py4me76/+Xr8+bu+8DH0ae+pClmHP7//7G6zYR1Xl5widDIwrvD1O3r57Wmgf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJgALAAAAAAQABAAAAj7ADEJxDTEzYhLeeg0KZFBTKJAAzFR4jHGgMUpK2TY+WEjoqUZC1gY2PEkR4o9aI4QWJlEQY8TC/xckdKCCQk5cwgYMaOgCIVBdRawAUMmhA8aZQg4UQCIwpoKLwoREYGDz40zSzAAACHpDQBBFfroCNJGoKNHWgUIAAAAD6E0ehw8iFRAYCMAagEg0vCnhoMBBSxEgYHpA4AAASAhDrDBihYTAApswTQBrwAlLlAwWiTkS4MGHQxRPhzgEOIuDQaoHnAhwh0vlhPIVlRpwIHbFx5wAYKEgW81WOIUGIDgAAIEErJEjGjBAZQIVSSoiLF8IAQOHsJMgkMFQkAAOw==); }\r\n         .privprotproperty { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeYAP///6KvxP/9+9/j6n2d36y3y//rbkFLWMjO2fb//6ykj//taE1PVMnQ3crR3rjA0uPm6r7H1rK7zsHI0nBhS3BhSqCrwtLX4sHI0YBxXPj7/uDl63WFnGR2jW1/lsLJ0+np4sSTFTMnFd3Z1OyoEZOFc9bY2JWEU+/0++3HS6u3y/TXZ66YWO3DQPj6/d7BYXqKoU9ie9y9VIBrV1FmQOjw/IXMhWVWTwoHEPLPVhsQC/nhcvrrsPnjf45iFImcaXN1fGBcXbvF1Liso//QH/bhg6TF/1OsQUtLTqq62vz+/zKMGOq7MZmPerfK8ffdasTM2r3G1vPSWPrick9jfLjB0sTM2fbbaUxQU1VogZinvG+Al11vh9jd5sjP2ZCetN+yMmd3kM3Iv39tW8iZHT+XKbnJ5Vt4WaaiX3JcQU1RVomSp1A9QZadpMS4leXk31dqgn1/goyQUEGeMqCWgGdgUotyUWN1jfz+/qOXgOLm7Pq6Ii4hAtapLk86MPL2/eXThqbBrs7KwuLNeqytsFlNV2R2jvn7//3+/py4me76/+Xr8+bu+8DH0ae+pClmHP7//7G6zYR1Xl5widDIwrvD1O3r57Wmgf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJgALAAAAAAQABAAAAj7ADEJxDTEzYhLeeg0KZFBTKJAAzFR4jHGgMUpK2TY+WEjoqUZC1gY2PEkR4o9aI4QWJlEQY8TC/xckdKCCQk5cwgYMaOgCIVBdRawAUMmhA8aZQg4UQCIwpoKLwoREYGDz40zSzAAACHpDQBBFfroCNJGoKNHWgUIAAAAD6E0ehw8iFRAYCMAagEg0vCnhoMBBSxEgYHpA4AAASAhDrDBihYTAApswTQBrwAlLlAwWiTkS4MGHQxRPhzgEOIuDQaoHnAhwh0vlhPIVlRpwIHbFx5wAYKEgW81WOIUGIDgAAIEErJEjGjBAZQIVSSoiLF8IAQOHsJMgkMFQkAAOw==); }\r\n\r\n         .pubfield { background-image: url(data:image/gif;base64,R0lGODlhEAAQANUsAAAzmVub2JnN/7LY+1qa15W+5nmw47XE4efx+6HQ/pHD8d7t+oq97oK36sXb8X2y5ShXr77L5Ut0vB5OqdPn+q/W/Hmw5NLm+dLm+I7C87rX8f///8LZ8NXo+4vA9M3j+b/Y7zVjtZ/Q/p3J8pDE9qPR/niv43yz553P/lyb2Hy06ay93v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACwALAAAAAAQABAAAAZUQJZwSCwaj0gi5oFIDj8mhmHhpFhIgozhguxoPAJBYiRBnhQogWgwASALjUFpAAG4j4WAqhKyAzZHKQEBfgARSCAEhHYHThwEjE5CDgArkpeYmURBADs=); }\r\n         .protfield { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZIAAAzmf////jYaN28WqOALlub2JnN/+7AL9O4f7LY+1qa1+fXs/Tu4MipX7XE4Y9uIvDr33mw453J8vDo1ny06fH2/I7C83iv432y5TVjtf71rOXVtB5OqYq97vXrrovA9Pby6eTw+4O04rfP5v/aZClasO7q3oxrH3mw5KPR/uDu/JDE9v/PMvXssp3G7ev0/KHQ/ujIXcuvdcLZ8J/Q/u7blubMgoW04uby/IK36uTx/MXb8ZHD8b7L5ay93ihXr3uy5Z3P/lyb2K/W/OvhzeTbxqaFONLm+f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAEgALAAAAAAQABAAAAeXgEiCg4RIAYWIgwEhGBWHiYIBKhcdES+PiAE6KCsGFhFHkDhAHwYGMBIlkC48QQY0CRwAkQG1hyI5CSkJPwCzAQwIMg0LATcFFEMZvrPBLQICRgtCBQXMAD1IGx4aJwMsBCMK1r4Oggg1AgMDBwRIMwrlgxMNJALtRII7AD6FRQMCCJiARMjGPXcEBQ2I8QBCQkEgGiYMBAA7); }\r\n         .privfield { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZRAAAzmd/j6lub2Ky3y0FLWJnN/+Pm6rLY+8jO2crR3snQ3Vqa177H1rjA0rK7zrXE4fDy9HSq3qCrwtLX4nmw473G1sTM2ZCetGd3kFdqgp3P/m1/lp3J8pDE9tLm+LfP5ny06bjB0q/W/IvA9J/Q/rvF1B5OqXyz59Lm+dXo+77L5cXb8SlasJinvKu3y83j+X2y5aPR/rG6zV5wiZHD8XqKoVyb2IKRpDVjtXiv4yhXr7vD1MTM2tPn+vv7/N7t+nWFnGR2jU9ie2p7kay93sLZ8G+Al47C86HQ/niGm2R2joK36oq97qPJ7E9jfHuy5efx+////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFEALAAAAAAQABAAAAebgFGCg4SFhoYeMFCHhS85TBQ/jII9TR0FRxQojClPIwUFSBwsjCc0GgUkByYAjBFLBzEHOgCtURAJDTIDEBECICI4tbYJAQMSFTU2AgLDACqCFi2CA0YfC821D4IGJRcKCkFKBkUL2oMKAeoBEww3USsARIQ7AQT3Ew1JjAMBCAQIEDgYwkhCAh4MQjhwIYSRDyAbMMzI4MTAoUAAOw==); }\r\n         .privprotfield { background-image: url(data:image/gif;base64,R0lGODlhEAAQAOZRAAAzmd/j6lub2Ky3y0FLWJnN/+Pm6rLY+8jO2crR3snQ3Vqa177H1rjA0rK7zrXE4fDy9HSq3qCrwtLX4nmw473G1sTM2ZCetGd3kFdqgp3P/m1/lp3J8pDE9tLm+LfP5ny06bjB0q/W/IvA9J/Q/rvF1B5OqXyz59Lm+dXo+77L5cXb8SlasJinvKu3y83j+X2y5aPR/rG6zV5wiZHD8XqKoVyb2IKRpDVjtXiv4yhXr7vD1MTM2tPn+vv7/N7t+nWFnGR2jU9ie2p7kay93sLZ8G+Al47C86HQ/niGm2R2joK36oq97qPJ7E9jfHuy5efx+////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFEALAAAAAAQABAAAAebgFGCg4SFhoYeMFCHhS85TBQ/jII9TR0FRxQojClPIwUFSBwsjCc0GgUkByYAjBFLBzEHOgCtURAJDTIDEBECICI4tbYJAQMSFTU2AgLDACqCFi2CA0YfC821D4IGJRcKCkFKBkUL2oMKAeoBEww3USsARIQ7AQT3Ew1JjAMBCAQIEDgYwkhCAh4MQjhwIYSRDyAbMMzI4MTAoUAAOw==); }\r\n\r\n         .pubdelegate { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPebAP///9tw3PqY+6M+pOfq7dJl07fB0owtjUFVb83T2qu2y6Ctw/T1+E9je7nD05k2murlq9fWrJs4nPr6/LKgy0ped6I+o8HFrJ2pwtht2a24zJqnv1hrg0hbdY2ctsfO3EBSbLjB0qOvxqqzraexx+jq8f39/mx9lNZt0vLz9uPn7cW02jxRa8nP3VRmf5mlruqL65ejreLl7N/j6ubo7+Dj68HJ2M7PrPX2+Pqt+rO6rdvf5/qm+8LI0ZeMs+js8bS90MDI15ekvbG7zktfecmm1uTn7vn6+5ShuurmrF9xiK23zGByipilvp2pu73G1sDI2JOguTtPaThOaNne55OhurO90JWjtdne5jhNZ0RYcpyowK+5zZaStpumtK21rfqx+vHy9tNn1PDy9aayx7yq0ZKfudLY4rvE1f7+/qezyPb3+Zqmru3u8/f4+ubiq/v7/JCesJajvHiJn87U4dG84uuQ7Npu28HJ16GtxMjP3FpthbC7zbG8z+vu877H1tHW4nqKoOXX7mZ3kFVngLbA0urs8aA8oaq1xN3D6Y6dtqlFqrjC09jXrKm0yevt8qWwx5Shs8PGrHKDmtbc5rzF1ejZ8HCAl+Tn69vg6EVZc////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJsALAAAAAAQABAAAAjuADcJHEjAyhISBAYqJIjIyZVAl3osVPgkzg4ARpoomTjQQCQcAABU4bAQExQ0hfpocARpAYYNcsx4SLDJRkgAaY6kMCQoQCI9QUK42FTp5gQGfiwFyBGgjoMhDTYZAPDmhg42NAKA4SEgwAoFRDYBAWDCzZgSM1DYEcB2EZkOm7gkaSTpywssBQLAEDBgQB4tmxTAYdBGRaYzYu4E6HtoC4JNatZAiHBhRIwiBTIMkHBACIhNIsL8qEGJzoc/ZQpYONAlipRNCx7JoAKoBR5GfCg88IFEUZZNCeZMOjGIyR5CDSpoQsBiiheO0DcFBAA7); }\r\n         .protdelegate { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeQAP///9tw3N28WvjYaKM+pKOALvqY+9O4f+fq7dJl0+7AL6Ctw4wtjc3T2v/PMk9je8ipX49uIkFVb5s4nJ2pwtpu2+3kqZqnv5Shs7Kgy2ByirjB0qWwx5qmrqayx6u2y6q1xMHJ2L7H1oxrH/Xsslhrg+3iyuXX7uTn6/7+/ubo75yowEBSbFVngPqt+sLI0ZeMs253gPT1+KGtxJShusHJ13CAl5ajvJ2pu3qKoFpthd3D6aaFOJk2msmm1paStpKfuaGhnUped7vE1Y6dtrG8z0VZc8++k19xiOjZ8PLz9o2ctrbA0sDI18DI2Pr6/KA8oeqL68vMyeTn7khbddne5tvf55ejrTtPabO90Ovu85Ohuvn6+9G84ktfed/PrqlFqpekvcW02vDr3/X2+MnP3bC7zd/j6qm0ybGulb3G1sfO3NZt0pCesKI+o/qx+v71rLjC0zhNZ1Rmf9ht2ers8bG7zsS/sK23zKexx7yq0ebVkc7U4TxRa9LY4ujIXThOaMuvdZWjtZilvsjP3LzF1euQ7ERYcvqm+7nD0/Do1tNn1K24zJOguZumtLfB0v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjuACEJHIggC548CAYqJAgCh6AcNl4sVKimjRVIUwYhmTjwEQYykABsKbEQhZMhTIowQsNhAYULN4AsaQApBICbKbgoqXMiwA5CTTbMgVToJoAnMrQkCeAiQJdEdh5AunMgEIQjHVQEeIPIQAAxH7yYOEBiwAAeX86wMWSgLRgPVA5YgDNCgIMCVRIEiGKAAIEZhw7sGSBAgIICfhZVCOAXygoJiiA4GHA4zRUfCegQmMAgDAtIQQQMKCCFzxoRehK4YfCjERZIC0QfLlMjjpkMPWDQICIHUgMBfyLE0KCjxQMhRiT0AeRoYIQxHBUGBAA7); }\r\n         .privdelegate { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeWAP///9tw3PqY+6M+pEFLWOHl7OPm6qy3y77H1sjO2efq7dJl09/j6srR3rjA0tLX4owtjbG6zU9je73G1rK7zqCrwkFVb7jB0jhNZ6A8odpu20hbdbfB0qayx6exx9ht2cnQ3dvf56lFquvu8+rs8ZCesEped/Lz9pinvLvD1PT1+KWwx09jfKGtxKq1xLvE1Y6dtnqKoebo76Ctw8TM2am0yVRmf7Kgy8TM2ps4nLnD0/7+/md3kPqm+2+Al9Zt0kRYcr7H05eMs/Dy9EBSbJShupk2mpaStsHJ2Pqx+ktfecDI2E9ie2R2jvr6/Ovr1a24zEVZc6u3y7bA0ldqgrvF1GN1jWR2jTtPad7i6ZShs7C7zZOgudNn1JWjtZCetMjP3NG84uXX7sLI0byq0euQ7HqKoLzF1fqt+s7U3vn6+8DI17O90N3D6eTn61VngF9xiJumtLG8z+Di1cmm1lVogeTn7pOhurjC05yowDxRa9PZ3PX2+K23zFhrg42ctpekvau2y6I+o3WFnJKfuV5wiThOaM3T2rG7zl1vh5ilvujZ8LS9zG1/lsW02uqL65qnv+Pn7ZajvJ2pwnCAl52pu////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJYALAAAAAAQABAAAAjyAC0JHKiATR8PCgYqJOiikhczlMYsVDihRAgAdhTBmTiQgxY+AADc8bPQzZIXU+RAqbFixiRIkgj9OWQJSUgAO9ScICEmQBsway7YsHTmphMVIxYFQBMgjA5EEixlaeAgwoE9MgIk6SEggKNASiw1YHCgAqMYDH6UEcBWRIcNQ2igeDJngo80CwI8EjBgQAsgBqp8qXqlSZAuGgL0zZDHAohIBSI/QGCFzoIPA3JAAEQkRQECoB84SISAzAJBEI5wwXKAQQICCRJQqINnyw0jQorAwFChAQ4EFyhIYfJGgokoFvQYimNgUCMehaiwMMDRUkAAOw==); }\r\n         .privprotdelegate { background-image: url(data:image/gif;base64,R0lGODlhEAAQAPeWAP///9tw3PqY+6M+pEFLWOHl7OPm6qy3y77H1sjO2efq7dJl09/j6srR3rjA0tLX4owtjbG6zU9je73G1rK7zqCrwkFVb7jB0jhNZ6A8odpu20hbdbfB0qayx6exx9ht2cnQ3dvf56lFquvu8+rs8ZCesEped/Lz9pinvLvD1PT1+KWwx09jfKGtxKq1xLvE1Y6dtnqKoebo76Ctw8TM2am0yVRmf7Kgy8TM2ps4nLnD0/7+/md3kPqm+2+Al9Zt0kRYcr7H05eMs/Dy9EBSbJShupk2mpaStsHJ2Pqx+ktfecDI2E9ie2R2jvr6/Ovr1a24zEVZc6u3y7bA0ldqgrvF1GN1jWR2jTtPad7i6ZShs7C7zZOgudNn1JWjtZCetMjP3NG84uXX7sLI0byq0euQ7HqKoLzF1fqt+s7U3vn6+8DI17O90N3D6eTn61VngF9xiJumtLG8z+Di1cmm1lVogeTn7pOhurjC05yowDxRa9PZ3PX2+K23zFhrg42ctpekvau2y6I+o3WFnJKfuV5wiThOaM3T2rG7zl1vh5ilvujZ8LS9zG1/lsW02uqL65qnv+Pn7ZajvJ2pwnCAl52pu////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJYALAAAAAAQABAAAAjyAC0JHKiATR8PCgYqJOiikhczlMYsVDihRAgAdhTBmTiQgxY+AADc8bPQzZIXU+RAqbFixiRIkgj9OWQJSUgAO9ScICEmQBsway7YsHTmphMVIxYFQBMgjA5EEixlaeAgwoE9MgIk6SEggKNASiw1YHCgAqMYDH6UEcBWRIcNQ2igeDJngo80CwI8EjBgQAsgBqp8qXqlSZAuGgL0zZDHAohIBSI/QGCFzoIPA3JAAEQkRQECoB84SISAzAJBEI5wwXKAQQICCRJQqINnyw0jQorAwFChAQ4EFyhIYfJGgokoFvQYimNgUCMehaiwMMDRUkAAOw==); }\r\n\r\n          .expander {font-size: 18px; background-color: black; color:white; clear:both; cursor: pointer;padding: 10px;border: none;text-align: left;outline: none;margin:0 0 2px 0;transition: 0.4s;}\r\n          .expander:hover {background-color: #555;}\r\n          .expander:after {content: '\\002B';color: #FFF;font-weight: bold;float: right;margin-left: 5px;}\r\n          .active:after {content: \"\\2212\";}\r\n          .collapse {display: none;}\r\n      </style>\r\n    </head>\r\n<body>\r\n\r\nGenerated with <a href=\"https://github.com/dotMorten/DotNetOMDGenerator\">.NET Object Model Diagram Generator</a><br /><br />\r\n\r\n\r\n"
  },
  {
    "path": "src/Generator/Generators/MarkdownGenerator.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Microsoft.CodeAnalysis;\n\nnamespace Generator.Generators\n{\n    internal class MarkdownGenerator : ICodeGenerator, ICodeDiffGenerator\n    {\n        private System.IO.StreamWriter sw;\n        private List<INamedTypeSymbol> allSymbols;\n        private List<INamedTypeSymbol> oldSymbols;\n        private string currentNamespace;\n\n        public void Initialize(List<INamedTypeSymbol> allSymbols) => Initialize(allSymbols, null);\n        public void Initialize(List<INamedTypeSymbol> allSymbols, List<INamedTypeSymbol> oldSymbols)\n        {\n            this.allSymbols = allSymbols;\n            this.oldSymbols = oldSymbols;\n            var outLocation = GeneratorSettings.OutputLocation;\n            if (string.IsNullOrEmpty(new System.IO.FileInfo(outLocation).Extension))\n                outLocation += \".md\";\n            sw = new System.IO.StreamWriter(outLocation);\n            WriteLine(\"<pre>\", 0);\n        }\n\n        public void Complete()\n        {\n            if (currentNamespace != null)\n            {\n                //close the last namespace section\n                WriteLine(\"}\", 0);\n                WriteLine(\"</pre>\", 0);\n                WriteLine(\"Generated with (.NET Object Model Diagram Generator)[https://github.com/dotMorten/DotNetOMDGenerator]\", 0);\n                sw.Flush();\n            }\n            sw.Flush();\n            sw.Close();\n            sw.Dispose();\n        }\n\n\n        public void WriteClass(INamedTypeSymbol type) => WriteType(type, null, false);\n\n        public void WriteClass(INamedTypeSymbol type, INamedTypeSymbol oldType = null)\n        {\n            WriteType(type, oldType, true);\n        }\n\n        private void WriteLine(string line, int indent)\n        {\n            if (!string.IsNullOrEmpty(line))\n            {\n                for (int i = 0; i < indent; i++)\n                {\n                    line = \"\\t\" + line.Replace(\"\\n\", \"\\n\\t\");\n                }\n                line = line.Replace(\"\\n\", \"\\n\");\n                line = line.Replace(\"\\t\", \"    \");\n                sw.Write(line);\n            }\n            sw.WriteLine();\n        }\n        private const string RemoveStart = \"<strike>\";\n        private const string RemoveEnd = \"</strike>\";\n        private const string AddedStart = \"<b>\";\n        private const string AddedEnd = \"</b>\";\n        public void WriteType(INamedTypeSymbol type, INamedTypeSymbol oldType, bool isComparison, int indent = 0)\n        {\n            bool isTypeRemoved = type == null && oldType != null;\n            bool isTypeNew = type != null && oldType == null && isComparison;\n            if (isTypeRemoved)\n                type = oldType;\n\n            string kind = \"\";\n            switch (type.TypeKind)\n            {\n                case TypeKind.Struct:\n                case TypeKind.Class:\n                    if (type.BaseType.GetFullTypeName() == \"System.Enum\")\n                        kind = \"enum\"; //When loading assemblies the enum kind isn't recognized\n                    else\n                    {\n                        kind = \"class\";\n                        if (type.IsSealed && (oldType == null || oldType.IsSealed)) kind = \"sealed \" + kind;\n                        else if (type.IsSealed && !oldType.IsSealed) kind = $\"{AddedStart}sealed{AddedEnd} {kind}\";\n                        else if (!type.IsSealed && oldType != null && oldType.IsSealed) kind = $\"{RemoveStart}sealed{RemoveEnd} {kind}\";\n\n                        if (type.IsStatic && (oldType == null || oldType.IsStatic)) kind = \"static \" + kind;\n                        else if (type.IsStatic && !oldType.IsStatic) kind = $\"{AddedStart}static{AddedEnd} {kind}\";\n                        else if (!type.IsStatic && oldType != null && oldType.IsStatic) kind = $\"{RemoveStart}static{RemoveEnd} {kind}\";\n                    }\n                    break;\n                case TypeKind.Delegate: kind = \"delegate\"; break;\n                case TypeKind.Enum: kind = \"enum\"; break;\n                case TypeKind.Interface: kind = \"interface\"; break;\n                default:\n                    return; //Not supported\n            }\n\n            var nsname = type.GetFullNamespace();\n            if (nsname != currentNamespace)\n            {\n                if (currentNamespace != null)\n                {\n                    //close the current namespace section\n                    WriteLine(\"}\", indent);\n                }\n                WriteLine($\"namespace {nsname}\\n{{\", indent);\n                currentNamespace = nsname;\n            }\n            \n            string className = AccessorToString(type.DeclaredAccessibility) + \" \" + kind + \" \" + type.Name;\n\n            var symbols = Generator.GetChangedSymbols(\n                type == oldType ? Enumerable.Empty<INamedTypeSymbol>() : type.GetAllNestedTypes(),\n                oldType == null ? Enumerable.Empty<INamedTypeSymbol>() : oldType.GetAllNestedTypes());\n            if (type.BaseType != null && (type.BaseType.Name != \"Object\" || type.BaseType.ToDisplayString() != oldType?.BaseType.ToDisplayString()) && kind != \"enum\")\n            {\n                if (oldType == null || type.BaseType.ToDisplayString() != oldType.BaseType.ToDisplayString())\n                {\n                    if (oldType != null && oldType.BaseType.Name != \"Object\" && !isTypeRemoved)\n                    {\n                        className += $\" : {RemoveStart}{FormatType(oldType.BaseType)}{RemoveEnd}\"; //removed baseclass\n                        if (type.BaseType.Name != \"Object\") className += $\"{FormatType(type.BaseType)}\";\n                    }\n                    if (type.BaseType.Name != \"Object\")\n                    {\n                        if (isComparison && !isTypeNew)\n                            className += $\" : {AddedStart}{FormatType(type.BaseType)}{AddedEnd}\"; //new baseclass\n                        else\n                            className += $\" : {FormatType(type.BaseType)}\";\n                    }\n                }\n            }\n            else if (kind == \"enum\")\n            {\n                if (type.TypeKind == TypeKind.Enum)\n                {\n                    INamedTypeSymbol enumType = type.EnumUnderlyingType;\n                    INamedTypeSymbol oldEnumType = oldType?.EnumUnderlyingType;\n                    if (oldEnumType == null || enumType.ToDisplayString() != oldEnumType.ToDisplayString())\n                    {\n                        className += \" : \";\n                        if (oldEnumType != null && !isTypeRemoved)\n                        {\n                            className += $\"{RemoveStart}{FormatType(oldEnumType)}{RemoveEnd}{AddedStart}{FormatType(enumType)}{AddedEnd}\"; //removed baseclass\n                        }\n                        else if (oldEnumType == null && isComparison && !isTypeNew)\n                            className += $\"{AddedStart}{FormatType(enumType)}{AddedEnd}\"; //new baseclass\n                        else\n                            className += FormatType(enumType);\n                    }\n                }\n                else if (type.TypeKind == TypeKind.Class) //Happens when analyzing assemblies\n                {\n                    var fields = type.GetFields();\n                    var enumType = fields.FirstOrDefault()?.ConstantValue?.GetType().FullName;\n                    var oldEnumType = oldType?.GetFields().FirstOrDefault()?.ConstantValue?.GetType().FullName;\n                    if (oldEnumType == null || enumType != oldEnumType)\n                    {\n                        className += \" : \";\n                        if (oldEnumType != null && !isTypeRemoved)\n                        {\n                            className += $\"{RemoveStart}{oldEnumType}{RemoveEnd}\"; //removed baseclass\n                        }\n                        else if (oldEnumType == null && isComparison && !isTypeNew)\n                            className += $\"{AddedStart}{enumType}{AddedEnd}\"; //new baseclass\n                        else\n                            className += enumType;\n                    }\n                }\n            }\n\n            //Document interfaces\n            if (type.GetInterfaces(oldType).Any())\n            {\n                foreach (var iface in type.GetInterfaces(oldType))\n                {\n                    if (className.Contains(\" : \"))\n                        className += \", \";\n                    else\n                        className += \" : \";\n                    var typeName = FormatType(iface.symbol);\n                    if (iface.wasRemoved && !isTypeRemoved)\n                        typeName = $\"{RemoveStart}{typeName}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        className += $\"{AddedStart}{typeName}{AddedEnd}\";\n                    else\n                        className += typeName;\n                }\n            }\n\n            if (isTypeRemoved)\n            {\n                WriteLine($\"{RemoveStart}{className} {{ ... }}{RemoveEnd}\", indent + 1);\n                return;\n            }\n\n\n            WriteLine($\"{(isTypeNew && isComparison ? AddedStart : \"\")}{className}\", indent + 1);\n            WriteLine(\"{\", indent + 1); //Begin class\n            //List out members\n            if (type.GetConstructors(oldType).Any())\n            {\n                foreach (var method in type.GetConstructors(oldType))\n                {\n                    var str = FormatMember(method.symbol);\n                    if (method.wasRemoved)\n                        str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        str = $\"{AddedStart}{str}{AddedEnd}\";\n                    WriteLine(str, indent + 2);\n                }\n            }\n            if (type.GetProperties(oldType).Any())\n            {\n                foreach (var method in type.GetProperties(oldType))\n                {\n                    var str = FormatMember(method.symbol);\n                    if (method.wasRemoved)\n                        str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        str = $\"{AddedStart}{str}{AddedEnd}\";\n                    WriteLine(str, indent + 2);\n                }\n            }\n            if (type.GetMethods(oldType).Any())\n            {\n                foreach (var method in type.GetMethods(oldType))\n                {\n                    var str = FormatMember(method.symbol);\n                    if (method.wasRemoved)\n                        str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        str = $\"{AddedStart}{str}{AddedEnd}\";\n                    WriteLine(str, indent + 2);\n                }\n            }\n            if (type.GetEvents(oldType).Any())\n            {\n                foreach (var method in type.GetEvents(oldType))\n                {\n                    var str = FormatMember(method.symbol) + \";\";\n                    if (method.wasRemoved)\n                        str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        str = $\"{AddedStart}{str}{AddedEnd}\";\n                    WriteLine(str, indent + 2);\n                }\n            }\n            if (kind != \"enum\" && type.GetFields(oldType).Any())\n            {\n                foreach (var method in type.GetFields(oldType))\n                {\n                    var str = FormatMember(method.symbol);\n                    if (method.wasRemoved)\n                        str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                    else if (isComparison && !isTypeNew)\n                        str = $\"{AddedStart}{str}{AddedEnd}\";\n                    WriteLine(str, indent + 2);\n                }\n            }\n\n            if (kind == \"enum\")\n            {\n                if (type.TypeKind == TypeKind.Enum)\n                {\n                    foreach (var e in type.GetEnums(oldType).OrderBy(f => f.symbol.ConstantValue))\n                    {\n                        string str = Briefify(e.symbol);\n                        if (e.symbol.HasConstantValue)\n                            str += \" = \" + e.symbol.ConstantValue?.ToString();\n                        if (e.wasRemoved)\n                            str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                        else if (isComparison && !isTypeNew)\n                            str = $\"{AddedStart}{str}{AddedEnd}\";\n                        WriteLine(str + \",\", indent + 2);\n                    }\n                }\n                else if (type.TypeKind == TypeKind.Class)\n                {\n                    foreach (var e in type.GetFields(oldType).Where(f => f.symbol.HasConstantValue).OrderBy(f => f.symbol.ConstantValue))\n                    {\n                        if (!e.symbol.HasConstantValue)\n                            continue;\n                        string str = Briefify(e.symbol) + \" = \" + e.symbol.ConstantValue?.ToString();\n                        if (e.wasRemoved)\n                            str = $\"{RemoveStart}{str}{RemoveEnd}\";\n                        else if (isComparison && !isTypeNew)\n                            str = $\"{AddedStart}{str}{AddedEnd}\";\n                        WriteLine(str + \",\", indent + 2);\n                    }\n                }\n\n            }\n\n            if (symbols.Any())\n            {\n                WriteLine(null, 0);\n                foreach (var t in symbols)\n                {\n                    WriteType(t.newSymbol, t.oldSymbol, isComparison && !isTypeNew, indent + 1);\n                }\n            }\n\n            WriteLine(\"}\" + (isTypeNew && isComparison ? AddedEnd:\"\"), indent + 1); //EndClass\n            sw.Flush();\n        }\n\n        public void WriteEnum(INamedTypeSymbol enm) => WriteType(enm, null, false);\n        public void WriteEnum(INamedTypeSymbol enm, INamedTypeSymbol oldType = null)\n        {\n            WriteType(enm, oldType, true);\n        }\n\n        public void WriteInterface(INamedTypeSymbol iface) => WriteType(iface, null, false);\n        public void WriteInterface(INamedTypeSymbol iface, INamedTypeSymbol oldType = null)\n        {\n            WriteType(iface, oldType, true);\n        }\n        public void WriteDelegate(INamedTypeSymbol del) => WriteType(del, null, false);\n\n        public void WriteDelegate(INamedTypeSymbol del, INamedTypeSymbol oldDel = null)\n        {\n            WriteType(del, oldDel, true);\n        }\n\n        private string FormatType(ITypeSymbol type)\n        {\n            var f = SymbolDisplayFormat.MinimallyQualifiedFormat;\n            f.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters);\n            var parts = type.ToDisplayParts(f);\n            if (parts.Length > 1)\n            {\n                string t = \"\";\n                foreach (var p in parts)\n                {\n                    if (p.Kind == SymbolDisplayPartKind.Punctuation || p.Kind == SymbolDisplayPartKind.Space)\n                        t += p; // System.Web.HttpUtility.HtmlEncode(p.ToString());\n                    else if (p.Symbol is ITypeSymbol its)\n                        t += LinkifyType(its, false);\n                    else\n                    {\n\n                    }\n                }\n                return t;\n            }\n            else\n            {\n                return LinkifyType(type);\n            }\n        }\n\n        private string LinkifyType(ITypeSymbol type, bool includeGeneric = true)\n        {\n            if (type is INamedTypeSymbol nts && nts.IsGenericType && !includeGeneric)\n            {\n                type = nts.OriginalDefinition;\n            }\n            var name = includeGeneric ? type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) : type.Name;\n            //if (allSymbols.Contains(type))\n            //    return $\"<a href='#{type.GetFullTypeName()}'>{System.Web.HttpUtility.HtmlEncode(name)}</a>\";\n            //else\n                return Briefify(type, name);\n        }\n\n        private static string AccessorToString(Accessibility a)\n        {\n            switch (a)\n            {\n                case Accessibility.Public:\n                    return \"public\";\n                case Accessibility.Private:\n                    return \"private\";\n                case Accessibility.Internal:\n                    return \"internal\";\n                case Accessibility.Protected:\n                    return \"protected\";\n                case Accessibility.ProtectedOrInternal:\n                    return GeneratorSettings.ShowInternalMembers ? \"protected internal\" : \"protected\";\n                case Accessibility.ProtectedAndInternal:\n                    return \"private protected\";\n                default:\n                    return string.Empty;\n            }\n        }\n\n        private string FormatMember(ISymbol member)\n        {\n            var brief = member.GetDescription();\n            var name = member.Name;\n            if (name == \".ctor\")\n            {\n                name = member.ContainingType.Name;\n            }\n            name = Briefify(member, name);\n            string accessor = AccessorToString(member.DeclaredAccessibility);\n            if (member is IPropertySymbol p)\n            {\n                name += \" { \";\n                if (p.GetMethod != null && ((p.GetMethod.DeclaredAccessibility == Accessibility.Public || p.GetMethod.DeclaredAccessibility == Accessibility.Protected || p.GetMethod.DeclaredAccessibility == Accessibility.ProtectedOrInternal) ||\n                    (GeneratorSettings.ShowInternalMembers && p.GetMethod.DeclaredAccessibility == Accessibility.Internal || p.GetMethod.DeclaredAccessibility == Accessibility.ProtectedAndInternal) ||\n                    (GeneratorSettings.ShowPrivateMembers && p.GetMethod.DeclaredAccessibility == Accessibility.Private)))\n                {\n                    if (p.DeclaredAccessibility != p.GetMethod.DeclaredAccessibility)\n                    {\n                        name += AccessorToString(p.GetMethod.DeclaredAccessibility) + \" \";\n                    }\n                    name += \"get; \";\n                }\n                if (p.SetMethod != null && ((p.SetMethod.DeclaredAccessibility == Accessibility.Public || p.SetMethod.DeclaredAccessibility == Accessibility.Protected || p.SetMethod.DeclaredAccessibility == Accessibility.ProtectedOrInternal) ||\n                   (GeneratorSettings.ShowInternalMembers && p.SetMethod.DeclaredAccessibility == Accessibility.Internal || p.SetMethod.DeclaredAccessibility == Accessibility.ProtectedAndInternal) ||\n                   (GeneratorSettings.ShowPrivateMembers && p.SetMethod.DeclaredAccessibility == Accessibility.Private)))\n                {\n                    if (p.DeclaredAccessibility != p.SetMethod.DeclaredAccessibility)\n                    {\n                        name += AccessorToString(p.SetMethod.DeclaredAccessibility) + \" \";\n                    }\n                    name += \"set; \";\n                }\n\n                name = FormatType(p.Type) + \" \" + name + \"}\";\n            }\n            else if (member is IMethodSymbol m)\n            {\n                if (m.TypeArguments.Any())\n                {\n                    name += \"&lt;\" + string.Join(\", \", m.TypeArguments.Select(t => t.ToDisplayString())) + \"&gt;\";\n                }\n\n                name += \"(\";\n                name += string.Join(\", \", m.Parameters.Select(pr => FormatType(pr.Type) + \" \" + Briefify(pr) + (pr.HasExplicitDefaultValue ? (\" = \" + (pr.ExplicitDefaultValue?.ToString() ?? \"null\")) : \"\")));\n                name += \");\";\n                if (!m.ReturnsVoid)\n                {\n                    name = FormatType(m.ReturnType) + \" \" + name;\n                }\n                \n            }\n            else if (member is IEventSymbol e)\n            {\n                name = FormatType(e.Type) + \" \" + name;\n            }\n            else if (member is IFieldSymbol f)\n            {\n                name = FormatType(f.Type) + \" \" + name;\n            }\n            if (member.ContainingType.TypeKind == TypeKind.Interface)\n                return name; //Don't add accessor to interface members\n            return accessor + \" \" + name;\n        }\n\n        private static string Briefify(ISymbol symbol, string content = null)\n        {\n            if (content == null)\n                content = symbol.Name;\n            return content;\n            //var brief = symbol.GetDescription();\n            //if (!string.IsNullOrEmpty(brief))\n            //    return $\"<span title=\\\"{System.Web.HttpUtility.HtmlEncode(brief)}\\\">{System.Web.HttpUtility.HtmlEncode(content)}</span>\";\n            //return System.Web.HttpUtility.HtmlEncode(content);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Generator/Generators/OMDGenerator.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Drawing;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing Microsoft.CodeAnalysis;\r\n\r\nnamespace Generator.Generators\r\n{\r\n    internal class OMDGenerator : ICodeGenerator\r\n    {\r\n        private static SolidBrush BackgroundClassBrush = new SolidBrush(Color.FromArgb(255, 211, 220, 239));\r\n        private static SolidBrush BackgroundInterfaceBrush = new SolidBrush(Color.FromArgb(255, 231, 240, 220));\r\n        private static SolidBrush BackgroundEnumBrush = new SolidBrush(Color.FromArgb(255, 221, 214, 239));\r\n        private static SolidBrush BackgroundGroupBrush = new SolidBrush(Color.FromArgb(255, 240, 242, 239));\r\n        private static Font MemberFont = new System.Drawing.Font(\"Arial\", 16);\r\n        private static Font HeaderFont = new System.Drawing.Font(\"Arial\", 20, FontStyle.Bold);\r\n        private static Pen BlackPen = new Pen(Color.Black, 1);\r\n        private const int groupHeight = 47;\r\n        private const int headerHeight = 100;\r\n        private const int lineSpacing = 12;\r\n        private const int MemberIndent = 75;\r\n\r\n        public void WriteClass(INamedTypeSymbol type) =>RenderOMD(type);\r\n\r\n        public void WriteDelegate(INamedTypeSymbol type) => RenderOMD(type);\r\n        public void WriteEnum(INamedTypeSymbol enm) => RenderOMD(enm);\r\n\r\n        public void WriteInterface(INamedTypeSymbol iface) => RenderOMD(iface);\r\n\r\n        private void RenderOMD(INamedTypeSymbol type)\r\n        { \r\n            using (Bitmap bitmap = new System.Drawing.Bitmap(2000, 2000))\r\n            {\r\n                int y = 0;\r\n                int startHeight = 0;\r\n                double width = 200; //MinWidth\r\n                using (var bmp = System.Drawing.Graphics.FromImage(bitmap))\r\n                {\r\n                    bmp.Clear(Color.Transparent);\r\n                    if (type.Interfaces.Any())\r\n                    {\r\n                        bmp.DrawEllipse(BlackPen, 40, 0, 24, 24);\r\n                        y += 5;\r\n                        foreach (var iface in type.Interfaces)\r\n                        {\r\n                            width = Math.Max(width, bmp.MeasureString(iface.Name, HeaderFont).Width + 75);\r\n                            bmp.DrawString(iface.Name, MemberFont, Brushes.Black, 75, y);\r\n                            y += (int)(MemberFont.Size + lineSpacing);\r\n                        }\r\n                        y += lineSpacing;\r\n                        bmp.DrawLine(BlackPen, 52, 24, 52, y);\r\n                    }\r\n                    startHeight = y;\r\n                    var bbrush = BackgroundClassBrush;\r\n                    if (type.TypeKind == TypeKind.Enum)\r\n                        bbrush = BackgroundEnumBrush;\r\n                    else if (type.TypeKind == TypeKind.Interface)\r\n                        bbrush = BackgroundInterfaceBrush;\r\n                    bmp.FillRectangle(bbrush, 0, y, bitmap.Width, headerHeight);\r\n                    width = Math.Max(width, bmp.MeasureString(type.Name, HeaderFont).Width + 10);\r\n                    bmp.DrawString(type.Name, HeaderFont, Brushes.Black, 10, 18 + y);\r\n                    string typeDesc = \"\";\r\n                    if (type.TypeKind == TypeKind.Class)\r\n                        typeDesc = type.IsAbstract ? \"Abstract \" : \"\" + \"Class\";\r\n                    else if (type.TypeKind == TypeKind.Interface)\r\n                        typeDesc = \"Interface\";\r\n                    else if (type.TypeKind == TypeKind.Enum)\r\n                        typeDesc = \"Enum\";\r\n                    bmp.DrawString(typeDesc, MemberFont, Brushes.Black, 10, 18 + y + HeaderFont.Size + lineSpacing);\r\n                    if (type.BaseType != null && type.BaseType.Name != \"Object\" && type.TypeKind != TypeKind.Enum)\r\n                        bmp.DrawString(\"→ \" + type.BaseType.Name, MemberFont, Brushes.Black, 10, 18 + y + HeaderFont.Size + lineSpacing * 2 + MemberFont.Size);\r\n                    y += headerHeight;\r\n                    bmp.DrawLine(BlackPen, 0, y, bitmap.Width, y);\r\n                    Action<string, IEnumerable<ISymbol>> RenderMembers = (n, m) =>\r\n                       {\r\n                           if (m.Any())\r\n                           {\r\n                               bmp.FillRectangle(BackgroundGroupBrush, 0, y, bitmap.Width, groupHeight);\r\n                               var size = bmp.MeasureString(n, new Font(\"Arial\", 18));\r\n                               width = Math.Max(width, size.Width + 25);\r\n                               bmp.DrawString(n, new Font(\"Arial\", 18), Brushes.Black, 25, y + (groupHeight - size.Height)/2);\r\n                               y += groupHeight + lineSpacing;\r\n\r\n                               foreach (var method in m)\r\n                               {\r\n                                   var str = FormatMember(method);\r\n                                   width = Math.Max(width, bmp.MeasureString(str, MemberFont).Width + MemberIndent);\r\n                                   bmp.DrawString(str, MemberFont, Brushes.Black, MemberIndent, y);\r\n                                   y += (int)(MemberFont.Size + lineSpacing);\r\n                               }\r\n                               y += lineSpacing;\r\n                           }\r\n                       };\r\n                    RenderMembers(\"Constructors\", type.GetConstructors().OfType<ISymbol>());\r\n                    RenderMembers(\"Properties\", type.GetProperties().OfType<ISymbol>());\r\n                    RenderMembers(\"Methods\", type.GetMethods().OfType<ISymbol>());\r\n                    RenderMembers(\"Events\", type.GetEvents().OfType<ISymbol>());\r\n                    if(type.TypeKind == TypeKind.Enum)\r\n                    {\r\n                        y += lineSpacing;\r\n                        foreach(var e in type.GetEnums())\r\n                        {\r\n                            string str = e.Name;\r\n                            width = Math.Max(width, bmp.MeasureString(str, MemberFont).Width + 25);\r\n                            bmp.DrawString(str, MemberFont, Brushes.Black, 25, y);\r\n                            y += (int)(MemberFont.Size + lineSpacing);\r\n                        }\r\n                    }\r\n                    bmp.Flush();\r\n                }\r\n                int padding = 10;\r\n                using (Bitmap bitmap2 = new System.Drawing.Bitmap((int)width + 10 + 2* padding, (int)y + 10 + 2* padding))\r\n                {\r\n                    using (var bmp2 = System.Drawing.Graphics.FromImage(bitmap2))\r\n                    {\r\n                        bmp2.Clear(Color.White);\r\n                        bmp2.DrawImageUnscaledAndClipped(bitmap, new Rectangle(padding, padding, bitmap2.Width - 2 * padding, bitmap2.Height - 2 * padding));\r\n                        bmp2.DrawRectangle(BlackPen, padding, startHeight+padding, (float)bitmap2.Width - 21, bitmap2.Height - startHeight - 21);\r\n                    }\r\n                    bitmap2.Save($\"{type.ContainingNamespace.GetFullNamespace()}.{type.Name}.png\");\r\n                }\r\n            }\r\n        }\r\n\r\n        private string FormatMember(ISymbol member)\r\n        {\r\n            string name = member.Name;\r\n            if (member.DeclaredAccessibility != Accessibility.Public)\r\n            {\r\n                name = member.DeclaredAccessibility.ToString().ToLower() + \" \" + name;\r\n            }\r\n            if (member is IPropertySymbol)\r\n            {\r\n                var p = (IPropertySymbol)member;\r\n                name += \" { \";\r\n                if(p.IsReadable())\r\n                {\r\n                    if (p.GetMethod.DeclaredAccessibility < member.DeclaredAccessibility)\r\n                    {\r\n                        name += p.SetMethod.DeclaredAccessibility.ToString() + \" \";\r\n                    }\r\n                    name += \"get; \";\r\n                }\r\n                if (p.IsSettable())\r\n                {\r\n                    if (p.SetMethod.DeclaredAccessibility < member.DeclaredAccessibility)\r\n                    {\r\n                        name += p.SetMethod.DeclaredAccessibility.ToString() + \" \";\r\n                    }\r\n                    name += \"set; \";\r\n                }\r\n                name += \"} : \" + p.Type.Name;\r\n            }\r\n            else if(member is IMethodSymbol)\r\n            {\r\n                var m = (member as IMethodSymbol);\r\n                name += \"(\";\r\n                name += string.Join(\", \", m.Parameters.Select(p => p.Type.Name + \" \" + p.Name));\r\n                name += \")\";\r\n                if (!m.ReturnsVoid) {\r\n                    name += \" : \" + m.ReturnType.Name;\r\n                }\r\n            }\r\n            else if (member is IEventSymbol)\r\n            {\r\n                var m = (member as IEventSymbol);\r\n                name += \" : \" + m.Type.Name;\r\n            }\r\n            return name;\r\n        }\r\n\r\n        public void Initialize(List<INamedTypeSymbol> allSymbols)\r\n        {\r\n        }\r\n\r\n        public void Complete()\r\n        {\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/ICodeGenerator.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing Microsoft.CodeAnalysis;\r\n\r\nnamespace Generator\r\n{\r\n    interface ICodeGenerator\r\n    {\r\n        void Initialize(List<INamedTypeSymbol> allSymbols);\r\n\r\n        void WriteClass(INamedTypeSymbol type);\r\n\r\n        void WriteInterface(INamedTypeSymbol iface);\r\n\r\n        void WriteEnum(INamedTypeSymbol enm);\r\n        void WriteDelegate(INamedTypeSymbol type);\r\n        void Complete();\r\n    }\r\n    interface ICodeDiffGenerator\r\n    {\r\n        void Initialize(List<INamedTypeSymbol> allSymbols, List<INamedTypeSymbol> oldSymbols);\r\n\r\n        void WriteClass(INamedTypeSymbol type, INamedTypeSymbol oldType);\r\n\r\n        void WriteInterface(INamedTypeSymbol iface, INamedTypeSymbol oldIface);\r\n\r\n        void WriteEnum(INamedTypeSymbol enm, INamedTypeSymbol oldEnm);\r\n\r\n        void WriteDelegate(INamedTypeSymbol del, INamedTypeSymbol oldDel);\r\n\r\n        void Complete();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/Program.cs",
    "content": "﻿using Microsoft.CodeAnalysis;\r\nusing Microsoft.CodeAnalysis.Text;\r\nusing NuGet.Protocol.Core.Types;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing System.Net.Http;\r\nusing System.Text;\r\nusing System.Text.RegularExpressions;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Generator\r\n{\r\n    internal static class GeneratorSettings\r\n    {\r\n        public static bool ShowPrivateMembers { get; set; } = false;\r\n        public static bool ShowInternalMembers { get; set; } = false;\r\n        public static string OutputLocation { get; set; } = \"./\";\r\n    }\r\n\r\n    class Program\r\n    {\r\n\r\n        static async Task Main(string[] args)\r\n        {\r\n            Console.WriteLine(\"*********************** Object Model Generator ***********************\");\r\n\r\n            var arg = ArgumentParser.Parse(args);\r\n            List<ICodeGenerator> generators = new List<ICodeGenerator>();\r\n            if (arg.ContainsKey(\"format\"))\r\n            {\r\n                var formats = arg[\"format\"].Split(';', StringSplitOptions.RemoveEmptyEntries);\r\n                foreach (var format in formats)\r\n                    if (format == \"md\")\r\n                        generators.Add(new Generators.MarkdownGenerator());\r\n                    else if (format == \"html\")\r\n                        generators.Add(new Generators.HtmlOmdGenerator());\r\n                    else\r\n                    {\r\n                        Console.WriteLine(\"Invalid format parameter.\");\r\n                        WriteUsage();\r\n                        return;\r\n                    }\r\n            }\r\n            if(!generators.Any())\r\n            {\r\n                generators.Add(new Generators.HtmlOmdGenerator());\r\n            }\r\n            if (!arg.ContainsKey(\"source\") && !arg.ContainsKey(\"assemblies\") && !arg.ContainsKey(\"nuget\"))\r\n            {\r\n                WriteUsage();\r\n                return;\r\n            }\r\n\r\n            GeneratorSettings.ShowPrivateMembers = arg.ContainsKey(\"showPrivate\");\r\n            GeneratorSettings.ShowInternalMembers = arg.ContainsKey(\"showInternal\");\r\n            if(arg.ContainsKey(\"output\"))\r\n                GeneratorSettings.OutputLocation = arg[\"output\"];\r\n            List<Regex> filters = arg.ContainsKey(\"exclude\") ? arg[\"exclude\"].Split(';', StringSplitOptions.RemoveEmptyEntries).Select(f=>CreateFilter(f)).ToList() : new List<Regex>();\r\n            if(arg.ContainsKey(\"regexfilter\"))\r\n                filters.Add(new Regex(arg[\"regexfilter\"]));\r\n            string[] source = arg.ContainsKey(\"source\") ? arg[\"source\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : new string[] { };\r\n            string[] oldSource = arg.ContainsKey(\"compareSource\") ? arg[\"compareSource\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] preprocessors = arg.ContainsKey(\"preprocessors\") ? arg[\"preprocessors\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] assemblies = arg.ContainsKey(\"assemblies\") ? arg[\"assemblies\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : new string[] { };\r\n            string[] compareAssemblies = arg.ContainsKey(\"compareAssemblies\") ? arg[\"compareAssemblies\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] referenceAssemblies = arg.ContainsKey(\"referenceAssemblies\") ? arg[\"referenceAssemblies\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] filterTypes = arg.ContainsKey(\"filter\") ? arg[\"filter\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] nugetPackages = arg.ContainsKey(\"nuget\") ? arg[\"nuget\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string[] compareNugetPackages = arg.ContainsKey(\"compareNuget\") ? arg[\"compareNuget\"].Split(';', StringSplitOptions.RemoveEmptyEntries) : null;\r\n            string tfm = arg.ContainsKey(\"tfm\") ? arg[\"tfm\"] : null;\r\n\r\n            // Fetch nuget packages\r\n            if (nugetPackages != null && nugetPackages.Length > 0)\r\n            {\r\n                var nugetAssemblies = await ParseNugets(nugetPackages, tfm);\r\n                if (nugetAssemblies is null)\r\n                    return;\r\n                Console.WriteLine($\"Found {nugetAssemblies.Length} assemblies in nuget packages\");\r\n                assemblies = assemblies == null ? nugetAssemblies : assemblies.Concat(nugetAssemblies).ToArray();\r\n            }\r\n            if (compareNugetPackages != null && compareNugetPackages.Length > 0)\r\n            {\r\n                var nugetAssemblies = await ParseNugets(compareNugetPackages, tfm);\r\n                if (nugetAssemblies is null)\r\n                    return;\r\n                Console.WriteLine($\"Found {nugetAssemblies.Length} assemblies in nuget packages\");\r\n                compareAssemblies = compareAssemblies == null ? nugetAssemblies : compareAssemblies.Concat(nugetAssemblies).ToArray();\r\n            }\r\n\r\n            var g = new Generator(generators);\r\n\r\n            //Set up output filename\r\n            if (string.IsNullOrEmpty(GeneratorSettings.OutputLocation))\r\n                GeneratorSettings.OutputLocation = \"./\";\r\n            var fi = new System.IO.FileInfo(GeneratorSettings.OutputLocation);\r\n            if (!fi.Directory.Exists)\r\n                throw new System.IO.DirectoryNotFoundException(fi.Directory.FullName);\r\n            if (fi.Attributes == System.IO.FileAttributes.Directory)\r\n                GeneratorSettings.OutputLocation = System.IO.Path.Combine(GeneratorSettings.OutputLocation, \"OMD\");\r\n\r\n            if (oldSource != null || compareAssemblies != null)\r\n                await g.ProcessDiffs(oldSource, source, compareAssemblies, assemblies, preprocessors, filters.ToArray(), referenceAssemblies, filterTypes);\r\n            else\r\n                await g.Process(source, assemblies, preprocessors, filters.ToArray(), referenceAssemblies, filterTypes);\r\n\r\n            if(System.Diagnostics.Debugger.IsAttached)\r\n                Console.ReadKey();\r\n        }\r\n        static List<FindPackageByIdResource> resources;\r\n        private async static Task<string[]> ParseNugets(string[] nugetPackages, string tfm)\r\n        {\r\n            if (string.IsNullOrEmpty(tfm))\r\n            {\r\n                Console.WriteLine(\"A target framework identifier is required with nuget parameter. For example: '-tfm net8.0-windows10.0.19041.0'\");\r\n                return null;\r\n            }\r\n\r\n            if (resources is null)\r\n            {\r\n                var settings = NuGet.Configuration.Settings.LoadDefaultSettings(null);\r\n                var sources = NuGet.Configuration.SettingsUtility.GetEnabledSources(settings);\r\n                resources = new List<FindPackageByIdResource>();\r\n                foreach (var source in sources)\r\n                {\r\n                    List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();\r\n                    providers.AddRange(Repository.Provider.GetCoreV3());  // Add v3 API support\r\n\r\n                    SourceRepository repository = new SourceRepository(source, providers);\r\n                    FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>();\r\n                    resources.Add(resource);\r\n                }\r\n            }\r\n\r\n                List<string> nugetAssemblies = new List<string>();\r\n            // https://www.nuget.org/api/v2/package/Newtonsoft.Json/13.0.3\r\n            foreach (var package in nugetPackages)\r\n            {\r\n                if (!package.Contains(\":\"))\r\n                {\r\n                    Console.WriteLine($\"Invalid nuget identifier {package}. Please use the format `nugetid:version`, for example 'Newtonsoft.Json:13.0.3'\");\r\n                    return null;\r\n                }\r\n                string[] id = package.Split(':', 2, StringSplitOptions.None);\r\n                if (id.Length != 2)\r\n                {\r\n                    Console.WriteLine($\"Invalid nuget identifier {package}\");\r\n                    return null;\r\n                }\r\n                NuGet.Versioning.NuGetVersion version;\r\n                if (!NuGet.Versioning.NuGetVersion.TryParse(id[1], out version))\r\n                {\r\n                    Console.WriteLine($\"Invalid nuget version {id[1]}\");\r\n                    return null;\r\n                }\r\n                //var f = NuGet.Frameworks.AssetTargetFallbackFramework.ParseFrameworkName(tfm, new NuGet.Frameworks.DefaultFrameworkNameProvider());\r\n                var f = NuGet.Frameworks.NuGetFramework.Parse(tfm, new NuGet.Frameworks.DefaultFrameworkNameProvider());\r\n\r\n                Console.WriteLine($\"Getting NuGet package {package}...\");\r\n                MemoryStream resultStream = null;\r\n                foreach (var resource in resources)\r\n                {\r\n                    var exists = await resource.DoesPackageExistAsync(id[0], version, new SourceCacheContext(), NuGet.Common.NullLogger.Instance, System.Threading.CancellationToken.None);\r\n                    if (!exists)\r\n                    {\r\n                        continue;\r\n                    }\r\n                    MemoryStream packageStream = new MemoryStream();\r\n                    bool result = await resource.CopyNupkgToStreamAsync(\r\n                        id[0],\r\n                        version,\r\n                        packageStream,\r\n                        new SourceCacheContext(),\r\n                        NuGet.Common.NullLogger.Instance,\r\n                        System.Threading.CancellationToken.None);\r\n                    if (result)\r\n                    {\r\n                        resultStream = packageStream;\r\n                        resultStream.Seek(0, SeekOrigin.Begin);\r\n                        break;\r\n                    }\r\n                    else\r\n                    {\r\n                        packageStream.Dispose();\r\n                    }\r\n                }\r\n                if (resultStream is null)\r\n                {\r\n                    Console.WriteLine($\"'{package}' not found\");\r\n                    return null;\r\n                }\r\n                using var packageReader = new NuGet.Packaging.PackageArchiveReader(resultStream);\r\n                var libs = (await packageReader.GetLibItemsAsync(CancellationToken.None)).ToList();\r\n                var nearest = NuGet.Frameworks.NuGetFrameworkExtensions.GetNearest(libs, f);\r\n\r\n                if (nearest is null)\r\n                {\r\n                    Console.ForegroundColor = ConsoleColor.Yellow;\r\n                    Console.WriteLine($\"Warning: No compatible target framework libs found for '{tfm}' in '{package}'\");\r\n                    Console.ResetColor();\r\n                    resultStream.Dispose();\r\n                    continue;\r\n                }\r\n                var path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());\r\n                packageReader.CopyFiles(path, nearest.Items.Where(i => !i.EndsWith(\"/\")), (string sourceFile, string targetPath, Stream fileStream) =>\r\n                {\r\n                    FileInfo fi = new FileInfo(targetPath);\r\n                    if (!fi.Directory.Exists)\r\n                        fi.Directory.Create();\r\n                    using var fs = File.Create(targetPath);\r\n                    fileStream.CopyTo(fs);\r\n                    nugetAssemblies.Add(targetPath);\r\n                    return targetPath;\r\n                }, NuGet.Common.NullLogger.Instance, CancellationToken.None);\r\n                resultStream.Dispose();\r\n            }\r\n            return nugetAssemblies.ToArray();\r\n        }\r\n\r\n        private static System.Text.RegularExpressions.Regex CreateFilter(string pattern, bool caseSensitive = false)\r\n        {\r\n            return new Regex(\"^\" + Regex.Escape(pattern).\r\n             Replace(\"\\\\*\", \".*\").\r\n             Replace(\"\\\\?\", \".\") + \"$\", caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);\r\n        }\r\n\r\n        private static void WriteUsage()\r\n        {\r\n            Console.WriteLine(\"\\nUsage:\");\r\n            Console.WriteLine(\" --source=[source folder] --compareSource=[oldSourceFolder] --preprocessors=[defines] --output=[out location] --format=[html,md] --filter=[regex] --showPrivate --showInternal\");\r\n            Console.WriteLine(\"\\nRequired parameters (one or more):\");\r\n            Console.WriteLine(\"  source               Specifies the folder of source files to include for the object model.\\n                       Separate with ; for multiple folders\");\r\n            Console.WriteLine(\"  assemblies           Specifies a set of assemblies to include for the object model.\\n                       Separate with ; for multiple assemblies\");\r\n            Console.WriteLine(\"\\nOptional parameters:\");\r\n            Console.WriteLine(\"  compareSource        Specifies a folder to compare source and generate a diff model\\n                       This can be useful for finding API changes or compare branches\");\r\n            Console.WriteLine(\"  compareAssemblies    Specifies a set of assemblies to include to generate a adiff model.\\n                       Separate with ; for multiple assemblies\");\r\n            Console.WriteLine(\"  output        Output location\");\r\n            Console.WriteLine(\"  preprocessors        Define a set of preprocessors values. Use ; to separate multiple\");\r\n            Console.WriteLine(\"  exclude              Defines one or more strings that can't be part of the path Ie '/Samples/;/UnitTests/'\\n                       (use forward slash for folder separators)\");\r\n            Console.WriteLine(\"  regexfilter          Defines a regular expression for filtering on full file names in the source\");\r\n            Console.WriteLine(\"  referenceAssemblies  Specifies a set of assemblies to include for references for better type resolution.\");\r\n            Console.WriteLine(\"  showPrivate          Show private members (default is false)\");\r\n            Console.WriteLine(\"  showInternal         Show internal members (default is false)\");\r\n            Console.WriteLine(\"  filter               A set of namespaces or classes to ignore. For example: -filter=Microsoft.CSharp;Microsoft.VisualBasic\"); \r\n            Console.Write(\"Using Nuget comparison:\");\r\n            Console.WriteLine(\"  nuget                nuget packages to generate OMD for (separate multiple with semicolon). Example: /nuget=Newtonsoft.Json:13.0.0\");\r\n            Console.WriteLine(\"  compareNuget         nuget packages to compare versions with (separate multiple with semicolon). Example: /nuget=Newtonsoft.Json:12.0.0\");\r\n            Console.WriteLine(\"  tfm                  Target Framework to use against NuGet package. Example: /tfm=net8.0-windows10.0.19041.0\");\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/TypeExtensions.cs",
    "content": "﻿using Microsoft.CodeAnalysis;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Xml;\r\n\r\nnamespace Generator\r\n{\r\n    internal static class TypeExtensions\r\n    {\r\n        public static string GetDescription(this ISymbol type)\r\n        {\r\n            string xml = null;\r\n            if (type.Kind == SymbolKind.Parameter)\r\n            {\r\n                xml = type.ContainingSymbol.GetDocumentationCommentXml();\r\n            }\r\n            else\r\n            {\r\n                xml = type.GetDocumentationCommentXml();\r\n            }\r\n            if (!string.IsNullOrEmpty(xml))\r\n            {\r\n                XmlDocument doc = new XmlDocument();\r\n                XmlElement elm = null;\r\n                try\r\n                {\r\n                    doc.LoadXml(xml);\r\n                }\r\n                catch\r\n                {\r\n                    return null;\r\n                }\r\n                if (type.Kind == SymbolKind.Parameter)\r\n                {\r\n                    elm = doc.GetElementsByTagName(\"param\").OfType<XmlElement>().Where(e => e.Attributes[\"name\"]?.Value == type.Name).FirstOrDefault();\r\n                }\r\n                else\r\n                {\r\n                    elm = doc.GetElementsByTagName(\"summary\").OfType<XmlElement>().FirstOrDefault();\r\n                }\r\n                if(elm != null)\r\n                {\r\n                    foreach(var n in elm.ChildNodes.OfType<XmlElement>())\r\n                    {\r\n                        if(n.Name == \"see\")\r\n                        {\r\n                            // strip down xml <see cref=\"...\"/> to just the type name\r\n                            if (string.IsNullOrEmpty(n.InnerText))\r\n                            {\r\n                                var cref = n.GetAttribute(\"cref\");\r\n                                var idx = cref.LastIndexOf(\".\");\r\n                                if (idx == -1)\r\n                                    idx = cref.IndexOf(\":\");\r\n                                if (idx > -1)\r\n                                    n.InnerText = cref.Substring(idx + 1);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                return elm?.InnerText.Trim();\r\n            }\r\n            return null;\r\n        }\r\n\r\n        private static IEnumerable<ISymbol> GetAllMembers(this INamedTypeSymbol type)\r\n        {\r\n            IEnumerable<ISymbol> members = type.GetMembers().Where(m => !m.IsOverride);\r\n            if (!GeneratorSettings.ShowPrivateMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Private && m.DeclaredAccessibility != Accessibility.ProtectedAndFriend);\r\n            if (!GeneratorSettings.ShowInternalMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Internal);\r\n            return members;\r\n        }\r\n        internal static IEnumerable<INamedTypeSymbol> GetAllNestedTypes(this INamedTypeSymbol type)\r\n        {\r\n            if (type == null) return Enumerable.Empty<INamedTypeSymbol>();\r\n            IEnumerable<INamedTypeSymbol> members = type.GetTypeMembers();\r\n            if (!GeneratorSettings.ShowPrivateMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Private && m.DeclaredAccessibility != Accessibility.ProtectedAndFriend);\r\n            if (!GeneratorSettings.ShowInternalMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Internal);\r\n            return members;\r\n        }\r\n\r\n        public static IEnumerable<IMethodSymbol> GetMethods(this INamedTypeSymbol type)\r\n        {\r\n            if (type.TypeKind == TypeKind.Delegate)\r\n                return Enumerable.Empty<IMethodSymbol>();\r\n            return type.GetAllMembers().OfType<IMethodSymbol>()\r\n                .Where(m => m.CanBeReferencedByName)\r\n                .OrderBy(m => string.Join(',', m.Parameters.Select(p => p.Name))).OrderBy(m=>m.Name);\r\n        }\r\n\r\n        public static IEnumerable<(IMethodSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetMethods(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n            {\r\n                return GetMethods(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n                //foreach (var item in GetMethods(type ?? oldType).Select(p => (p, type == null, p.IsObsolete())))\r\n                //    yield return item;\r\n            }\r\n            else\r\n            {\r\n                var newMembers = GetMethods(type).ToList();\r\n                var oldMembers = GetMethods(oldType).ToList();\r\n                var result = newMembers.Except(oldMembers, Generator.MethodComparer.Comparer).Select(p => (p, false, false))\r\n                    .Union(oldMembers.Except(newMembers, Generator.MethodComparer.Comparer).Select(p => (p, true, false)))\r\n                    .Union(newMembers.Where(n => n.IsObsolete() && oldMembers.Any(o => !o.IsObsolete() && Generator.MethodComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                 .OrderBy(t => string.Join(',', t.Item1.Parameters.Select(p => p.Name))).OrderBy(t => t.Item1.Name);\r\n                foreach (var item in result.ToArray())\r\n                {\r\n                    if (item.Item2 == true)//Item was removed. Check if it was just moved up to a base-class\r\n                    {\r\n                        if (item.p.IsOverride)\r\n                            continue; //If override has been removed, just ignore, as it's not a removed method in that sense\r\n                        var basetype = type.BaseType;\r\n                        bool matchFound = false;\r\n                        while (basetype != null && !matchFound)\r\n                        {\r\n                            var members = basetype.GetMembers(item.p.Name);\r\n                            if (members.Any())\r\n                            {\r\n                                var identifier = item.p.ToDisplayString(Generator.Constants.AllFormatWithoutContaining);\r\n                                if (members.OfType<IMethodSymbol>().Any(m=>identifier == m.ToDisplayString(Generator.Constants.AllFormatWithoutContaining)))\r\n                                {\r\n                                    matchFound = true;\r\n                                    continue;\r\n                                }\r\n                            }\r\n                            basetype = basetype.BaseType;\r\n                        }\r\n                        if (matchFound)\r\n                        {\r\n                            if (newMembers.Contains(item.p))\r\n                                newMembers.Remove(item.p);\r\n                            else if (oldMembers.Contains(item.p))\r\n                                oldMembers.Remove(item.p);\r\n                            continue;\r\n                        }\r\n                        //Check if optional was changed to explicit overloads\r\n                        if (item.p.Parameters.Any(p => p.IsOptional) && newMembers.Any(n=>n.Name == item.p.Name))\r\n                        {\r\n                            bool found = true;\r\n                            var newOverloads = newMembers.Where(n => n.Name == item.p.Name).ToList();\r\n                            var start = item.p.Parameters.IndexOf(item.p.Parameters.First(item => item.IsOptional));\r\n                            List<IMethodSymbol> foundNewMembers = new List<IMethodSymbol>();\r\n                            for (int i = start; i <= item.p.Parameters.Length; i++)\r\n                            {\r\n                                var ps = item.p.Parameters.Take(i);\r\n                                var matches = newOverloads.Where(n => n.Parameters.Length == i);\r\n                                for (int j = 0; j < i; j++)\r\n                                {\r\n                                    matches = matches.Where(m =>  m.Parameters[j].Type.GetFullTypeName() == item.p.Parameters[j].Type.GetFullTypeName()).ToList();\r\n                                }\r\n                                if (matches.Count() == 1)\r\n                                {\r\n                                    foundNewMembers.Add(matches.Single());\r\n                                }\r\n                                else\r\n                                    found = false;\r\n                            }\r\n                            if (found)\r\n                            {\r\n                                foreach(var member in foundNewMembers)\r\n                                    newMembers.Remove(member);\r\n                                if (oldMembers.Contains(item.p))\r\n                                    oldMembers.Remove(item.p);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                return result;\r\n            }\r\n        }\r\n\r\n        public static IEnumerable<IPropertySymbol> GetProperties(this INamedTypeSymbol type)\r\n        {\r\n            return type.GetAllMembers().OfType<IPropertySymbol>().Where(m => m.CanBeReferencedByName).OrderBy(m=>m.Name);\r\n        }\r\n\r\n        public static IEnumerable<(IPropertySymbol symbol, bool wasRemoved, bool wasObsoleted)> GetProperties(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n                return GetProperties(type ?? oldType).Select(p=>(p, type == null, p.IsObsolete()));\r\n            var newProps = GetProperties(type);\r\n            var oldProps = GetProperties(oldType);\r\n            return newProps.Except(oldProps, Generator.PropertyComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldProps.Except(newProps, Generator.PropertyComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newProps.Where(n => n.IsObsolete() && oldProps.Any(o => !o.IsObsolete() && Generator.PropertyComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n        }\r\n\r\n        public static IEnumerable<IFieldSymbol> GetFields(this INamedTypeSymbol type)\r\n        {\r\n            return type.GetAllMembers().OfType<IFieldSymbol>().Where(m => m.CanBeReferencedByName).OrderBy(m => m.Name);\r\n        }\r\n\r\n        public static IEnumerable<(IFieldSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetFields(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (type.TypeKind == TypeKind.Enum)\r\n                return Enumerable.Empty<(IFieldSymbol symbol, bool wasRemoved, bool wasObsoleted)> ();\r\n\r\n            if (oldType == null || type == null)\r\n                return GetFields(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n            var newProps = GetFields(type);\r\n            var oldProps = GetFields(oldType);\r\n            return newProps.Except(oldProps, Generator.FieldComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldProps.Except(newProps, Generator.FieldComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newProps.Where(n => n.IsObsolete() && oldProps.Any(o => !o.IsObsolete() && Generator.FieldComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n        }\r\n\r\n        public static IEnumerable<INamedTypeSymbol> GetInterfaces(this INamedTypeSymbol type)\r\n        {\r\n            IEnumerable<INamedTypeSymbol> i = type.Interfaces;\r\n            if (!GeneratorSettings.ShowPrivateMembers)\r\n                i = i.Where(m => m.DeclaredAccessibility != Accessibility.Private && m.DeclaredAccessibility != Accessibility.ProtectedAndFriend);\r\n            if (!GeneratorSettings.ShowInternalMembers)\r\n                i = i.Where(m => m.DeclaredAccessibility != Accessibility.Internal && m.DeclaredAccessibility != Accessibility.NotApplicable);\r\n            return i;\r\n        }\r\n\r\n        public static IEnumerable<(INamedTypeSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetInterfaces(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n                return GetInterfaces(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n            var newMembers = GetInterfaces(type);\r\n            var oldMembers = GetInterfaces(oldType);\r\n            return newMembers.Except(oldMembers, Generator.SymbolNameComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldMembers.Except(newMembers, Generator.SymbolNameComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newMembers.Where(n => n.IsObsolete() && oldMembers.Any(o => !o.IsObsolete() && Generator.SymbolNameComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n        }\r\n\r\n        public static bool IsSettable(this IPropertySymbol prop)\r\n        {\r\n            if (prop.SetMethod == null)\r\n                return false;\r\n            if (prop.SetMethod.DeclaredAccessibility == Accessibility.Private && !GeneratorSettings.ShowPrivateMembers)\r\n                return false;\r\n            if (prop.SetMethod.DeclaredAccessibility == Accessibility.Internal && !GeneratorSettings.ShowInternalMembers)\r\n                return false;\r\n            // if (prop.SetMethod.DeclaredAccessibility == Accessibility.Public || prop.SetMethod.DeclaredAccessibility == Accessibility.Protected)\r\n            //     return true;\r\n            return true;\r\n        }\r\n        public static bool IsReadable(this IPropertySymbol prop)\r\n        {\r\n            if (prop.GetMethod == null)\r\n                return false;\r\n            if (prop.GetMethod.DeclaredAccessibility == Accessibility.Private && !GeneratorSettings.ShowPrivateMembers)\r\n                return false;\r\n            if (prop.GetMethod.DeclaredAccessibility == Accessibility.Internal && !GeneratorSettings.ShowInternalMembers)\r\n                return false;\r\n            // if (prop.SetMethod.DeclaredAccessibility == Accessibility.Public || prop.SetMethod.DeclaredAccessibility == Accessibility.Protected)\r\n            //     return true;\r\n            return true;\r\n        }\r\n        public static bool IsObsolete(this ISymbol prop)\r\n        {\r\n            return prop.GetAttributes().Any(a => a.AttributeClass.GetFullTypeName() == \"System.ObsoleteAttribute\" || a.AttributeClass.GetFullTypeName() == \"Obsolete\");\r\n        }\r\n        public static IEnumerable<IEventSymbol> GetEvents(this INamedTypeSymbol type)\r\n        {\r\n            return type.GetAllMembers().OfType<IEventSymbol>().Where(m => m.CanBeReferencedByName).OrderBy(m => m.Name);\r\n        }\r\n\r\n        public static IEnumerable<(IEventSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetEvents(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n                return GetEvents(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n            var newMembers = GetEvents(type);\r\n            var oldMembers = GetEvents(oldType);\r\n            return newMembers.Except(oldMembers, Generator.EventComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldMembers.Except(newMembers, Generator.EventComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newMembers.Where(n => n.IsObsolete() && oldMembers.Any(o => !o.IsObsolete() && Generator.EventComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n        }\r\n\r\n        public static IEnumerable<IMethodSymbol> GetConstructors(this INamedTypeSymbol type)\r\n        {\r\n            if (type.TypeKind == TypeKind.Enum)\r\n                return Enumerable.Empty<IMethodSymbol>();\r\n            IEnumerable<IMethodSymbol> members = type.Constructors; //.Where(c=>c.CanBeReferencedByName);\r\n            if (!GeneratorSettings.ShowPrivateMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Private && m.DeclaredAccessibility != Accessibility.ProtectedAndFriend);\r\n            if (!GeneratorSettings.ShowInternalMembers)\r\n                members = members.Where(m => m.DeclaredAccessibility != Accessibility.Internal);\r\n            return members.OrderBy(m => string.Join(',', m.Parameters.Select(p => p.Name)));\r\n        }\r\n\r\n        public static IEnumerable<(IMethodSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetConstructors(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n                return GetConstructors(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n            var newMembers = GetConstructors(type).ToList();\r\n            var oldMembers = GetConstructors(oldType).ToList();\r\n            var result = newMembers.Except(oldMembers, Generator.MethodComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldMembers.Except(newMembers, Generator.MethodComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newMembers.Where(n => n.IsObsolete() && oldMembers.Any(o => !o.IsObsolete() && Generator.MethodComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n            foreach (var item in result.ToArray())\r\n            {\r\n                if (item.Item2 == true)//Item was removed. Check if it was just moved up to a base-class\r\n                {\r\n                    //Check if optional was changed to explicit overloads\r\n                    if (item.p.Parameters.Any(p => p.IsOptional) && newMembers.Any(n => n.Name == item.p.Name))\r\n                    {\r\n                        bool found = true;\r\n                        var newOverloads = newMembers.Where(n => n.Name == item.p.Name).ToList();\r\n                        var start = item.p.Parameters.IndexOf(item.p.Parameters.First(item => item.IsOptional));\r\n                        List<IMethodSymbol> foundNewMembers = new List<IMethodSymbol>();\r\n                        for (int i = start; i <= item.p.Parameters.Length; i++)\r\n                        {\r\n                            var ps = item.p.Parameters.Take(i);\r\n                            var matches = newOverloads.Where(n => n.Parameters.Length == i);\r\n                            for (int j = 0; j < i; j++)\r\n                            {\r\n                                matches = matches.Where(m => m.Parameters[j].Type.GetFullTypeName() == item.p.Parameters[j].Type.GetFullTypeName()).ToList();\r\n                            }\r\n                            if (matches.Count() == 1)\r\n                            {\r\n                                foundNewMembers.Add(matches.Single());\r\n                            }\r\n                            else\r\n                                found = false;\r\n                        }\r\n                        if (found)\r\n                        {\r\n                            foreach (var member in foundNewMembers)\r\n                                newMembers.Remove(member);\r\n                            if (oldMembers.Contains(item.p))\r\n                                oldMembers.Remove(item.p);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            return result;\r\n        }\r\n\r\n        public static IEnumerable<IFieldSymbol> GetEnums(this INamedTypeSymbol type)\r\n        {\r\n            if (type.TypeKind != TypeKind.Enum)\r\n                return new IFieldSymbol[] { };\r\n            return type.GetAllMembers().OfType<IFieldSymbol>().OrderBy(f => f.ConstantValue);\r\n        }\r\n\r\n        public static IEnumerable<(IFieldSymbol symbol, bool wasRemoved, bool wasObsoleted)> GetEnums(this INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (oldType == null || type == null)\r\n                return GetEnums(type ?? oldType).Select(p => (p, type == null, p.IsObsolete()));\r\n            var newMembers = GetEnums(type);\r\n            var oldMembers = GetEnums(oldType);\r\n            return newMembers.Except(oldMembers, Generator.FieldComparer.Comparer).Select(p => (p, false, false))\r\n                .Union(oldMembers.Except(newMembers, Generator.FieldComparer.Comparer).Select(p => (p, true, false)))\r\n                .Union(newMembers.Where(n => n.IsObsolete() && oldMembers.Any(o => !o.IsObsolete() && Generator.FieldComparer.Comparer.Equals(o, n))).Select(p => (p, false, true))) //Obsoleted\r\n                .OrderBy(t => t.Item1.Name);\r\n        }\r\n\r\n        public static string GetFullTypeName(this ITypeSymbol type)\r\n        {\r\n            string name = type.Name;\r\n            var ns = type.ContainingNamespace;\r\n            while (ns != null && !ns.IsGlobalNamespace)\r\n            {\r\n                name = ns + \".\" + name;\r\n                ns = ns.ContainingNamespace;\r\n            }\r\n            return name;\r\n        }\r\n        public static string GetFullNamespace(this ITypeSymbol type)\r\n        {\r\n            var name = \"\";\r\n            var ns = type.ContainingNamespace;\r\n            while (ns != null && !ns.IsGlobalNamespace)\r\n            {\r\n                if (string.IsNullOrEmpty(name))\r\n                    name += ns.Name;\r\n                else\r\n                    name = ns.Name + \".\" + name;\r\n                ns = ns.ContainingNamespace;\r\n            }\r\n            return name;\r\n        }\r\n\r\n        public static string GetFullTypeString(this INamedTypeSymbol type)\r\n        {\r\n            string result = type.Name;\r\n\r\n            if (type.TypeArguments.Length > 0)\r\n            {\r\n                result += \"<\";\r\n\r\n                bool isFirstIteration = true;\r\n                foreach (INamedTypeSymbol typeArg in type.TypeArguments.OfType< INamedTypeSymbol>())\r\n                {\r\n                    if (isFirstIteration)\r\n                    {\r\n                        isFirstIteration = false;\r\n                    }\r\n                    else\r\n                    {\r\n                        result += \", \";\r\n                    }\r\n\r\n                    result += GetFullTypeString(typeArg);\r\n                }\r\n\r\n                result += \">\";\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        public static string GetFullNamespace(this INamespaceSymbol ns)\r\n        {\r\n            if (ns.IsGlobalNamespace) return string.Empty;\r\n            string name = ns.Name;\r\n            ns = ns.ContainingNamespace;\r\n            while (ns != null && !ns.IsGlobalNamespace)\r\n            {\r\n                name = ns + \".\" + name;\r\n                ns = ns.ContainingNamespace;\r\n            }\r\n            return name;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Generator/WorkspaceHelper.cs",
    "content": "﻿using Microsoft.CodeAnalysis;\r\nusing Microsoft.CodeAnalysis.Text;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing System.Net.Http;\r\nusing System.Text.RegularExpressions;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Generator\r\n{\r\n    internal class Generator\r\n    {\r\n        private IEnumerable<ICodeGenerator> generators;\r\n\r\n        public Generator(IEnumerable<ICodeGenerator> generators)\r\n        {\r\n            this.generators = generators;\r\n        }\r\n\r\n        internal async Task Process(IEnumerable<string> paths, IEnumerable<string> assemblies, IEnumerable<string> preprocessors = null, Regex[] filters = null, string[] referenceAssemblies = null, string[] objectFilters = null)\r\n        {\r\n            var compilation = await CreateCompilationAsync(paths, assemblies, preprocessors, filters, referenceAssemblies);\r\n            Console.WriteLine(\"Processing types...\");\r\n            var symbols = GetSymbols(compilation.compilation, compilation.metadata);\r\n\r\n            foreach (var generator in generators)\r\n            {\r\n                generator.Initialize(symbols);\r\n                foreach (var s in symbols)\r\n                {\r\n                    if (objectFilters is not null && objectFilters.Any(o => s.ToDisplayString().StartsWith(o)))\r\n                        continue;\r\n                    GenerateCode(generator, s);\r\n                }\r\n                generator.Complete();\r\n            }\r\n            Console.WriteLine(\"Complete\");\r\n        }\r\n\r\n        private List<INamedTypeSymbol> GetSymbols(Compilation compilation, IEnumerable<MetadataReference> assemblies)\r\n        {\r\n            Action<INamespaceSymbol, List<INamespaceSymbol>> getNamespaces = null;\r\n            getNamespaces = (inss, list) =>\r\n            {\r\n                foreach (var childNs in inss.GetMembers().OfType<INamespaceSymbol>().Where(n => n.Locations.Any(l => l.Kind == LocationKind.SourceFile)))\r\n                {\r\n                    list.Add(childNs);\r\n                    getNamespaces(childNs, list);\r\n                }\r\n                foreach (var childNs in inss.GetMembers().OfType<INamespaceSymbol>().Where(n => n.Locations.Any(l => l.Kind == LocationKind.MetadataFile)))\r\n                {\r\n                    list.Add(childNs);\r\n                    getNamespaces(childNs, list);\r\n                }\r\n            };\r\n            List<INamespaceSymbol> namespaces = new List<INamespaceSymbol>();\r\n            getNamespaces(compilation.GlobalNamespace, namespaces);\r\n            List<INamedTypeSymbol> symbols = new List<INamedTypeSymbol>();\r\n            foreach (var ns in namespaces)\r\n            {\r\n                symbols.AddRange(GetTypes(ns, assemblies));\r\n            }\r\n            symbols = symbols.OrderBy(t => t.Name).OrderBy(t => t.GetFullNamespace()).ToList();\r\n            return symbols;\r\n        }\r\n\r\n        private IEnumerable<INamedTypeSymbol> GetTypes(INamespaceSymbol ns, IEnumerable<MetadataReference> assemblies)\r\n        {\r\n            foreach (var type in ns.GetTypeMembers().OfType<INamedTypeSymbol>())\r\n            {\r\n                if (type.Locations.Any(l => l.Kind == LocationKind.MetadataFile))\r\n                {\r\n                    var loc = type.Locations.First(l => l.Kind == LocationKind.MetadataFile);\r\n                    var meta = loc.MetadataModule.GetMetadata();\r\n                    if (!assemblies.Any(n => n.Display.EndsWith(meta.Name)))\r\n                        continue;\r\n                }\r\n                else if (type.Locations.Any(l => l.Kind != LocationKind.SourceFile))\r\n                    continue;\r\n                if (type.DeclaredAccessibility == Accessibility.Private && !GeneratorSettings.ShowPrivateMembers)\r\n                    continue;\r\n                if (type.DeclaredAccessibility == Accessibility.Internal && !GeneratorSettings.ShowInternalMembers)\r\n                    continue;\r\n                yield return type;\r\n            }\r\n        }\r\n\r\n        private void GenerateCode(ICodeGenerator generator, INamedTypeSymbol type)\r\n        {\r\n            Console.WriteLine(type.GetFullTypeName());\r\n            if (type.TypeKind == TypeKind.Enum)\r\n                generator.WriteEnum(type);\r\n            else if (type.TypeKind == TypeKind.Interface)\r\n                generator.WriteInterface(type);\r\n            else if (type.TypeKind == TypeKind.Class || type.TypeKind == TypeKind.Struct)\r\n                generator.WriteClass(type);\r\n            else if (type.TypeKind == TypeKind.Delegate)\r\n                generator.WriteDelegate(type);\r\n            else\r\n            {\r\n                Console.WriteLine(\"****TODO**** ERROR: No generator for type \" + type.GetFullTypeName() + \" of kind \" + type.TypeKind.ToString());\r\n            }\r\n        }\r\n\r\n        internal async Task<(Compilation compilation, List<MetadataReference> metadata)> CreateCompilationAsync(IEnumerable<string> paths, IEnumerable<string> assemblies, IEnumerable<string> preprocessors = null, Regex[] filters = null, string[] referenceAssemblies = null)\r\n        {\r\n            Console.WriteLine(\"Creating workspace...\");\r\n\r\n            var ws = new AdhocWorkspace();\r\n            var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default);\r\n            ws.AddSolution(solutionInfo);\r\n            var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, \"CSharpExample\", \"CSharpExample\", \"C#\");\r\n            ws.AddProject(projectInfo);\r\n            if (paths != null)\r\n            {\r\n                foreach (var path in paths)\r\n                {\r\n                    if (path.StartsWith(\"http://\") || path.StartsWith(\"https://\"))\r\n                    {\r\n                        await DownloadDocumentsAsync(path, ws, projectInfo.Id, filters).ConfigureAwait(false);\r\n                    }\r\n                    else if (path.EndsWith(\".zip\"))\r\n                    {\r\n                        LoadCompressedDocuments(path, ws, projectInfo.Id, filters);\r\n                    }\r\n                    else\r\n                    {\r\n                        LoadFolderDocuments(path, ws, projectInfo.Id, filters);\r\n                    }\r\n                }\r\n            }\r\n            Console.WriteLine(\"Compiling...\");\r\n            var project = ws.CurrentSolution.Projects.Single();\r\n            List<MetadataReference> metadata = new List<MetadataReference>();\r\n            if (assemblies != null)\r\n            {\r\n                foreach (var assm in assemblies)\r\n                {\r\n                    IEnumerable<FileInfo> files = Enumerable.Empty<FileInfo>();\r\n                    if (File.Exists(assm))\r\n                    {\r\n                        files = new FileInfo[] { new FileInfo(assm) };\r\n                    }\r\n                    else\r\n                    {\r\n                        string recursive = Path.DirectorySeparatorChar + \"**\" + Path.DirectorySeparatorChar;\r\n                        bool isRecursive = false;\r\n                        var d = assm;\r\n                        var fn = Path.GetFileName(assm);\r\n                        if (d.Contains(recursive))\r\n                        {\r\n                            d = d.Substring(0, d.IndexOf(recursive));\r\n                            isRecursive = true;\r\n                        }\r\n                        else if (Directory.Exists(d))\r\n                        {\r\n                            fn = null;\r\n                        }\r\n                        else\r\n                        {\r\n                            d = Path.GetDirectoryName(d);\r\n                        }\r\n                        var dir = new DirectoryInfo(d);\r\n                        if (!dir.Exists)\r\n                            throw new DirectoryNotFoundException(d);\r\n                        if (string.IsNullOrEmpty(fn))\r\n                        {\r\n                            files = dir.GetFiles(\"*.dll\", isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);\r\n                        }\r\n                        else\r\n                        {\r\n                            var di = new DirectoryInfo(d);\r\n                            files = dir.GetFiles(fn, isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);\r\n                        }\r\n                    }\r\n                    foreach (var item in files)\r\n                    {\r\n                        var metaref = MetadataReference.CreateFromFile(item.FullName);\r\n                        project = project.AddMetadataReference(metaref);\r\n                        metadata.Add(metaref);\r\n                    }\r\n                }\r\n            }\r\n\r\n            \r\n            if (referenceAssemblies != null)\r\n            {\r\n                foreach (var refasm in referenceAssemblies)\r\n                {\r\n                    if (File.Exists(refasm))\r\n                    {\r\n                        project = project.WithParseOptions(new Microsoft.CodeAnalysis.CSharp.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest, DocumentationMode.Parse, SourceCodeKind.Regular, preprocessors));\r\n                        var metaref = MetadataReference.CreateFromFile(refasm);\r\n                        project = project.AddMetadataReference(metaref);\r\n                    }\r\n                }\r\n            }\r\n\r\n            var comp = await project.GetCompilationAsync().ConfigureAwait(false);\r\n            return (comp, metadata);\r\n        }\r\n\r\n        private async Task DownloadDocumentsAsync(string uri, AdhocWorkspace ws, ProjectId projectId, Regex[] filters)\r\n        {\r\n            var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate };\r\n            var client = new HttpClient(handler);\r\n            HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, uri);\r\n            msg.Headers.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue(\"DotNetOMDGenerator\", \"1.0\"));\r\n            Console.WriteLine(\"Downloading \" + uri + \"...\");\r\n            using (var result = await client.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead))\r\n            {\r\n                var content = result.EnsureSuccessStatusCode().Content;\r\n                using (var s = await content.ReadAsStreamAsync())\r\n                {\r\n                    var headers = result.Headers.ToArray();\r\n                    var filename = Path.GetTempFileName();\r\n                    var name = content.Headers.ContentDisposition?.FileName;\r\n                    if (content.Headers.ContentType?.MediaType == \"application/zip\")\r\n                    {\r\n                        var length = content.Headers.ContentLength;\r\n                        using (var f = System.IO.File.OpenWrite(filename))\r\n                        {\r\n                            var buffer = new byte[65536];\r\n                            long read = 0;\r\n                            int count = -1;\r\n                            while (count != 0)\r\n                            {\r\n                                count = await s.ReadAsync(buffer, 0, buffer.Length);\r\n                                if (count > 0)\r\n                                    await f.WriteAsync(buffer, 0, count);\r\n                                read += count;\r\n                                if (length.HasValue)\r\n                                    Console.Write($\"         \\r{(read * 100.0 / length.Value).ToString(\"0.0\")}%  ({(length.Value / 1024d / 1024d).ToString(\"0.0\")}mb)\");\r\n                                else\r\n                                    Console.Write($\"         \\r{read} bytes...\");\r\n                            }\r\n                            Console.WriteLine();\r\n                        }\r\n                        LoadCompressedDocuments(filename, ws, projectId, filters);\r\n                        File.Delete(filename);\r\n                    }\r\n                    else if (content.Headers.ContentType?.MediaType == \"text/plain\")\r\n                    {\r\n                        var sourceText = SourceText.From(s);\r\n                        ws.AddDocument(projectId, name ?? \"Unknown.cs\", sourceText);\r\n                    }\r\n                    else\r\n                        throw new Exception(\"Invalid or missing content type: \" + content.Headers.ContentType?.MediaType);\r\n                }\r\n            }\r\n        }\r\n\r\n        private void LoadCompressedDocuments(string zipFile, AdhocWorkspace ws, ProjectId projectId, Regex[] filters)\r\n        {\r\n            using (var s = File.OpenRead(zipFile))\r\n            {\r\n                System.IO.Compression.ZipArchive a = new System.IO.Compression.ZipArchive(s, System.IO.Compression.ZipArchiveMode.Read);\r\n                foreach (var e in a.Entries)\r\n                {\r\n                    if (string.IsNullOrEmpty(e.Name)) //Folder\r\n                        continue;\r\n                    var fullname = e.FullName.Replace('\\\\', '/');\r\n                    if (filters == null || !filters.Where(f => f.IsMatch(fullname)).Any())\r\n                    {\r\n                        if (e.Name.EndsWith(\".cs\"))\r\n                        {\r\n                            using (var sr = new StreamReader(e.Open()))\r\n                            {\r\n                                var sourceText = SourceText.From(sr.ReadToEnd());\r\n                                ws.AddDocument(projectId, e.Name, sourceText);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        private void LoadFolderDocuments(string pathName, AdhocWorkspace ws, ProjectId projectId, Regex[] filters)\r\n        {\r\n            FileInfo f = new FileInfo(pathName);\r\n            DirectoryInfo di = null;\r\n            IEnumerable<FileInfo> files;\r\n            if (f.Exists)\r\n            {\r\n                files = new FileInfo[] { f };\r\n            }\r\n            else\r\n            {\r\n                di = new DirectoryInfo(pathName);\r\n                files = di.GetFiles(\"*.cs\");\r\n                if (filters != null)\r\n                    files = files.Where(n => !filters.Where(fl => fl.IsMatch(n.FullName.Replace('\\\\', '/'))).Any());\r\n            }\r\n            foreach (var file in files)\r\n            {\r\n                var sourceText = SourceText.From(File.OpenRead(file.FullName));\r\n                ws.AddDocument(projectId, file.Name, sourceText);\r\n            }\r\n            if (di != null)\r\n            {\r\n                foreach (var dir in di.GetDirectories())\r\n                {\r\n                    LoadFolderDocuments(dir.FullName, ws, projectId, filters);\r\n                }\r\n            }\r\n        }\r\n\r\n        //************* Difference comparisons *******************/\r\n\r\n        internal async Task ProcessDiffs(string[] oldPaths, string[] newPaths, IEnumerable<string> oldAssemblies, IEnumerable<string> newAssemblies, IEnumerable<string> preprocessors = null, Regex[] filters = null, string[] referenceAssemblies = null, string[] objectFilters = null)\r\n        {\r\n            var oldCompilation = await CreateCompilationAsync(oldPaths, oldAssemblies, preprocessors, filters, referenceAssemblies);\r\n            var newCompilation = await CreateCompilationAsync(newPaths, newAssemblies, preprocessors, filters, referenceAssemblies);\r\n            var oldSymbols = GetSymbols(oldCompilation.compilation, oldCompilation.metadata);\r\n            var newSymbols = GetSymbols(newCompilation.compilation, newCompilation.metadata);\r\n            var symbols = GetChangedSymbols(newSymbols, oldSymbols);\r\n            int i = 0;\r\n            foreach (var generator in generators.OfType<ICodeDiffGenerator>())\r\n            {\r\n                generator.Initialize(newSymbols, oldSymbols);\r\n                i = 0;\r\n                foreach (var s in symbols)\r\n                {\r\n                    if (objectFilters is not null && objectFilters.Any(o => s.oldSymbol != null && s.oldSymbol.ToDisplayString().StartsWith(o) || s.newSymbol != null && s.newSymbol.ToDisplayString().StartsWith(o)))\r\n                        continue;\r\n                    GenerateCode(generator, s.newSymbol, s.oldSymbol);\r\n                    i++;\r\n                }\r\n                generator.Complete();\r\n            }\r\n            Console.WriteLine($\"Complete. {i} symbols with changes found\");\r\n        }\r\n\r\n        internal static IEnumerable<(INamedTypeSymbol newSymbol, INamedTypeSymbol oldSymbol)> GetChangedSymbols(IEnumerable<INamedTypeSymbol> newSymbols, IEnumerable<INamedTypeSymbol> oldSymbols)\r\n        {\r\n            var symbolNameComparer = new SymbolNameComparer();\r\n            var removedSymbols = oldSymbols.Except(newSymbols, symbolNameComparer).ToList(); //Objects that have been removed\r\n            var addedSymbols = newSymbols.Except(oldSymbols, symbolNameComparer).ToList(); //Objects that have been added\r\n            var sameNewSymbols = newSymbols.Intersect(oldSymbols, symbolNameComparer).ToList(); // Objects present before and after\r\n            var sameOldSymbols = oldSymbols.Intersect(newSymbols, symbolNameComparer).ToList(); // Objects present before and after\r\n            var changedSymbols = sameNewSymbols.Except(sameOldSymbols, new SymbolMemberComparer())\r\n                .Union(sameNewSymbols.Where(n=>n.IsObsolete() && !sameOldSymbols.Single(o=>symbolNameComparer.Equals(n, o)).IsObsolete()))\r\n                .ToList(); //Objects that have changes\r\n            List<(INamedTypeSymbol newSymbol, INamedTypeSymbol oldSymbol)> symbols = new List<(INamedTypeSymbol newSymbol, INamedTypeSymbol oldSymbol)>();\r\n            foreach (var s in addedSymbols)\r\n                symbols.Add((s, null));\r\n            foreach (var s in removedSymbols)\r\n                symbols.Add((null, s));\r\n            foreach (var s in changedSymbols)\r\n            {\r\n                var name = s.GetFullTypeName();\r\n                var oldS = oldSymbols.Where(o => o.GetFullTypeName() == name).First();\r\n                symbols.Add((s, oldS));\r\n            }\r\n            return symbols.OrderBy(s => (s.Item1 ?? s.Item2).Name).OrderBy(s => (s.Item1 ?? s.Item2).GetFullNamespace()).ToList();\r\n        }\r\n        private void GenerateCode(ICodeDiffGenerator generator, INamedTypeSymbol type, INamedTypeSymbol oldType)\r\n        {\r\n            if (type == null && oldType == null)\r\n                throw new ArgumentNullException(\"Both old and new type can't be null\");\r\n            var t = (type ?? oldType);\r\n            Console.WriteLine(t.GetFullTypeName());\r\n            if (t.TypeKind == TypeKind.Enum)\r\n                generator.WriteEnum(type, oldType);\r\n            else if (t.TypeKind == TypeKind.Interface)\r\n                generator.WriteInterface(type, oldType);\r\n            else if (t.TypeKind == TypeKind.Class || t.TypeKind == TypeKind.Struct)\r\n                generator.WriteClass(type, oldType);\r\n            else if (t.TypeKind == TypeKind.Delegate)\r\n                generator.WriteDelegate(type, oldType);\r\n            else\r\n            {\r\n                Console.WriteLine(\"****TODO**** ERROR: No generator for type \" + t.GetFullTypeName() + \" of kind \" + t.TypeKind.ToString());\r\n            }\r\n        }\r\n        internal class SymbolNameComparer : IEqualityComparer<INamedTypeSymbol>\r\n        {\r\n            internal static SymbolNameComparer Comparer = new SymbolNameComparer();\r\n            public bool Equals(INamedTypeSymbol x, INamedTypeSymbol y) => x.ToDisplayString().Equals(y.ToDisplayString());\r\n            public int GetHashCode(INamedTypeSymbol obj) => obj.ToDisplayString().GetHashCode();\r\n        }\r\n\r\n        private class SymbolMemberComparer : IEqualityComparer<INamedTypeSymbol>\r\n        {\r\n            public bool Equals(INamedTypeSymbol x, INamedTypeSymbol y)\r\n            {\r\n                //TODO: Also check base types. It's ok to move members up the hiarchy\r\n                if (x.BaseType?.ToDisplayString() != y.BaseType?.ToDisplayString())\r\n                    return false; // Inheritance changed\r\n\r\n                if (x.TypeKind != y.TypeKind) return false;\r\n\r\n                var ifacesNew = x.GetInterfaces();\r\n                var ifacesOld = y.GetInterfaces();\r\n                if (ifacesNew.Count() != ifacesOld.Count()) return false;\r\n\r\n                if (x.TypeKind == TypeKind.Enum && x.EnumUnderlyingType?.ToDisplayString() != y.EnumUnderlyingType?.ToDisplayString())\r\n                    return false; //Enum type changed\r\n\r\n                // Compare member count\r\n                var constructorsNew = x.GetConstructors();\r\n                var constructorsOld = y.GetConstructors();\r\n                if (constructorsNew.Count() != constructorsOld.Count()) return false;\r\n\r\n                var propsNew = x.GetProperties();\r\n                var propsOld = y.GetProperties();\r\n                if (propsNew.Count() != propsOld.Count()) return false;\r\n\r\n                var methodsNew = x.GetMethods();\r\n                var methodsOld = y.GetMethods();\r\n                if (methodsNew.Count() != methodsOld.Count()) return false;\r\n\r\n                var eventsNew = x.GetEvents();\r\n                var eventsOld = y.GetEvents();\r\n                if (eventsNew.Count() != eventsOld.Count()) return false;\r\n\r\n                var fieldsNew = x.GetEnums();\r\n                var fieldsOld = y.GetEnums();\r\n                if (fieldsNew.Count() != fieldsOld.Count()) return false;\r\n\r\n                if (ifacesNew.Except(ifacesOld, SymbolNameComparer.Comparer).Any() ||\r\n                    ifacesOld.Except(ifacesNew, SymbolNameComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (propsNew.Except(propsOld, PropertyComparer.Comparer).Any() ||\r\n                   propsOld.Except(propsNew, PropertyComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (constructorsNew.Except(constructorsOld, MethodComparer.Comparer).Any() ||\r\n                   constructorsOld.Except(constructorsNew, MethodComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (propsNew.Except(propsOld, PropertyComparer.Comparer).Any() ||\r\n                   propsOld.Except(propsNew, PropertyComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (methodsNew.Except(methodsOld, MethodComparer.Comparer).Any() ||\r\n                   methodsOld.Except(methodsNew, MethodComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (eventsNew.Except(eventsOld, EventComparer.Comparer).Any() ||\r\n                   eventsOld.Except(eventsNew, EventComparer.Comparer).Any())\r\n                    return false;\r\n\r\n                if (fieldsNew.Except(fieldsOld, FieldComparer.Comparer).Any() ||\r\n                   fieldsOld.Except(fieldsNew, FieldComparer.Comparer).Any())\r\n                    return false;\r\n                return true;\r\n            }\r\n            public int GetHashCode(INamedTypeSymbol obj) => obj.GetFullTypeName().GetHashCode();\r\n        }\r\n\r\n        internal static class Constants\r\n        {\r\n            public static readonly SymbolDisplayFormat AllFormat = new SymbolDisplayFormat(\r\n                SymbolDisplayGlobalNamespaceStyle.Included,\r\n                SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,\r\n                (SymbolDisplayGenericsOptions)255,\r\n                (SymbolDisplayMemberOptions)255,\r\n                (SymbolDisplayDelegateStyle)255, (SymbolDisplayExtensionMethodStyle)255,\r\n                (SymbolDisplayParameterOptions)255, SymbolDisplayPropertyStyle.NameOnly,\r\n                (SymbolDisplayLocalOptions)255, (SymbolDisplayKindOptions)255, (SymbolDisplayMiscellaneousOptions)255);\r\n            public static readonly SymbolDisplayFormat AllFormatWithoutContaining = new SymbolDisplayFormat(\r\n                SymbolDisplayGlobalNamespaceStyle.Omitted,\r\n                SymbolDisplayTypeQualificationStyle.NameOnly,\r\n                (SymbolDisplayGenericsOptions)255,\r\n                (SymbolDisplayMemberOptions)223,\r\n                (SymbolDisplayDelegateStyle)255, (SymbolDisplayExtensionMethodStyle)255,\r\n                (SymbolDisplayParameterOptions)255, SymbolDisplayPropertyStyle.NameOnly,\r\n                (SymbolDisplayLocalOptions)255, (SymbolDisplayKindOptions)255, (SymbolDisplayMiscellaneousOptions)255);\r\n        }\r\n        internal class PropertyComparer : IEqualityComparer<IPropertySymbol>\r\n        {\r\n            internal static PropertyComparer Comparer = new PropertyComparer();\r\n            public bool Equals(IPropertySymbol x, IPropertySymbol y)\r\n            {\r\n                if (!x.ToDisplayString(Constants.AllFormat).Equals(y.ToDisplayString(Constants.AllFormat)))\r\n                    return false;\r\n                IMethodSymbol gx = (x.GetMethod?.DeclaredAccessibility == Accessibility.Public ||\r\n                    (x.GetMethod?.DeclaredAccessibility == Accessibility.Internal && GeneratorSettings.ShowInternalMembers) ||\r\n                    (x.GetMethod?.DeclaredAccessibility == Accessibility.Private && GeneratorSettings.ShowPrivateMembers)) ? x.GetMethod : null;\r\n                IMethodSymbol gy = (y.GetMethod?.DeclaredAccessibility == Accessibility.Public ||\r\n                    (y.GetMethod?.DeclaredAccessibility == Accessibility.Internal && GeneratorSettings.ShowInternalMembers) ||\r\n                    (y.GetMethod?.DeclaredAccessibility == Accessibility.Private && GeneratorSettings.ShowPrivateMembers)) ? y.GetMethod : null;\r\n                if (gx?.DeclaredAccessibility != gy?.DeclaredAccessibility)\r\n                    return false;\r\n                IMethodSymbol sx = (x.SetMethod?.DeclaredAccessibility == Accessibility.Public ||\r\n                    (x.SetMethod?.DeclaredAccessibility == Accessibility.Internal && GeneratorSettings.ShowInternalMembers) ||\r\n                    (x.SetMethod?.DeclaredAccessibility == Accessibility.Private && GeneratorSettings.ShowPrivateMembers)) ? x.SetMethod : null;\r\n                IMethodSymbol sy = (y.SetMethod?.DeclaredAccessibility == Accessibility.Public ||\r\n                    (y.SetMethod?.DeclaredAccessibility == Accessibility.Internal && GeneratorSettings.ShowInternalMembers) ||\r\n                    (y.SetMethod?.DeclaredAccessibility == Accessibility.Private && GeneratorSettings.ShowPrivateMembers)) ? y.SetMethod : null;\r\n                if (sx?.DeclaredAccessibility != sy?.DeclaredAccessibility)\r\n                    return false;\r\n                return true;\r\n            }\r\n            public int GetHashCode(IPropertySymbol obj) => obj.ToDisplayString(Constants.AllFormat).GetHashCode();\r\n        }\r\n\r\n        internal class MethodComparer : IEqualityComparer<IMethodSymbol>\r\n        {\r\n            public static MethodComparer Comparer = new MethodComparer();\r\n            public bool Equals(IMethodSymbol x, IMethodSymbol y) => x.ToDisplayString(Constants.AllFormat).Equals(y.ToDisplayString(Constants.AllFormat));\r\n            public int GetHashCode(IMethodSymbol obj) => obj.ToDisplayString(Constants.AllFormat).GetHashCode();\r\n        }\r\n\r\n        internal class EventComparer : IEqualityComparer<IEventSymbol>\r\n        {\r\n            public static EventComparer Comparer = new EventComparer();\r\n            public bool Equals(IEventSymbol x, IEventSymbol y) => x.ToDisplayString(Constants.AllFormat).Equals(y.ToDisplayString(Constants.AllFormat));\r\n            public int GetHashCode(IEventSymbol obj) => obj.ToDisplayString(Constants.AllFormat).GetHashCode();\r\n        }\r\n\r\n        internal class FieldComparer : IEqualityComparer<IFieldSymbol>\r\n        {\r\n            public static FieldComparer Comparer = new FieldComparer();\r\n            public bool Equals(IFieldSymbol x, IFieldSymbol y) => FormatField(x).Equals(FormatField(y));\r\n            public int GetHashCode(IFieldSymbol obj) => obj.ToDisplayString(Constants.AllFormat).GetHashCode();\r\n            private static string FormatField(IFieldSymbol x)\r\n            {\r\n                return x.ToDisplayString(Constants.AllFormat) + \"=\" + x.ConstantValue?.ToString();\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "src/Generator/dotMorten.OmdGenerator.targets",
    "content": "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\n  <PropertyGroup>\n    <DotNetOMDGeneratorToolPath>$(MSBuildThisFileDirectory)..\\tools\\netcoreapp2.1\\any\\generateomd.dll</DotNetOMDGeneratorToolPath>\n  </PropertyGroup>\n  <Target Name=\"GenerateObjectModel\" AfterTargets=\"Compile\">\n    <PropertyGroup>\n      <OMDOutputFormat Condition=\"'$(OMDOutputFormat)'==''\">html</OMDOutputFormat>\n    </PropertyGroup>\n    <Exec Command=\"dotnet &quot;$(DotNetOMDGeneratorToolPath)&quot; /source=&quot;@(Compile)&quot; /preprocessors=&quot;$(DefineConstants)&quot; /output=&quot;$(OutputPath)$(TargetName).html&quot; /format=$(OMDOutputFormat)\" WorkingDirectory=\"$(ProjectDir)\" />\n  </Target>\n\n</Project> "
  },
  {
    "path": "src/Generator.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.27130.2027\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Generator\", \"Generator\\Generator.csproj\", \"{AD341C4A-21E0-4268-B573-5C37A727BC23}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{5BC4D75B-15DF-4FA8-9981-2021ACED5AFD}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t..\\README.md = ..\\README.md\r\n\tEndProjectSection\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{AD341C4A-21E0-4268-B573-5C37A727BC23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{AD341C4A-21E0-4268-B573-5C37A727BC23}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{AD341C4A-21E0-4268-B573-5C37A727BC23}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{AD341C4A-21E0-4268-B573-5C37A727BC23}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {1449C758-CD7D-4A6A-AA3D-B7F9B0A4764E}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  }
]