[
  {
    "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# 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\nbuild/\r\nbld/\r\n[Bb]in/\r\n[Oo]bj/\r\n\r\n# Visual Studo 2015 cache/options directory\r\n.vs/\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*_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*.opensdf\r\n*.sdf\r\n*.cachefile\r\n\r\n# Visual Studio profiler\r\n*.psess\r\n*.vsp\r\n*.vspx\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 addin-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# NCrunch\r\n_NCrunch_*\r\n.*crunch*.local.xml\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# 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\r\n# Windows Azure Build Output\r\ncsx/\r\n*.build.csdef\r\n\r\n# Windows Store app package directory\r\nAppPackages/\r\n\r\n# Others\r\n*.[Cc]ache\r\nClientBin/\r\n[Ss]tyle[Cc]op.*\r\n~$*\r\n*~\r\n*.dbmdl\r\n*.dbproj.schemaview\r\n*.pfx\r\n*.publishsettings\r\nnode_modules/\r\nbower_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\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# Node.js Tools for Visual Studio\r\n.ntvs_analysis.dat\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/source/out\r\n\r\n*.local.*\r\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# NsDepCop Change Log\n\n## v2.7.0\n(12/2025)\n\n- [x] Perf: Avoids unnecessary rebuilds when only a solution-level config.nsdepcop file is used (no project-level files).\n\n## v2.6.0\n(04/2025)\n\n- [x] New: Regex patterns for assemblies and namespaces.\n\n## v2.5.0\n(01/2025)\n\n- [x] New: Added assembly dependency checking.\n\n## v2.4.0\n(09/2024)\n\n- [x] New: Analyzing top level statements.\n\n## v2.3.0\n(07/2023)\n\n- [x] Changed: Added the allowed type names to the diagnostic message (if VisibleMembers are specified).\n\n## v2.2.0\n(09/2022)\n\n- [x] New: Wildcard patterns for namespaces.\n\n## v2.1.0\n(07/2022)\n\n- [x] New: ParentCanDependOnChildImplicitly config attribute.\n\n## v2.0.1\n(03/2022)\n\n- [x] Fix: #60 - Statically imported type dependency not detected.\n\n## v2.0.0\n(06/2021)\n\nThe big change in this version is that the implementation changed from MSBuild task + Visual Studio Extension to a standard Roslyn analyzer.\n\n  - [x] NsDepCop must be added to a project as a NuGet package.\n  - [x] Appears in Solution Explorer: project / Dependencies / Analyzers / NsDepCop.Analyzer\n  - [x] Issue severities can be configured that same way as other analyzers (use Visual Studio or .editorconfig files).\n  - [x] Works both at build time and inside Visual Studio editor.\n  - [x] Requires Visual Studio 2019 (16.10.0 or later).\n  - [x] Supports .NET Core / .NET 5 / etc. projects too.\n  - [x] Uses Roslyn 3.9.0.\n\nStuff that was removed:\n  - [x] No need for the NsDepCop Visual Studio Extension any more.\n  - [x] No need for the out-of-process service host any more.\n  - [x] Dropped support for VS 2015/2017. For those, use NsDepCop v1.11.0.\n  - [x] Config attributes no longer supported (ignored): CodeIssueKind, MaxIssueCountSeverity, InfoImportance, AnalyzerServiceCallRetryTimeSpans. \n\nOther info:\n  - [x] AutoLowerMaxIssueCount feature is temporarily not supported.\n\n## v1.11.0\n(04/2020)\n\n- [x] New: Disable/force NsDepCop with MSBuild property. \n\n## v1.10.1\n(02/2020)\n\n- [x] Fix: #51 - RemotingException when using different NsDepCop NuGet and VSIX version.\n\n## v1.10.0\n(04/2019)\n\n- [x] New: Support Visual Studio 2019\n\n## v1.9.0\n(03/2019)\n\n- [x] New: Support incremental build - don't run the tool if there was no change in the source/config files.\n- [x] New: Global turn off switch - DisableNsDepCop environment variable.\n- [x] New: Excluding files from analysis - ExcludedFiles attribute in config.nsdepcop.\n\n## v1.8.2\n(01/2019)\n\n- [x] Fix: #43 (for real this time) - RemotingException when path contains space.\n\n## v1.8.1\n(12/2018)\n\n- [x] Fix: #43 - RemotingException when path contains space.\n\n## v1.8.0\n(07/2018)\n\n- [x] Enhancements in launching the out-of-process service host (configurable retry intervals, allow access for any user).\n- [x] MaxIssueCountSeverity - enables breaking the build when a threshold number of dependency violations has been reached.\n- [x] AutoLowerMaxIssueCount - automatically lower MaxIssueCount to encourage cleaning up dependency problems and prohibit introducing new ones.\n- [x] Supports C# up to 7.3.\n- [x] The Visual Studio Extension (VSIX) requires 15.7.4 or higher.\n\n## v1.7.1\n(07/2017)\n\n- [x] Performance enhancement when run by MSBuild. \n  - [x] The analyzer keeps running in its own process to avoid repeated creation cost. Shuts down with parent process.\n\n## v1.7.0\n(07/2017)\n\n- [x] New: C# 7 support.\n- [x] New: Visual Studio 2017 support.\n- [x] Removed: MSI installer.\n  - [x] Config XML schema support is now available as a Visual Studio Extension (only for VS2017).\n  - [x] Global MSBuild-integration is discontinued. Please use per-project MSBuild integration via the NuGet package.\n\n## v1.6.1\n(04/2017)\n\n- [x] Fix: Type without a name caused exception in analyzer.\n\n## v1.6.0\n(03/2017)\n\n- [x] New: NuGet package.\n  - [x] Enables per-project MSBuild integration.\n  - [x] Enables zero install on build machine.\n- [x] New: Multi-level config file.\n  - [x] Use the InheritanceDepth config attribute to specify the number of parent folder levels to merge config files from.\n  - [x] Use it to get rid of redundant rules and settings in nsdepcop.config files and move them to a common place, eg. to solution level or repo root level.\n- [x] Changed: MSI installer modified.\n  - [x] Option (default on): config.nsdepcop XML schema support updated.\n  - [x] Option (default off): Machine-wide MSBuild integration. Not recommended any more, use the NuGet (per-project) distribution instead.\n  - [x] Removed option: Visual Studio 2015 integration. Use the VSIX package directly instead.\n- [x] Fixed: \n  - [x] Types in enum and delegate declarations were not analyzed.\n  - [x] Constructed generic, array and pointer types are now analyzed recursively.\n  - [x] Source and metadata file load errors are now handled gracefully.\n- [x] Changed: Roslyn version updated to 1.3.2.\n- [x] Changed: Removed NRefactory as a parser choice.\n\n### Upgrading\n\n* To upgrade please uninstall the previous version first. \n  * Your existing config.nsdepcop files will be preserved.\n* Then install the new version. \n  * Recommended: change to per-project MSBuild integration with NuGet. See [README.md](README.md) for details.\n  * Please note that if you don't uninstall the previous version then its machine-wide MSBuild integration will override the per-project integration provided by the NuGet package and the old analyzer version will run at build time.\n\n## v1.5\n(06/2016)\n\n- [x] Supports Visual Studio 2015 only.\n- [x] New: Use the VisibleMembers element to fine-tune the allowed dependencies at the type level.\n- [x] New: Added config.nsdepcop XML schema support to Visual Studio so it can validate config syntax and provide IntelliSense.\n- [x] Fixed: adding an nsdepcop.config file to a project now works for all C# projects (incl. portable lib).\n- [x] Changed: Roslyn version updated to 1.2.2.\n\n## v1.4\n(08/2015)\n\n- [x] Supports Visual Studio 2015 only.\n- [x] New: Info messages' level can be configured to suppress/enable them in the MSBuild output.\n- [x] New: ChildCanDependOnParentImplicitly config attribute.\n- [x] Fixed:\n  - [x] MSBuild return code was success even if an error was detected.\n  - [x] Extension method declaring type was not checked.\n- [x] Changed: Roslyn version updated to 1.0.\n- [x] Icons (tadaaa! :)\n\n## v1.3\n(01/2015)\n\n- [x] Supports Visual Studio 2013 only.\n- [x] New: Disallowed rules.\n\n## v1.2\n(08/2014)\n\n- [x] Supports Visual Studio 2013 only.\n- [x] Requires the Roslyn End User Preview of April 2014.\n\n## v1.1\n(07/2013)\n\n- [x] Supports Visual Studio 2012 only.\n- [x] Requires Roslyn September 2012 CTP. \n- [x] New: Added NRefactory as the default parser for the MSBuild task.\n\n## v1.0\n(03/2013)\n\n- [x] Supports Visual Studio 2012 only.\n- [x] Requires Roslyn September 2012 CTP. "
  },
  {
    "path": "CLAUDE.md",
    "content": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nNsDepCop is a Roslyn-based static analysis tool for C# that enforces namespace and assembly dependency rules. It ships as a NuGet package that integrates into the build process, reporting violations as compiler warnings/errors.\n\n## Build and Test Commands\n\nSolution-level `dotnet build/test` fails due to a self-referencing NuGet cycle (`NsDepCop.Analyzer` depends on the `NsDepCop` NuGet package, which is produced by `NsDepCop.NuGet` in the same solution). CI avoids this with standalone `nuget.exe restore` + Framework `msbuild`; VS IDE handles it internally. From the command line, target individual projects:\n\n```bash\n# Build the analyzer (restores and builds dependencies automatically)\ndotnet build source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj\n\n# Run unit tests\ndotnet test source/NsDepCop.Test/NsDepCop.Test.csproj\n\n# Run source-based integration tests\ndotnet test source/NsDepCop.SourceTest/NsDepCop.SourceTest.csproj\n\n# Run a single test by name\ndotnet test source/NsDepCop.Test/NsDepCop.Test.csproj --filter \"FullyQualifiedName~TestMethodName\"\n```\n\n**Prerequisites:** Visual Studio 2022 with **Visual Studio extension development** workload (includes the .NET SDK).\n\n## Solution Structure\n\nAll source code lives under `source/`. The solution is `source/NsDepCop.sln`.\n\n| Project | Target | Purpose |\n|---|---|---|\n| `NsDepCop.Analyzer` | netstandard2.0 | Core analyzer — the main product code |\n| `NsDepCop.Test` | net8.0 | Unit tests (xUnit, FluentAssertions, Moq) |\n| `NsDepCop.SourceTest` | net8.0 | Integration tests — verifies analyzer against C# source files |\n| `NsDepCop.NuGet` | netstandard2.0 | NuGet package packaging |\n| `NsDepCop.Benchmarks` | — | Performance benchmarks |\n| `NsDepCop.Vsix` | — | Visual Studio Extension wrapper |\n\n## Architecture\n\n### Analyzer Core (`NsDepCop.Analyzer`)\n\nRoot namespace: `Codartis.NsDepCop`. Internal module dependencies are enforced by `config.nsdepcop` in the project itself.\n\n- **RoslynAnalyzer/** — Entry point. `NsDepCopAnalyzer` extends Roslyn `DiagnosticAnalyzer`, registered for `IdentifierName`, `GenericName`, and `DefaultLiteralExpression` syntax kinds. Wires together config and analysis. Must only depend on other modules via interfaces (not `.Implementation` namespaces).\n- **Config/** — XML config file parsing and rule model. `DependencyRule`, `Domain`, `WildcardDomain`, `RegexDomain` represent rules. `MultiLevelXmlFileConfigProvider` handles config inheritance (project → parent directories). Factory pattern separates creation from implementation.\n- **Analysis/** — Dependency validation logic. `DependencyAnalyzer` orchestrates type-level and assembly-level validation. `TypeDependencyValidator` checks namespace rules; `AssemblyDependencyValidator` checks assembly rules.\n- **ParserAdapter/Roslyn/** — Extracts type dependencies from Roslyn syntax trees.\n- **Util/** — Shared helpers.\n\n### Dependency flow between modules\n\n```\nRoslynAnalyzer → Config (interfaces only), Analysis (interfaces only), ParserAdapter\nParserAdapter  → Analysis\nAnalysis       → Config\nConfig.Factory → Config.Implementation\n```\n\nThe `RoslynAnalyzer` layer is explicitly **disallowed** from depending on `*.Implementation` namespaces.\n\n### Test Structure\n\n**Unit tests** (`NsDepCop.Test`): Standard xUnit tests for config parsing, validation logic, and analyzer behavior. Test data files (`.nsdepcop` configs) are in subdirectories named after their test class, copied to output via `CopyToOutputDirectory`.\n\n**Source tests** (`NsDepCop.SourceTest`): Each test case is a folder containing a `.cs` source file and a `config.nsdepcop` file. The `.cs` files are excluded from compilation (`<Compile Remove>`) and instead copied to output as test data. Tests verify the analyzer produces expected diagnostics for various C# syntax patterns (C# 6, 7, 7.1, 7.2, 7.3, top-level statements).\n\n### Self-referencing / Dogfooding\n\nThe project references its own NuGet package (`NsDepCop 2.7.0`) and enforces dependency rules on its own code. `Directory.Build.targets` contains a workaround (`AvoidCycleErrorOnSelfReference`) that renames `PackageId` to `NsDepCop_temp` during build to break the cycle, restoring it before pack. This workaround is broken with current .NET SDK versions — `dotnet restore` and `msbuild /t:Restore` still detect the cycle. Only standalone `nuget.exe restore` (used by CI) and VS IDE's internal restore avoid the error. This is why command-line builds must target individual projects rather than the solution.\n\n## Key Conventions\n\n- `TreatWarningsAsErrors` is enabled on all projects\n- Root namespace is `Codartis.NsDepCop` (with project-specific suffixes like `.Test`)\n- `config.nsdepcop` is the XML configuration file format — both the product config and test fixtures\n- CI runs on AppVeyor (Visual Studio 2022 image), Release configuration\n- Version is managed in `appveyor.yml` and patched into `source/Include/VersionInfo.cs`\n\n## Diagnostics\n\nDiagnostic IDs: `NSDEPCOP01` (illegal namespace dependency), `NSDEPCOP02` (too many issues), `NSDEPCOP03` (no config), `NSDEPCOP04` (config disabled), `NSDEPCOP05` (config error), `NSDEPCOP06` (tool disabled), `NSDEPCOP07` (illegal assembly dependency). Definitions are in `DiagnosticDefinitions.cs`.\n"
  },
  {
    "path": "Contribute.md",
    "content": "## How to build the source\n1. Prerequisites\n   * Visual Studio 2019 or later (16.10.0 or later, any edition)\n     * With workload: **Visual Studio extension development**\n1. [Download or clone the source](https://github.com/realvizu/NsDepCop)\n1. Open \"source\\NsDepCop.sln\"\n1. Build the solution.\n\n## How to debug the tool in Visual Studio\n1. Set **NsDepCop.Vsix** as the StartUp project.\n1. In the project file modify the **StartArguments** tag to point to a valid solution file and log path.\n1. Run the solution."
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {description}\n    Copyright (C) {year}  {fullname}\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  {signature of Ty Coon}, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n\n"
  },
  {
    "path": "README.md",
    "content": "# NsDepCop - Namespace and Assembly Dependency Checker Tool for C# #\n\nNsDepCop is a static code analysis tool that enforces namespace and assembly dependency rules in C# projects.\n* It runs as part of the build process and reports any dependency problems.\n* No more unplanned or unnoticed dependencies in your system.\n\nWhat is this [**dependency control**](doc/DependencyControl.md) anyway? And [**why should you automate it**](https://www.plainionist.net/Dependency-Governance-DotNet/)?\n\n## Getting Started\n\n1. Add the [**NsDepCop NuGet package**](https://nuget.org/packages/NsDepCop) to your C# projects: [![NuGet Package](https://img.shields.io/nuget/v/NsDepCop.svg)](https://nuget.org/packages/NsDepCop)\n1. Add a text file named **'config.nsdepcop'** to your project, then edit it to define your [**dependency rules**](doc/Help.md#dependency-rules). \n1. Dependency violations will be underlined in the code editor and reported at build time just like compiler errors/warnings.\n\nSee the [**Help**](doc/Help.md) for details.\n\nOr check out this step-by-step [**tutorial video**](https://www.youtube.com/watch?v=rkU7Hx20Dc0) by [plainionist](https://github.com/plainionist).\n\n## Versions\n* See the [**Change Log**](CHANGELOG.md) for version history.\n\n## Feedback\n* Use the [**Issue Tracker**](https://github.com/realvizu/NsDepCop/issues) to submit bugs and feature requests.\n* Use the [**Discussions forum**](https://github.com/realvizu/NsDepCop/discussions) for questions.\n\n## More Info\n* [Diagnostics Reference](doc/Diagnostics.md)\n* [Configuring XML schema support for config.nsdepcop files](doc/Help.md#config-xml-schema-support-in-visual-studio)\n* [Troubleshooting](doc/Troubleshooting.md)\n* [How to contribute?](Contribute.md)\n\n## Thanks to \n* [Roslyn](https://github.com/dotnet/roslyn) for the amazing parser API.\n* [DotNet.Glob](https://github.com/dazinator/DotNet.Glob) for the globbing library.\n\n## License\n* [GPL-2.0](LICENSE)\n\n## Other Tools\n* Check out my other project: [Codartis Diagram Tool](https://codartis.com/), a code visualization tool for C#.\n"
  },
  {
    "path": "appveyor.yml",
    "content": "image: Visual Studio 2022\n\nenvironment:\n  shortversion: '2.7.0'\n  informationalversion: '2.7.0'\n\nversion: '$(shortversion).{build}'\n\nconfiguration: Release\n\ninstall:\n- ps: (New-Object Net.WebClient).DownloadString(\"https://raw.githubusercontent.com/realvizu/Tools/master/Build/buildtools.ps1\") | Invoke-Expression\n\nassembly_info:\n  patch: true\n  file: source\\include\\VersionInfo.cs\n  assembly_version: '{version}'\n  assembly_file_version: '{version}'\n  assembly_informational_version: '$(informationalversion)'\n\ndotnet_csproj:\n  patch: true\n  file: source\\NsDepCop.NuGet\\NsDepCop.NuGet.csproj\n  package_version: '$(informationalversion)'\n\nbefore_build:\n- cmd: nuget restore -Verbosity quiet source\\NsDepCop.sln\n\nbuild:\n  project: source\\NsDepCop.sln\n  verbosity: minimal\n\ntest:\n  assemblies: '**\\*Test*.dll'\n\nartifacts:\n- path: 'source\\NsDepCop.NuGet\\bin\\$(configuration)\\NsDepCop*.nupkg'"
  },
  {
    "path": "doc/DependencyControl.md",
    "content": "# Dependency Control\n\n## Why Care About Code Dependencies?\nThe number one enemy of a developer is complexity.\n\nAmong the many sources of complexity, lets focus now on the structure of the codebase and its dependencies.\n* To reduce complexity, the primary strategy is to decompose the code into smaller units (e.g., modules) and limit dependencies between them. \n* A codebase with well-defined modules and clear dependency rules is easier to understand, modify, and reuse. \n* However, without a dependency control tool acting as a safeguard, even a well-structured codebase can eventually degrade into a tangled mess.\n\n## How to Control Code Dependencies?\nDependency control tools allow you to define rules for permitted and prohibited dependencies and alert you to any violations.\n\nThese tools can operate at various levels and on different input formats:\n* Physical Level: Projects, libraries, and assemblies.\n* Logical Level: Namespaces and types.\n* Input Formats: Source code, compiled binaries, or intermediary representations.\n\n**This tool performs the following dependency checks:**\n* Namespace dependencies in the C# source code.\n* Assembly dependencies in the C# projects.\n\nIt also supports some fine-tuning at the type level (see details below).\n\n## What Is a Namespace Dependency?\nNamespace **A** depends on Namespace **B** if any type declared in Namespace **A** uses any type declared in Namespace **B**.\n\nIn the example below **Namespace A depends on Namespace B** because type A1 uses types B1, B2, B3, B4 and B5.\n```csharp\nnamespace A\n{\n    using B;\n\n    class A1 : B1\n    {\n        B2 field1;\n        B3 Property1 { get; set; }\n        B4 MyMethod(B5 p) { ... }\n    }\n}\nnamespace B\n{\n    interface B1 {}\n    class B2 {}\n    struct B3 {}\n    enum B4 {}\n    delegate void B5();\n}\n```\n\nNote that a \"using B\" directive *does not automatically imply* a dependency from A to B. If no members of Namespace B are actually used in class A1, then no real dependency exists. Modern code editors can warn about unnecessary using directives. This tool only considers actual code dependencies.\n\n## Recommended approach\n* **Define** the high-level structure of your system as a hierarchy of logical modules or packages. \n  * It's better to do this upfront to avoid extensive refactoring later. \n  * This tool won't assist with the initial design; use a modeling tool or even pen and paper for this step.\n* **Implement** these logical modules/packages using C# namespaces.\n  * Ensure a one-to-one correspondence between logical units and namespaces.\n* [**Describe**](Help.md#dependency-rules) allowed namespace dependencies in config.nsdepcop files.\n  * Use one config file per C# project. \n  * Common dependency rules can be placed in a [\"master\" config file](Help.md#config-inheritance).\n* **Fix** illegal dependencies reported by the tool. \n  * This may require rethinking or redesigning parts of your architecture.\n  * Avoid circular dependencies.\n\n## Why Namespace Dependencies Instead of Type Dependencies?\nEnforcing dependency rules at the type level can lead to verbose and fragile dependency descriptions.\n\nNamespaces provide a useful level of abstraction above types and offer a hierarchical structure that simplifies dependency rules. This allows dependencies to be specified not just between individual logical packages but also between groups or subgroups of packages.\n\n## Why Does This Tool Support Some Type-Level Dependency Control?\nIn cases where you are working with third-party or legacy code whose structure you cannot control, but still want to limit dependencies, this tool allows you to specify a subset of types within a namespace as the visible \"surface\" of that namespace. All other types in that namespace are then illegal to depend upon.\n"
  },
  {
    "path": "doc/Diagnostics.md",
    "content": "# NsDepCop Diagnostics Reference\n\n### NSDEPCOP01\n\nTitle|Illegal namespace reference.\n:-|:-\nDefault Severity|Warning\nExplanation|The designated type cannot reference the other type because their namespaces cannot depend on each other according to the current rules.\nTo Do|Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this namespace dependency.\n\n### NSDEPCOP02\n\nTitle|Too many dependency issues, analysis was stopped.\n:-|:-\nDefault Severity|Warning\nExplanation|The number of dependency issues in this compilation has exceeded the configured maximum value.\nTo Do|Correct the reported issues and run the build again or set the MaxIssueCount attribute in your 'config.nsdepcop' file to a higher number.\n\n### NSDEPCOP03\n\nTitle|No config file found, analysis skipped.\n:-|:-\nDefault Severity|Info\nExplanation|This analyzer requires that you add a file called 'config.nsdepcop' to your project with build action 'C# analyzer additional file'.\nTo Do|None, this is just an informational message.\n\n### NSDEPCOP04\n\nTitle|Analysis is disabled in the config file.\n:-|:-\nDefault Severity|Info\nExplanation|The IsEnabled attribute was set to false in this project's 'config.nsdepcop' file, so the analyzer skips this project.\nTo Do|None, this is just an informational message.\n\n### NSDEPCOP05\n\nTitle|Error loading config.\n:-|:-\nDefault Severity|Error\nExplanation|There was an error while loading the 'config.nsdepcop' file, see the message for details. Some common reasons: malformed content, file permission or file locking problem.\nTo Do|Make sure that the file can be read by the user running the build or Visual Studio and make sure that its content is correct.\n\n### NSDEPCOP06\n\nTitle|Analysis is disabled with environment variable.\n:-|:-\nDefault Severity|Info\nExplanation|If the 'DisableNsDepCop' environment variable is set to 'True' or '1' then all analysis is skipped.\nTo Do|None, this is just an informational message.\n\n### NSDEPCOP07\n\nTitle|Illegal assembly reference.\n:-|:-\nDefault Severity|Warning\nExplanation|The designated assembly cannot reference the other assembly because their dependency is prohibited according to the current rules.\nTo Do|Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this assembly dependency."
  },
  {
    "path": "doc/Help.md",
    "content": "# NsDepCop Help\n\n* [Supported project types](#supported-project-types)\n* [Dependency rules](#dependency-rules)\n* [Config inheritance](#config-inheritance)\n* [Dealing with a high number of dependency issues](#dealing-with-a-high-number-of-dependency-issues)\n* [Disabling with an environment variable](#disabling-with-an-environment-variable)\n* [Config XML schema](#config-xml-schema)\n* [Config XML schema support in Visual Studio](#config-xml-schema-support-in-visual-studio)\n* [v1.x only topics](#v1.x-only-topics)\n\n## Supported project types\n\n* Projects with a **csproj** project file are supported.\n* .Net Core and .Net 5+ projects are supported in v2.0 or above.\n* Projects with an **xproj** project file are not supported.\n\n## Dependency rules\n\n* Allowed and disallowed namespace and assembly dependencies are described with dependency rules in config files. \n* The rule config file must be named **config.nsdepcop** and its build action must be set to **C# analyzer additional file** (the NsDepCop NuGet package sets it automatically).\n* The default (and recommended) approach is [**allowlisting**](#allowlisting), that is, if a dependency is not explicitly allowed then it is disallowed. (See also: [denylisting](#denylisting)).\n* The config file can inherit other config files from parent folders, see [**config inheritance**](#config-inheritance).\n* Assembly dependency checking is disabled by default (for backward compatibility reason) and needs to be enabled with **CheckAssemblyDependencies** attribute on the root element. See [Example Two](#example-two).\n* Rules can specify namespaces in the following ways. \n\nNamespace specification type | Example\n-- | --\nExact| System.IO\nWildcard | System.Collections.* <br> MyProduct.?.StorageModel\nRegex | /MyProduct(\\.[\\w]+)*\\.StorageModel[\\w]/\n\n> Notice that Regex patterns must be enclosed in forward slashes ('/').\n\n### Rule notation\n\nNotation | Meaning\n-- | --\n. (a single dot) | The global namespace.\n \\* (a single star) | Any namespace.\n MyNamespace.\\* | MyNamespace and any sub-namespaces.\n MyNamespace.?| All direct sub-namespaces of MyNamespace\n\\*.MyNamespace | Any namespace named MyNamespace\n?.MyNamespace | Any namespace named MyNamespace which has exactly one parent namespace.\nMyNamespace.*.MyOtherNamespace| Any namespace called MyOtherNamespace which has an ancestor named MyNamespace\nMyNamespace.?.MyOtherNamespace| Any namespace called MyOtherNamespace which has a grandparent named MyNamespace\n/RegexPattern/| Any namespace that matches the specified regular expression (Regex) pattern. <br> The pattern must be enclosed in forward slashes ('/'). <br> Regex special characters must be escaped, e.g. '.' should be \"\\\\.\". See the [Regex reference](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference) for details.\n\n### Example One\n```xml\n<NsDepCopConfig IsEnabled=\"true\" ChildCanDependOnParentImplicitly=\"true\">\n    <Allowed From=\"*\" To=\"System.*\" />\n    <Allowed From=\"NsDepCop.*\" To=\"Microsoft.CodeAnalysis.*\" />\n    <Allowed From=\"NsDepCop.ParserAdapter.Roslyn\" To=\"NsDepCop.Analysis\" />\n</NsDepCopConfig>\n```\n\nMeaning:\n* **Any** namespace can reference the **System** namespace and any of its sub-namespaces.\n* The **NsDepCop** namespace and all of its sub-namespaces can reference the **Microsoft.CodeAnalysis** namespace and any of its sub-namespaces.\n* The **NsDepCop.ParserAdapter.Roslyn** namespace can reference the **NsDepCop.Analysis** namespace (but not its sub-namespaces).\n\n### Example Two\n```xml\n<NsDepCopConfig IsEnabled=\"true\" CheckAssemblyDependencies=\"true\">\n    <AllowedAssembly From=\"*\" To=\"*\" />\n    <DisallowedAssembly From=\"*.Repository\" To=\"*.Service\" />\n</NsDepCopConfig>\n```\n\nMeaning:\n* **Any** assembly can reference each other with the following exception.\n* The **Repository** layer cannot reference the **Service** layer.\n\nTip: When using the allowlisting approach for assemblies, don't forget the include the following rules:\n\n```xml\n<NsDepCopConfig IsEnabled=\"true\" CheckAssemblyDependencies=\"true\">\n    <AllowedAssembly From=\"*\" To=\"mscorlib\" />\n    <AllowedAssembly From=\"*\" To=\"netstandard\" />\n    <AllowedAssembly From=\"*\" To=\"System.*\" />\n</NsDepCopConfig>\n```\n\n### Config attributes\nYou can set the following attributes on the root element. (Bold marks the the **default** value.)\n\nAttribute | Values | Description\n--- | --- | ---\n**IsEnabled** | **true**, false | If set to false then analysis is not performed for the project.\n**ChildCanDependOnParentImplicitly** | true, **false** | If set to true then all child namespaces can depend on any of their parents without an explicit allowing rule. The recommended value is **true**. (False is default for backward compatibility.)\n**ParentCanDependOnChildImplicitly** | true, **false** | If set to true then all parent namespaces can depend on any of their children without an explicit allowing rule. The recommended value is **false**.\n**MaxIssueCount** | int (>0), default: **100** | Analysis stops when reaching this number of dependency issues.\n**AutoLowerMaxIssueCount** | true, **false** | If set to true then each successful build yielding fewer issues than MaxIssueCount sets MaxIssueCount to the current number of issues.\n**InheritanceDepth** | int (>=0), default: **0** | Sets the number of parent folder levels to inherit config from. 0 means no inheritance.\n**ExcludedFiles** | Comma separated list of [file patterns](https://github.com/dazinator/DotNet.Glob) | Defines which source files should be excluded from the analysis. Paths are relative to the config file's folder. E.g.: `**/*.g.cs,TestFiles/*.cs`\n**CheckAssemblyDependencies** | true, **false** | We adopt the 'disallowed-by-default' approach for assembly dependencies check, similar to how we handle namespace dependencies (where everything is disallowed unless explicitly permitted). To ensure the backward compatibility, this configuration attribute has been introduced to explicitly enable the assembly dependency checking. By default this attribute is false.\n\n### Allowlisting\n* The **`<Allowed From=\"N1\" To=\"N2\"/>`** config element defines that **N1** namespace can depend on **N2** namespace.\n* If a dependency does not match any of the allowed rules then it's considered disallowed.\n\nExamples:\n\nExample | Meaning\n-|-\n`<Allowed From=\"MyNamespace\" To=\"System\" />` | **MyNamespace** can depend on **System**\n`<Allowed From=\"MyNamespace\" To=\"System.*\" />` | **MyNamespace** can depend on **System and any sub-namespace**\n`<Allowed From=\"MyNamespace\" To=\"*\" />` | **MyNamespace** can depend on **any namespace**\n`<Allowed From=\"MyNamespace\" To=\".\" />` | **MyNamespace** can depend on the **global namespace**\n`<Allowed From=\"MyNamespace\" To=\"System.*.Serialization.*\" />` | **MyNamespace** can depend on all **Serialization** namespaces in **System** and their sub-namespaces\n\n### Denylisting\n* The **`<Disallowed From=\"N1\" To=\"N2\"/>`** config element defines that **N1** namespace **must not** depend on **N2** namespace.\n* To implement the denylisting behavior, you also have to define an \"allow all\" rule, otherwise no dependency will be allowed.\n* Only those dependencies are allowed that has a matching \"Allowed\" rule and no match with any of the \"Disallowed\" rules.\n* You can specify any number of \"Allowed\" and \"Disallowed\" rules in any order.\n* If both an \"Allowed\" and a \"Disallowed\" rule are matched then \"Disallowed\" is the \"stronger\".\n\nExample:\n```xml\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"MyFrontEnd.*\" To=\"MyDataAccess.*\" />\n</NsDepCopConfig>\n```\n\nMeaning:\n* Every dependency is allowed but MyFrontEnd (and its sub-namespace) must not depend on MyDataAccess (and its sub-namespaces).\n\n### Behavior of the wildcards '*' and '?'\nIf any `Disallowed` rule matches, no `Allowed` rule is considered.\n\nIf multiple `Allowed` rules match the same namespace, the one with best matching `From` rule is selected.\n\nThe best matching rule is the one with the minimal edit distance between namespace pattern and namespace name. The edit distance is calculated as the sum of all edit operations which are needed to replace the wildcards with the namespace names. The costs are as follows:\n* Replacing a `?` has a cost of 1.\n* Replacing a `*` has a cost of 1 and additionaly a cost of 1 per sub-namespace that replaces the `*`.\n\nExample: When matching the namespace `A.B.C.D` the rule `A.?.?.D` (edit distance = 2) is preferred to the rule `A.*.D` (edit distance = 3). If multiple rules have the same edit distance, the behavior is undefined.\n\n### Namespace surface\n* The *surface* of a namespace consists of the types that are visible to some other namespace.\n* The **`<VisibleMembers>`** config element defines the surface of a namespace.\n* In the following example **GameLogic** can use only **Vector2** and **Vector3** types of the **UnityEngine** namespace.\n```xml\n<Allowed From=\"GameLogic\" To=\"UnityEngine\">\n    <VisibleMembers>\n        <Type Name=\"Vector2\" />\n        <Type Name=\"Vector3\" />\n    </VisibleMembers>\n</Allowed>\n```\n* Notice that the surface is defined in the context of a particular namespace dependency, that is, this surface of **UnityEngine** is accessible only to **GameLogic**.\n* You can define different surfaces for different other namespaces.\n* You can also define a **\"global\"** surface, that is, a surface that is applicable to all namespaces that otherwise are allowed to depend on **UnityEngine**. See the following example. \n```xml\n<VisibleMembers OfNamespace=\"UnityEngine\">\n    <Type Name=\"Vector2\" />\n    <Type Name=\"Vector3\" />\n</VisibleMembers>\n```\n* Notice that when defining a \"global\" surface the `<VisibleMembers>` element is not embedded in an `<Allowed>` element but you must specify the **OfNamespace** attribute.\n\n### Allowing all child namespaces to depend on their parents\nYou can specify the **ChildCanDependOnParentImplicitly** attribute on the NsDepCopConfig element.\n* True means that all child namespaces can depend on any of their parent namespaces without requiring an explicit Allowed rule.\n* True is in line with how C# type resolution works: it searches parent namespaces without requiring an explicit using statement.\n* False means that all dependencies between children and their parents must be explicitly allowed with a rule.\n* False is the default for backward compatibility.\n\nExample:\n```xml\n<NsDepCopConfig ChildCanDependOnParentImplicitly=\"true\">\n    <!-- The following rule is not necessary because the ChildCanDependOnParentImplicitly=\"true\" attribute implies it. -->\n    <Allowed From=\"MyNamespace.SubNamespace\" To=\"MyNamespace\" />\n</NsDepCopConfig>\n```\n\n### Allowing all parent namespaces to depend on their children\nYou can specify the **ParentCanDependOnChildImplicitly** attribute on the NsDepCopConfig element.\n\nHowever, this is **not recommended**, because child namespaces are usually more concrete/specialized than their parents and the dependecies should point from the more concrete/specialized to the more abstract/generic and not the other way.\n\n## Config inheritance\nFrom v1.6 NsDepCop supports config inheritance, aka multi-level config.\n\n* The goal is to achieve \"DRY\" configs, that is, **avoid redundant info** in config.nsdepcop files.\n* You can extract common config settings from project-level config.nsdepcop files and put them into a **\"master\"** config file, that must be in a folder that is a common ancestor of the project folders, e.g. the solution folder.\n* The \"master\" config file must also be named config.nsdepcop.\n* You have to **\"turn on\" inheritance** in the project-level configs by setting the `InheritanceDepth` attribute to a number that indicates the number of folder levels between the project folder and the master config's folder. \n* Typically you put the master config file into the solution folder which is the immediate parent of the project folders, so you set `InheritanceDepth=\"1\"` in all project-level configs.\n\nExample: \n\n```xml\nconfig.nsdepcop file in \"C:\\MySolution\":\n\n<NsDepCopConfig ChildCanDependOnParentImplicitly=\"true\">\n    <Allowed From=\"*\" To=\"System.*\" />\n    <Allowed From=\"*\" To=\"MoreLinq\" />\n    <Allowed From=\"*\" To=\"NsDepCop.Core.Util\" />\n</NsDepCopConfig>\n\nconfig.nsdepcop file in \"C:\\MySolution\\MyProject\":\n\n<NsDepCopConfig InheritanceDepth=\"1\">\n    <Allowed From=\"NsDepCop.MsBuildTask\" To=\"NsDepCop.Core.Interface.*\" />\n    <Allowed From=\"NsDepCop.MsBuildTask\" To=\"NsDepCop.Core.Factory\" />\n    <Allowed From=\"NsDepCop.MsBuildTask\" To=\"Microsoft.Build.*\" />\n</NsDepCopConfig>\n``` \n\nMore info:\n* If there is a conflict between the project-level and the inherited settings then the project-level settings \"wins\".\n* The `IsEnabled` attribute has different meaning in the project-level config and in inherited configs.\n  * If `IsEnabled=\"false\"` in a project-level config then the project don't get analyzed.\n  * If `IsEnabled=\"false\"` in an inherited config then its content doesn't get inherited.\n* The inheritance is not limited to just a project and a solution level config; you can have any number of config.nsdepcop files at any folder levels. Just make sure you set the `InheritanceDepth` to a number that is great enough to find all the higher-level configs.\n* There must always be a config.nsdepcop file in the project folder if you want to analyze that project. \nEven if all the settings come from a higher-level config, you have to put **at least a minimal config to the project level**, that enables the inheritance in the first place.\nE.g.: `<NsDepCopConfig InheritanceDepth=\"3\"/>`\n\n## Dealing with a high number of dependency issues\nIf there are so many dependency issues that you cannot fix them all at once but you still want to control them somehow then try the following.\n\n* Prevent the introduction of more dependency issues. Set the current number of issues as the maximum and make it an error to create more.\n\n```xml\n<NsDepCopConfig MaxIssueCount=\"<the current number of issues>\">\n```\n\n* Encourage developers to gradually fix the dependency issues by automatically lowering the max issue count whenever possible. Turn on AutoLowerMaxIssueCount.\n\n```xml\n<NsDepCopConfig AutoLowerMaxIssueCount=\"true\" MaxIssueCount=\"<the current number of issues>\">\n```\n\n> Please note that when NsDepCop modifies the nsdepcop.config files their formatting will be reset (because of the XML deserialization/serialization roundtrip).\n\n## Disabling with an environment variable\nTo disable the tool **globally**, set the **DisableNsDepCop** environment variable to **true** or **1**.\n\n`setx DisableNsDepCop 1`\n\nIt will affect both MSBuild integration (NuGet package) and Visual Studio integration (VSIX package).\n\nNote that it won't affect processes that are already running, only the newly started ones.\n\n## Config XML schema\nSee the XSD schema of config.nsdepcop [here](../source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd).\n\n## Config XML schema support in Visual Studio\nAdd NsDepCop config XML schema to the Visual Studio schema cache to get validation and IntelliSense when editing NsDepCop config files.\n\n* Copy the following files into the Visual Studio schema cache folder, located at &lt;VsInstallDir&gt;/Xml/Schemas (eg. C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Xml\\Schemas):\n  * [NsDepCopCatalog.xml](../source/NsDepCop.ConfigSchema/NsDepCopCatalog.xml)\n  * [NsDepCopConfig.xsd](../source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd)\n\n## v1.x only topics\nThe following topics apply only to v1.x versions.\n\n### Config attributes deprecated in v2.0\n\nAttribute | Values | Description\n--- | --- | ---\n**CodeIssueKind** | Info, **Warning**, Error | Dependency violations are reported at this severity level.\n**InfoImportance** | Low, **Normal**, High | Info messages are reported to MSBuild at this level. This setting and the MSBuild verbosity (/v) swicth together determine whether a message appears on the output or not. See [Controlling verbosity](#controlling-verbosity) for details.\n**MaxIssueCountSeverity** | Info, **Warning**, Error | This is the severity of the issue of reaching MaxIssueCount.\n**AnalyzerServiceCallRetryTimeSpans** | Comma separated list of wait times in milliseconds, default: **100, 300, 1000, 3000, 10000** | These wait times are used between retries when the NsDepCop MsBuild Task cannot communicate with the out-of-process analyzer service.\n\n### Controlling verbosity\n\n* Besides emitting dependency violation issues, the tool can emit diagnostic and info messages too.\n  * **Info messages** tell you when was the tool started and finished.\n  * **Diagnostic messages** help you debug config problems by dumping config contents and dependency validation result cache change events.\n* When the tool is run by MSBuild you can modify the [verbosity switch (/v:level)](https://msdn.microsoft.com/en-us/library/ms164311.aspx) to get more or less details in the output.\n  * The verbosity levels defined by MSBuild are the following (ordered from less verbose to most verbose): q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]\n  * Set it to **detailed** or higher to see NsDepCop **diagnostic messages**.\n  * Set it to **normal** or higher to see NsDepCop **info messages**.\n\nAdvanced settings:\n* You can also modify the importance level of NsDepCop info messages by setting the `InfoImportance` attribute in config.nsdepcop to Low, Normal or High.\n* This is useful if you want to keep the MSBuild verbosity level at a certain value for some reason (e.g.: because of other build steps you always want to keep verbosity at minimal level), and you want to control whether NsDepCop info messages are visible at that certain MSBuild verbosity level or not.\n* The following table shows which InfoImportance levels are shown at certain MSBuild verbosity levels.\n\n| MSBuild verbosity level| Low InfoImportance | Normal InfoImportance | High InfoImportance |\n| - | - | - | - |\n| q[uiet] | - | - | - |\n| m[inimal] | - | - | yes |\n| n[ormal] | - | yes | yes |\n| d[etailed] | yes | yes | yes |\n| diag[nostic] | yes | yes | yes |\n\nE.g.: if you want NsDepCop info messages to show up at minimal MSBuild verbosity then set `InfoImportance` to High.\n\n### Disabling to tool with MSBuild property\nTo disable the tool in MSBuild, set the **DisableNsDepCop** property to **true**.\n\n```xml\n<PropertyGroup>\n  <DisableNsDepCop>true</DisableNsDepCop>\n</PropertyGroup>\n```\n\n### Overriding the disabled state with MSBuild property\nTo force executing the tool in MSBuild, set the **ForceNsDepCop** property to **true**.\n\n`msbuild MySolution.sln -t:NsDepCop_Analyze -p:ForceNsDepCop=true`\n\n### Running NsDepCop only as an explicit command\nIf NsDepCop slows down the build too much then you can disable it as part of the build and run it explicitly before checking in.\n\n* Disable NsDepCop in every build by creating a file called [Directory.Build.Props](https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build) in your source root directory with the following content:\n ```xml\n<Project>\n  <PropertyGroup>\n    <DisableNsDepCop>true</DisableNsDepCop>\n  </PropertyGroup>\n</Project>\n```\n\n* Create a cmd file that runs only NsDepCop. Run it before every check-in.\n\n`msbuild MySolution.sln -t:NsDepCop_Analyze -p:ForceNsDepCop=true`\n\n### NsDepCop ServiceHost\nNsDepCop NuGet package **v1.7.1** have introduced the NsDepCop ServiceHost to improve build performance.\n* It runs in the background as a standalone process, communicates via named pipes and serves requests coming from NsDepCopTask instances running inside MSBuild processes.\n* It is started automatically when needed by an NsDepCopTask and quits automatically when the MSBuild process that started it exits.\n* By running continuously it avoids the repeated startup times which is significant.\n\nYou can control the lifetime of NsDepCop ServiceHost by controlling the lifetime of the MSBuild processes by modifying the **MSBUILDDISABLENODEREUSE** environment variable.\n* If you set it to 1 then new MSBuild processes are started for each build and they exit when the build finishes. So do NsDepCop ServiceHost.\n* If you set it to **0** then MSBuild processes are kept alive until the Visual Studio instance that started them exits. **This option gives the best build (and NsDepCop) performance.**\n"
  },
  {
    "path": "doc/Troubleshooting.md",
    "content": "# NsDepCop Troubleshooting\n\n* [Exception: Unable to communicate with NsDepCop service](#item5)\n* [NsDepCop NuGet package is not adding config.nsdepcop file to the project](#item4)\n* [Anonymous types raise false alarms](#item3)\n\n<a name=\"item5\"></a>\n## Exception: Unable to communicate with NsDepCop service\n> Applies only to versions before v2.0.\n\nThis problem is either caused by a bug or by the analyzer client not waiting enough time for the analyzer server started in a separate process to spin up.\nTo fix it:\n* Update to v1.10.1 or later. \n* Try to set longer and/or more wait intervals in your config.nsdepcop file(s) by adding the AnalyzerServiceCallRetryTimeSpans attribute to the root element and fiddling with its value. The value should be a comma separated list of wait times between retries (in milliseconds).\n  * E.g. this config waits 100ms, then 1sec, then 10sec:\n\n```xml\n<NsDepCopConfig AnalyzerServiceCallRetryTimeSpans=\"100,1000,10000\">\n```\n\n<a name=\"item4\"></a>\n## NsDepCop NuGet package is not adding config.nsdepcop file to the project\n> Applies only to versions before v2.0.\n\nIf the project uses the **PackageReference** package manager format then content files are not added to the project. \nWorkaround:\n* **Add** a file called **config.nsdepcop** and fill it in using the examples in [Help](Help.md).\n* Install the NsDepCop Visual Studio Extension [![Visual Studio extension](https://img.shields.io/badge/Visual%20Studio%20Marketplace-NsDepCop%20VS2017-green.svg)](https://marketplace.visualstudio.com/items?itemName=FerencVizkeleti.NsDepCopVS2017-CodedependencycheckerforC) and then:\n  * Right-click on project >> Add >> New Item... >> NsDepCop Config File\n\n<a name=\"item3\"></a>\n## Anonymous types raise false alarms\n\n> Applies only to versions before v1.6. \n\nFor anonymous types the compiler generates a class with no namespace so they will belong to the 'global namespace'. If your NsDepCop config does not allow referencing the global namespace (denoted with a single dot) then it will raise an alarm that you may consider a false positive.\n\nTo avoid alarms caused by anonymous types you have to add a rule that you allow referencing the global namespace:\n```xml\n<Allowed From=\"YourNamespace\" To=\".\" />\n```\n\nOr to be more lax:\n```xml\n<Allowed From=\"*\" To=\".\" />\n```\n"
  },
  {
    "path": "source/.editorconfig",
    "content": "﻿root = true\n\n[*.cs]\n\n# Default severity for analyzer diagnostics with category 'MicrosoftCodeAnalysisReleaseTracking'\ndotnet_analyzer_diagnostic.category-MicrosoftCodeAnalysisReleaseTracking.severity = none\n\n# NSDEPCOP01: Illegal namespace reference.\ndotnet_diagnostic.NSDEPCOP01.severity = error\n"
  },
  {
    "path": "source/Directory.Build.targets",
    "content": "﻿<Project>\n\n  <!--Begin: Avoid cycle error when package builds itself-->\n  <Choose>\n    <When Condition=\"$(AvoidCycleErrorOnSelfReference) == 'true'\">\n      <PropertyGroup>\n        <PackageId Condition=\"'$(PackageId)' == ''\">$(MSBuildProjectName)</PackageId>\n        <PackageIdTemp>$(PackageId)</PackageIdTemp>\n        <PackageId>$(PackageId)_temp</PackageId>\n      </PropertyGroup>\n    </When>\n  </Choose>\n  <Target Name=\"_UpdatePackageId\" BeforeTargets=\"$(PackDependsOn)\"\n          Condition=\"$(AvoidCycleErrorOnSelfReference) == 'true'\">\n    <PropertyGroup>\n      <PackageId>$(PackageIdTemp)</PackageId>\n    </PropertyGroup>\n  </Target>\n  <!--End: Avoid cycle error when package builds itself-->\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/AssemblyDependency.cs",
    "content": "﻿using System;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    [Serializable]\n    public struct AssemblyDependency\n    {\n        public static AssemblyDependency Empty;\n\n        public AssemblyIdentity FromAssembly { get; }\n\n        public AssemblyIdentity ToAssembly { get; }\n\n        public AssemblyDependency(AssemblyIdentity fromAssembly, AssemblyIdentity toAssembly)\n        {\n            FromAssembly = fromAssembly ?? throw new ArgumentNullException(nameof(fromAssembly));\n            ToAssembly = toAssembly ?? throw new ArgumentNullException(nameof(toAssembly));\n        }\n\n        public override string ToString() => $\"{FromAssembly?.Name}->{ToAssembly?.Name}\";\n\n        public bool Equals(AssemblyDependency other)\n        {\n            return string.Equals(FromAssembly?.Name, other.FromAssembly?.Name)\n                && string.Equals(ToAssembly?.Name, other.ToAssembly?.Name);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            return obj is AssemblyDependency && Equals((AssemblyDependency)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (FromAssembly != null ? FromAssembly.Name.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ (ToAssembly != null ? ToAssembly.Name.GetHashCode() : 0);\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(AssemblyDependency left, AssemblyDependency right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(AssemblyDependency left, AssemblyDependency right)\n        {\n            return !left.Equals(right);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Factory/AssemblyDependencyAnalyzerFactory.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis.Factory\n{\n    public sealed class AssemblyDependencyAnalyzerFactory : IAssemblyDependencyAnalyzerFactory\n    {\n        public IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider configProvider)\n        {\n\n            return new AssemblyDependencyAnalyzer(configProvider);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Factory/DependencyAnalyzerFactory.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Analysis.Factory\n{\n    /// <summary>\n    /// Creates dependency analyzer objects.\n    /// </summary>\n    public sealed class DependencyAnalyzerFactory : IDependencyAnalyzerFactory\n    {\n        private readonly MessageHandler _traceMessageHandler;\n\n        public DependencyAnalyzerFactory(MessageHandler traceMessageHandler)\n        {\n            _traceMessageHandler = traceMessageHandler;\n        }\n\n        public IDependencyAnalyzer Create(IUpdateableConfigProvider configProvider, ITypeDependencyEnumerator typeDependencyEnumerator)\n        {\n          \n            return new DependencyAnalyzer(configProvider, typeDependencyEnumerator, _traceMessageHandler);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Performs assembly dependency analysis on a project.\n    /// </summary>\n    public interface IAssemblyDependencyAnalyzer\n    {\n        IEnumerable<AnalyzerMessageBase> AnalyzeProject(AssemblyIdentity sourceAssembly, IReadOnlyList<AssemblyIdentity> referencedAssemblies);\n\n        /// <summary>\n        /// Re-reads the config.\n        /// </summary>\n        void RefreshConfig();\n\n        /// <summary>\n        /// Gets the current config state.\n        /// </summary>\n        AnalyzerConfigState ConfigState { get; }\n\n        /// <summary>\n        /// Gets the config exception or null if there was no exception.\n        /// </summary>\n        Exception ConfigException { get; }\n\n        /// <summary>\n        /// Gets the current analyzer config or null if there was an error.\n        /// </summary>\n        IAnalyzerConfig Config { get; }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzerFactory.cs",
    "content": "﻿using Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    public interface IAssemblyDependencyAnalyzerFactory\n    {\n        IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider configProvider);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Performs dependency analysis on a project or a syntax node.\n    /// </summary>\n    public interface IDependencyAnalyzer\n    {\n        /// <summary>\n        /// Analyzes a project (source files and referenced assemblies).\n        /// </summary>\n        /// <param name=\"sourceFilePaths\">A collection of the full path of source files.</param>\n        /// <param name=\"referencedAssemblyPaths\">A collection of the full path of referenced assemblies.</param>\n        /// <returns>Issue and info messages, including illegal dependency issues.</returns>\n        IEnumerable<AnalyzerMessageBase> AnalyzeProject(IEnumerable<string> sourceFilePaths, IEnumerable<string> referencedAssemblyPaths);\n\n        /// <summary>\n        /// Analyzes a syntax node.\n        /// </summary>\n        /// <param name=\"syntaxNode\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the project being analyzed.</param>\n        /// <returns>Issue and info messages, including illegal dependency issues.</returns>\n        IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode syntaxNode, SemanticModel semanticModel);\n\n        /// <summary>\n        /// Re-reads the config.\n        /// </summary>\n        void RefreshConfig();\n\n        /// <summary>\n        /// Gets the current config state.\n        /// </summary>\n        AnalyzerConfigState ConfigState { get; }\n\n        /// <summary>\n        /// Gets the config exception or null if there was no exception.\n        /// </summary>\n        Exception ConfigException { get; }\n\n        /// <summary>\n        /// Gets the current analyzer config or null if there was an error.\n        /// </summary>\n        IAnalyzerConfig Config { get; }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzerFactory.cs",
    "content": "﻿using Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Creates dependency analyzer objects.\n    /// </summary>\n    public interface IDependencyAnalyzerFactory\n    {\n        IDependencyAnalyzer Create(IUpdateableConfigProvider configProvider, ITypeDependencyEnumerator typeDependencyEnumerator);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/ITypeDependencyEnumerator.cs",
    "content": "using System.Collections.Generic;\nusing DotNet.Globbing;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Enumerates type dependencies for a project or a syntax node.\n    /// </summary>\n    public interface ITypeDependencyEnumerator \n    {\n        /// <summary>\n        /// Enumerates type dependencies for a project (source files and referenced assemblies).\n        /// </summary>\n        /// <param name=\"sourceFilePaths\">A collection of the full path of source files.</param>\n        /// <param name=\"referencedAssemblyPaths\">A collection of the full path of referenced assemblies.</param>\n        /// <param name=\"sourcePathExclusionGlobs\">A collection of file path patterns (globs) for excluding source files from analysis.</param>\n        /// <returns>A collection of type dependencies.</returns>\n        IEnumerable<TypeDependency> GetTypeDependencies(\n            IEnumerable<string> sourceFilePaths, \n            IEnumerable<string> referencedAssemblyPaths, \n            IEnumerable<Glob> sourcePathExclusionGlobs);\n\n        /// <summary>\n        /// Enumerates type dependencies for a syntax node.\n        /// </summary>\n        /// <param name=\"syntaxNode\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the project being analyzed.</param>\n        /// <param name=\"sourcePathExclusionGlobs\">A collection of file path patterns (globs) for excluding source files from analysis.</param>\n        /// <returns>A collection of type dependencies.</returns>\n        IEnumerable<TypeDependency> GetTypeDependencies(\n            SyntaxNode syntaxNode, \n            SemanticModel semanticModel, \n            IEnumerable<Glob> sourcePathExclusionGlobs);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    public sealed class AssemblyDependencyAnalyzer : IAssemblyDependencyAnalyzer\n    {\n        private readonly IUpdateableConfigProvider _configProvider;\n        private readonly object _configRefreshLock = new();\n\n        private IAssemblyDependencyValidator _assemblyDependencyValidator;\n        private IAnalyzerConfig _config;\n\n        public AssemblyDependencyAnalyzer(\n            IUpdateableConfigProvider configProvider)\n        {\n            _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));\n            UpdateConfig();\n        }\n\n        public AnalyzerConfigState ConfigState\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.ConfigState;\n                }\n            }\n        }\n\n        public Exception ConfigException\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.ConfigException;\n                }\n            }\n        }\n\n        public IAnalyzerConfig Config\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.Config;\n                }\n            }\n        }\n\n        public IEnumerable<AnalyzerMessageBase> AnalyzeProject(\n            AssemblyIdentity sourceAssembly,\n            IReadOnlyList<AssemblyIdentity> referencedAssemblies)\n        {\n            if (sourceAssembly == null) throw new ArgumentNullException(nameof(sourceAssembly));\n            if (referencedAssemblies == null) throw new ArgumentNullException(nameof(referencedAssemblies));\n\n            if (GlobalSettings.IsToolDisabled())\n                return [new ToolDisabledMessage()];\n\n            lock (_configRefreshLock)\n            {\n                var assemblyDependencyEnumerable = GetAssemblyDependencies(sourceAssembly, referencedAssemblies);\n                var illegalAssemblyDependencyEnumerable = GetIllegalAssemblyDependencies(assemblyDependencyEnumerable);\n                return AnalyzeCore(illegalAssemblyDependencyEnumerable);\n            }\n        }\n\n        private IEnumerable<AssemblyDependency> GetAssemblyDependencies(AssemblyIdentity sourceAssembly, IReadOnlyList<AssemblyIdentity> referencedAssemblies)\n        {\n            foreach (AssemblyIdentity referencedAssembly in referencedAssemblies)\n            {\n                yield return new AssemblyDependency(sourceAssembly, referencedAssembly);\n            }\n        }\n\n        public void RefreshConfig()\n        {\n            lock (_configRefreshLock)\n            {\n                _configProvider.RefreshConfig();\n                UpdateConfig();\n            }\n        }\n\n        private void UpdateConfig()\n        {\n            var oldConfig = _config;\n            _config = _configProvider.Config;\n\n            if (oldConfig == _config)\n                return;\n\n            _assemblyDependencyValidator = CreateTypeDependencyValidator();\n        }\n\n        private AssemblyDependencyValidator CreateTypeDependencyValidator()\n        {\n            return _configProvider.ConfigState == AnalyzerConfigState.Enabled\n                ? new AssemblyDependencyValidator(_configProvider.Config)\n                : null;\n        }\n\n        private IEnumerable<AnalyzerMessageBase> AnalyzeCore(IEnumerable<AssemblyDependency> illegalTypeDependencyEnumerable)\n        {\n            return _configProvider.ConfigState switch\n            {\n                AnalyzerConfigState.NoConfig => new NoConfigFileMessage().ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.Disabled => new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.ConfigError => new ConfigErrorMessage(_configProvider.ConfigException).ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.Enabled => _configProvider.Config.CheckAssemblyDependencies\n                    ? PerformAnalysis(illegalTypeDependencyEnumerable)\n                    : new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),\n                _ => throw new Exception($\"Unexpected ConfigState: {_configProvider.ConfigState}\")\n            };\n        }\n\n        private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(IEnumerable<AssemblyDependency> illegalTypeDependencyEnumerator)\n        {\n            return illegalTypeDependencyEnumerator.Select(element => new IllegalAssemblyDependencyMessage(element));\n        }\n\n        private IEnumerable<AssemblyDependency> GetIllegalAssemblyDependencies(IEnumerable<AssemblyDependency> assemblyDependencyEnumerator)\n        {\n            foreach (AssemblyDependency assemblyDependency in assemblyDependencyEnumerator)\n            {\n                DependencyStatus dependencyStatus = _assemblyDependencyValidator.IsDependencyAllowed(assemblyDependency);\n                if (!dependencyStatus.IsAllowed)\n                {\n                    yield return assemblyDependency;\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyValidator.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    public sealed class AssemblyDependencyValidator : IAssemblyDependencyValidator\n    {\n        private readonly HashSet<DependencyRule> _allowRules;\n        private readonly HashSet<DependencyRule> _disallowRules;\n\n        public AssemblyDependencyValidator(IDependencyRules dependencyRules)\n        {\n            if (dependencyRules is null) throw new ArgumentNullException(nameof(dependencyRules));\n\n            _allowRules = dependencyRules.AllowedAssemblyRules;\n            _disallowRules = dependencyRules.DisallowedAssemblyRules;\n        }\n\n        public DependencyStatus IsDependencyAllowed(AssemblyDependency assemblyDependency)\n        {\n            if (assemblyDependency == AssemblyDependency.Empty)\n            {\n                throw new ArgumentException(\"The parameter is empty.\", nameof(assemblyDependency));\n            }\n\n            // These assembly names are coming from a compiler so we don't have to validate them.\n            var fromAssembly = new Domain(assemblyDependency.FromAssembly.Name, validate: false);\n            var toAssembly = new Domain(assemblyDependency.ToAssembly.Name, validate: false);\n\n            var disallowRule = GetDisallowRule(fromAssembly, toAssembly);\n            if (disallowRule is not null)\n                return DependencyStatus.Disallowed;\n\n            var allowRule = GetMostSpecificAllowRule(fromAssembly, toAssembly);\n            if (allowRule is null)\n                return DependencyStatus.Disallowed;\n\n            return DependencyStatus.Allowed;\n        }\n\n        private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)\n        {\n            return _allowRules\n                .Where(element => element.From.Matches(from) && element.To.Matches(to))\n                .MaxByOrDefault(element => element.From.GetMatchRelevance(from));\n        }\n\n        private DependencyRule GetDisallowRule(Domain from, Domain to)\n        {\n            return _disallowRules.FirstOrDefault(element => element.From.Matches(from) && element.To.Matches(to));\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/CachingTypeDependencyValidator.cs",
    "content": "﻿using System.Collections.Concurrent;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    /// <summary>\n    /// Validates type dependencies to a set of allowed/disallowed rules and caches the results.\n    /// </summary>\n    public class CachingTypeDependencyValidator : TypeDependencyValidator, ICacheStatisticsProvider\n    {\n        private readonly MessageHandler _traceMessageHandler;\n        private readonly ConcurrentDictionary<TypeDependency, DependencyStatus> _dependencyValidationCache;\n\n        public int HitCount { get; private set; }\n        public int MissCount { get; private set; }\n\n        public CachingTypeDependencyValidator(IDependencyRules dependencyRules, MessageHandler traceMessageHandler)\n            : base(dependencyRules)\n        {\n            _traceMessageHandler = traceMessageHandler;\n            _dependencyValidationCache = new ConcurrentDictionary<TypeDependency, DependencyStatus>();\n        }\n\n        public double EfficiencyPercent => MathHelper.CalculatePercent(HitCount, HitCount + MissCount);\n        \n        public override DependencyStatus IsAllowedDependency(TypeDependency typeDependency)\n        {\n            if (typeDependency.FromNamespaceName == typeDependency.ToNamespaceName)\n                return DependencyStatus.Allowed;\n\n            var isAllowedDependency = _dependencyValidationCache.GetOrAdd(typeDependency, base.IsAllowedDependency, out var added);\n\n            if (added)\n            {\n                MissCount++;\n                LogTraceMessage($\"Dependency {typeDependency} added to cache as {isAllowedDependency}.\");\n            }\n            else\n            {\n                HitCount++;\n            }\n\n            return isAllowedDependency;\n        }\n\n        private void LogTraceMessage(string message) => _traceMessageHandler?.Invoke(message);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/DependencyAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\nusing DotNet.Globbing;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    /// <summary>\n    /// Abstract base class for dependency analyzers.\n    /// </summary>\n    public sealed class DependencyAnalyzer : IDependencyAnalyzer\n    {\n        private readonly IUpdateableConfigProvider _configProvider;\n        private readonly MessageHandler _traceMessageHandler;\n        private readonly ITypeDependencyEnumerator _typeDependencyEnumerator;\n        private readonly object _configRefreshLock = new();\n\n        private CachingTypeDependencyValidator _typeDependencyValidator;\n        private IAnalyzerConfig _config;\n        private Glob[] _sourcePathExclusionGlobs;\n\n        public DependencyAnalyzer(\n            IUpdateableConfigProvider configProvider,\n            ITypeDependencyEnumerator typeDependencyEnumerator,\n            MessageHandler traceMessageHandler)\n        {\n            _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));\n            _traceMessageHandler = traceMessageHandler;\n            _typeDependencyEnumerator = typeDependencyEnumerator ?? throw new ArgumentNullException(nameof(typeDependencyEnumerator));\n            UpdateConfig();\n        }\n\n\n        public AnalyzerConfigState ConfigState\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.ConfigState;\n                }\n            }\n        }\n\n        public Exception ConfigException\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.ConfigException;\n                }\n            }\n        }\n\n        public IAnalyzerConfig Config\n        {\n            get\n            {\n                lock (_configRefreshLock)\n                {\n                    return _configProvider.Config;\n                }\n            }\n        }\n\n        public IEnumerable<AnalyzerMessageBase> AnalyzeProject(\n            IEnumerable<string> sourceFilePaths,\n            IEnumerable<string> referencedAssemblyPaths)\n        {\n            if (sourceFilePaths == null) throw new ArgumentNullException(nameof(sourceFilePaths));\n            if (referencedAssemblyPaths == null) throw new ArgumentNullException(nameof(referencedAssemblyPaths));\n\n            if (GlobalSettings.IsToolDisabled())\n                return new[] {new ToolDisabledMessage()};\n\n            lock (_configRefreshLock)\n            {\n                return AnalyzeCore(\n                    () => GetIllegalTypeDependencies(\n                        () => _typeDependencyEnumerator.GetTypeDependencies(sourceFilePaths, referencedAssemblyPaths, _sourcePathExclusionGlobs))\n                );\n            }\n        }\n\n        public IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode syntaxNode, SemanticModel semanticModel)\n        {\n            if (syntaxNode == null) throw new ArgumentNullException(nameof(syntaxNode));\n            if (semanticModel == null) throw new ArgumentNullException(nameof(semanticModel));\n\n            lock (_configRefreshLock)\n            {\n                return AnalyzeCore(\n                    () => GetIllegalTypeDependencies(\n                        () => _typeDependencyEnumerator.GetTypeDependencies(syntaxNode, semanticModel, _sourcePathExclusionGlobs))\n                );\n            }\n        }\n\n        public void RefreshConfig()\n        {\n            lock (_configRefreshLock)\n            {\n                _configProvider.RefreshConfig();\n                UpdateConfig();\n            }\n        }\n\n        private void UpdateConfig()\n        {\n            var oldConfig = _config;\n            _config = _configProvider.Config;\n\n            if (oldConfig == _config)\n                return;\n\n            _typeDependencyValidator = CreateTypeDependencyValidator();\n            _sourcePathExclusionGlobs = _config.SourcePathExclusionPatterns.Select(Glob.Parse).ToArray();\n        }\n\n        private CachingTypeDependencyValidator CreateTypeDependencyValidator()\n        {\n            return _configProvider.ConfigState == AnalyzerConfigState.Enabled\n                ? new CachingTypeDependencyValidator(_configProvider.Config, _traceMessageHandler)\n                : null;\n        }\n\n        private IEnumerable<AnalyzerMessageBase> AnalyzeCore(Func<IEnumerable<IllegalTypeDependency>> illegalTypeDependencyEnumerator)\n        {\n            return _configProvider.ConfigState switch\n            {\n                AnalyzerConfigState.NoConfig => new NoConfigFileMessage().ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.Disabled => new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.ConfigError => new ConfigErrorMessage(_configProvider.ConfigException).ToEnumerable<AnalyzerMessageBase>(),\n                AnalyzerConfigState.Enabled => PerformAnalysis(illegalTypeDependencyEnumerator),\n                _ => throw new Exception($\"Unexpected ConfigState: {_configProvider.ConfigState}\")\n            };\n        }\n\n        private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(Func<IEnumerable<IllegalTypeDependency>> illegalTypeDependencyEnumerator)\n        {\n            return illegalTypeDependencyEnumerator().Select(i => new IllegalDependencyMessage(i.TypeDependency, i.AllowedMembers));\n\n            // TODO: AutoLowerMaxIssueCount logic should be moved to NsDepCopAnalyzer to act at the end of a compilation.\n            // This method is called multiple times during a compilation so we don't know the final issue count here\n            //var finalIssueCount = GetInterlocked(ref issueCount);\n            //if (config.AutoLowerMaxIssueCount && finalIssueCount < maxIssueCount)\n            //    ConfigProvider.UpdateMaxIssueCount(finalIssueCount);\n        }\n\n        private IEnumerable<IllegalTypeDependency> GetIllegalTypeDependencies(Func<IEnumerable<TypeDependency>> typeDependencyEnumerator)\n        {\n            var allDependencies = typeDependencyEnumerator()\n                .Select(dep => (Dependency: dep, Status: _typeDependencyValidator.IsAllowedDependency(dep)));\n            \n            var excessIllegalDependencies = allDependencies\n                .Where(i => !i.Status.IsAllowed)\n                .Take(_config.MaxIssueCount + 1);\n            \n            foreach (var illegalDependency in excessIllegalDependencies)\n            {\n                yield return new IllegalTypeDependency(illegalDependency.Dependency, illegalDependency.Status.AllowedTypeNames);\n            }\n\n            _traceMessageHandler?.Invoke(GetCacheStatisticsMessage(_typeDependencyValidator));\n        }\n\n        private static string GetCacheStatisticsMessage(ICacheStatisticsProvider i) =>\n            $\"Cache hits: {i.HitCount}, misses: {i.MissCount}, efficiency (hits/all): {i.EfficiencyPercent:P}\";\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/DependencyStatus.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    public class DependencyStatus\n    {\n        private DependencyStatus()\n        {\n        }\n\n        public bool IsAllowed { get; private set; }\n\n        public string[] AllowedTypeNames { get; private set; } = Array.Empty<string>();\n\n        public static readonly DependencyStatus Allowed = new() { IsAllowed = true };\n\n        public static readonly DependencyStatus Disallowed = new() { IsAllowed = false };\n\n        public static DependencyStatus DisallowedUseOfMember(string[] allowedTypeNames) =>\n            new() { IsAllowed = false, AllowedTypeNames = allowedTypeNames };\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/IAssemblyDependencyValidator.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Implementation\n{\n    public interface IAssemblyDependencyValidator\n    {\n        DependencyStatus IsDependencyAllowed(AssemblyDependency assemblyDependency);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/ITypeDependencyValidator.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Implementation\n{\n    /// <summary>\n    /// Determines whether a type-to-type dependency is allowed or not.\n    /// </summary>\n    internal interface ITypeDependencyValidator\n    {\n        /// <summary>\n        /// Decides whether a dependency is allowed based on the rule configuration.\n        /// </summary>\n        /// <param name=\"typeDependency\">A dependency of two types.</param>\n        /// <returns>True if the dependency is allowed, false otherwise.</returns>\n        DependencyStatus IsAllowedDependency(TypeDependency typeDependency);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/IllegalTypeDependency.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Implementation\n{\n    public class IllegalTypeDependency\n    {\n        public TypeDependency TypeDependency { get; }\n        \n        public string[] AllowedMembers { get; }\n    \n        public IllegalTypeDependency(TypeDependency typeDependency, string[] allowedMembers)\n        {\n            TypeDependency = typeDependency;\n            AllowedMembers = allowedMembers;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Implementation/TypeDependencyValidator.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n    /// <summary>\n    /// Determines whether a given type-to-type dependency is allowed.\n    /// </summary>\n    public class TypeDependencyValidator : ITypeDependencyValidator\n    {\n        private readonly Dictionary<DependencyRule, TypeNameSet> _allowRules;\n        private readonly HashSet<DependencyRule> _disallowRules;\n        private readonly Dictionary<Domain, TypeNameSet> _visibleTypesPerNamespaces;\n        private readonly bool _childCanDependOnParentImplicitly;\n        private readonly bool _parentCanDependOnChildImplicitly;\n\n        public TypeDependencyValidator(IDependencyRules dependencyRules)\n        {\n            _allowRules = dependencyRules.AllowRules;\n            _disallowRules = dependencyRules.DisallowRules;\n            _visibleTypesPerNamespaces = dependencyRules.VisibleTypesByNamespace;\n            _childCanDependOnParentImplicitly = dependencyRules.ChildCanDependOnParentImplicitly;\n            _parentCanDependOnChildImplicitly = dependencyRules.ParentCanDependOnChildImplicitly;\n        }\n\n        /// <summary>\n        /// Decides whether a dependency is allowed based on the rule configuration.\n        /// </summary>\n        /// <param name=\"typeDependency\">A dependency of two types.</param>\n        /// <returns>True if the dependency is allowed, false otherwise.</returns>\n        public virtual DependencyStatus IsAllowedDependency(TypeDependency typeDependency)\n        {\n            // Inside a namespace all dependencies are allowed.\n            if (typeDependency.FromNamespaceName == typeDependency.ToNamespaceName)\n                return DependencyStatus.Allowed;\n\n            // These namespace names are coming from a compiler so we don't have to validate them.\n            var fromNamespace = new Domain(typeDependency.FromNamespaceName, validate: false);\n            var toNamespace = new Domain(typeDependency.ToNamespaceName, validate: false);\n\n            var disallowRule = GetDisallowRule(fromNamespace, toNamespace);\n            if (disallowRule != null)\n                return DependencyStatus.Disallowed;\n\n            if (IsAllowedBecauseChildCanDependOnParent(fromNamespace, toNamespace))\n                return DependencyStatus.Allowed;\n            \n            if (IsAllowedBecauseParentCanDependOnChild(fromNamespace, toNamespace))\n                return DependencyStatus.Allowed;\n\n            var allowRule = GetMostSpecificAllowRule(fromNamespace, toNamespace);\n            if (allowRule == null)\n                return DependencyStatus.Disallowed;\n\n            TypeNameSet visibleMembers = GetVisibleMembers(allowRule, toNamespace);\n            if (visibleMembers == null || visibleMembers.Count == 0)\n                return DependencyStatus.Allowed;\n\n            bool isUsingVisibleMember = visibleMembers.Contains(typeDependency.ToTypeName);\n            \n            return isUsingVisibleMember\n                ? DependencyStatus.Allowed\n                : DependencyStatus.DisallowedUseOfMember(visibleMembers.ToArray());\n        }\n\n        private bool IsAllowedBecauseChildCanDependOnParent(Domain fromNamespace, Domain toNamespace)\n        {\n            return _childCanDependOnParentImplicitly && fromNamespace.IsSubDomain(toNamespace);\n        }\n        \n        private bool IsAllowedBecauseParentCanDependOnChild(Domain fromNamespace, Domain toNamespace)\n        {\n            return _parentCanDependOnChildImplicitly && toNamespace.IsSubDomain(fromNamespace);\n        }\n\n        private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)\n        {\n            return _allowRules.Keys\n                .Where(i => i.From.Matches(from) && i.To.Matches(to))\n                .MaxByOrDefault(i => i.From.GetMatchRelevance(from));\n        }\n\n        private DependencyRule GetDisallowRule(Domain from, Domain to)\n        {\n            return _disallowRules\n                .FirstOrDefault(i => i.From.Matches(from) && i.To.Matches(to));\n        }\n\n        private TypeNameSet GetVisibleMembers(DependencyRule allowRule, Domain targetNamespace)\n        {\n            TypeNameSet allowedTypeNameSet;\n\n            if (_allowRules.TryGetValue(allowRule, out allowedTypeNameSet) &&\n                allowedTypeNameSet != null &&\n                allowedTypeNameSet.Any())\n                return allowedTypeNameSet;\n\n            if (_visibleTypesPerNamespaces.TryGetValue(targetNamespace, out allowedTypeNameSet))\n                return allowedTypeNameSet;\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/AnalyzerMessageBase.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// Abstract base class for messages returned by the dependency analyzer.\n    /// </summary>\n    public abstract class AnalyzerMessageBase\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/ConfigDisabledMessage.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// A message indicating that analysis was disabled in the config file.\n    /// </summary>\n    public sealed class ConfigDisabledMessage : AnalyzerMessageBase\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/ConfigErrorMessage.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// A message that describes a config exception.\n    /// </summary>\n    public sealed class ConfigErrorMessage : AnalyzerMessageBase\n    {\n        public Exception Exception { get; }\n\n        public ConfigErrorMessage(Exception exception)\n        {\n            Exception = exception;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/IllegalAssemblyDependencyMessage.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Messages\n{\n    public sealed class IllegalAssemblyDependencyMessage : AnalyzerMessageBase\n    {\n        public AssemblyDependency IllegalAssemblyDependency { get; }\n\n        public IllegalAssemblyDependencyMessage(AssemblyDependency illegalAssemblyDependency)\n        {\n            IllegalAssemblyDependency = illegalAssemblyDependency;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/IllegalDependencyMessage.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// A message containing an illegal type dependency.\n    /// </summary>\n    public sealed class IllegalDependencyMessage : AnalyzerMessageBase\n    {\n        public TypeDependency IllegalDependency { get; }\n\n        public string[] AllowedMemberNames { get; } = Array.Empty<string>();\n\n        public IllegalDependencyMessage(TypeDependency illegalDependency, string[] allowedMemberNames)\n        {\n            IllegalDependency = illegalDependency;\n            AllowedMemberNames = allowedMemberNames;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/NoConfigFileMessage.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// A message indicating that no config file was found for a project or location.\n    /// </summary>\n    public sealed class NoConfigFileMessage : AnalyzerMessageBase\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/Messages/ToolDisabledMessage.cs",
    "content": "﻿namespace Codartis.NsDepCop.Analysis.Messages\n{\n    /// <summary>\n    /// A message indicating that analysis was disabled with environment variable.\n    /// </summary>\n    public sealed class ToolDisabledMessage : AnalyzerMessageBase\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/SourceSegment.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Describes a certain segment of a source file. Immutable.\n    /// </summary>\n    [Serializable]\n    public struct SourceSegment\n    {\n        /// <summary>\n        /// The line number of the segment's start (1-based).\n        /// </summary>\n        public int StartLine { get; }\n\n        /// <summary>\n        /// The column number of the segment's start (1-based).\n        /// </summary>\n        public int StartColumn { get; }\n\n        /// <summary>\n        /// The line number of the segment's end (1-based).\n        /// </summary>\n        public int EndLine { get; }\n\n        /// <summary>\n        /// The column number of the segment's end (1-based).\n        /// </summary>\n        public int EndColumn { get; }\n\n        /// <summary>\n        /// The text of the segment.\n        /// </summary>\n        public string Text { get; }\n\n        /// <summary>\n        /// The full path of the source file.\n        /// </summary>\n        public string Path { get; }\n\n        public SourceSegment(int startLine, int startColumn, int endLine, int endColumn, string text, string path)\n        {\n            StartLine = startLine;\n            StartColumn = startColumn;\n            EndLine = endLine;\n            EndColumn = endColumn;\n            Text = text;\n            Path = path;\n        }\n\n        public override string ToString() => $\"{Path} ({StartLine},{StartColumn},{EndLine},{EndColumn})\";\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Analysis/TypeDependency.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n    /// <summary>\n    /// Describes a dependency between two types at a source segment.\n    /// Immutable.\n    /// </summary>\n    [Serializable]\n    public struct TypeDependency\n    {\n        /// <summary>\n        /// The namespace of the referencing type.\n        /// </summary>\n        public string FromNamespaceName { get; }\n\n        /// <summary>\n        /// The name of the referencing type.\n        /// </summary>\n        public string FromTypeName { get; }\n\n        /// <summary>\n        /// The namespace of the referenced type.\n        /// </summary>\n        public string ToNamespaceName { get; }\n\n        /// <summary>\n        /// The name of the referenced type.\n        /// </summary>\n        public string ToTypeName { get; }\n\n        /// <summary>\n        /// The source segment where the dependency was found.\n        /// </summary>\n        public SourceSegment SourceSegment { get; }\n\n        public TypeDependency(string fromNamespaceName, string fromTypeName, string toNamespaceName, string toTypeName, SourceSegment sourceSegment)\n        {\n            if (string.IsNullOrWhiteSpace(fromTypeName))\n                throw new ArgumentException(\"Should not be null or whitespace.\", nameof(fromTypeName));\n            if (string.IsNullOrWhiteSpace(toTypeName))\n                throw new ArgumentException(\"Should not be null or whitespace.\", nameof(toTypeName));\n\n            FromNamespaceName = fromNamespaceName ?? throw new ArgumentNullException(nameof(fromNamespaceName));\n            FromTypeName = fromTypeName;\n            ToNamespaceName = toNamespaceName ?? throw new ArgumentNullException(nameof(toNamespaceName));\n            ToTypeName = toTypeName;\n            SourceSegment = sourceSegment;\n        }\n\n        // TODO: should print source segment too\n        public override string ToString() => $\"{FromNamespaceName}.{FromTypeName}->{ToNamespaceName}.{ToTypeName}\";\n\n        // TODO: should consider source segment too\n        public bool Equals(TypeDependency other)\n        {\n            return string.Equals(FromNamespaceName, other.FromNamespaceName) \n                && string.Equals(FromTypeName, other.FromTypeName) \n                && string.Equals(ToNamespaceName, other.ToNamespaceName) \n                && string.Equals(ToTypeName, other.ToTypeName);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            return obj is TypeDependency && Equals((TypeDependency) obj);\n        }\n\n        // TODO: should consider source segment too\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (FromNamespaceName != null ? FromNamespaceName.GetHashCode() : 0);\n                hashCode = (hashCode*397) ^ (FromTypeName != null ? FromTypeName.GetHashCode() : 0);\n                hashCode = (hashCode*397) ^ (ToNamespaceName != null ? ToNamespaceName.GetHashCode() : 0);\n                hashCode = (hashCode*397) ^ (ToTypeName != null ? ToTypeName.GetHashCode() : 0);\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(TypeDependency left, TypeDependency right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(TypeDependency left, TypeDependency right)\n        {\n            return !left.Equals(right);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/AnalyzerConfigState.cs",
    "content": "﻿namespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Enumerates the possible states of an analyzer's config.\n    /// </summary>\n    public enum AnalyzerConfigState\n    {\n        Enabled,\n        Disabled,\n        NoConfig,\n        ConfigError\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/ConfigDefaults.cs",
    "content": "namespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Defines the default values of the config properties.\n    /// </summary>\n    public static class ConfigDefaults\n    {\n        public const int InheritanceDepth = 0;\n        public const bool IsEnabled = true;\n        public const bool CheckAssemblyDependencies = false;\n        public const int MaxIssueCount = 100;\n        public const bool AutoLowerMaxIssueCount = false;\n        public const bool ChildCanDependOnParentImplicitly = false;\n        public const bool ParentCanDependOnChildImplicitly = false;\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/DependencyRule.cs",
    "content": "﻿using System;\nusing System.Text;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Represents a dependency rule between two domain specifications. Immutable.\n    /// </summary>\n    /// <remarks>\n    /// The 'From' domain specification depends on the 'To' domain specification.\n    /// A domain specification can represent more than just a single domain (eg. a subtree of namespaces).\n    /// </remarks>\n    [Serializable]\n    public class DependencyRule\n    {\n        /// <summary>\n        /// The dependency points from this domain to the other.\n        /// </summary>\n        public DomainSpecification From { get; }\n\n        /// <summary>\n        /// The dependency points into this domain.\n        /// </summary>\n        public DomainSpecification To { get; }\n\n        /// <summary>\n        /// Initializes a new instance.\n        /// </summary>\n        /// <param name=\"from\">The source of the dependency.</param>\n        /// <param name=\"to\">The target of the dependency.</param>\n        public DependencyRule(DomainSpecification from, DomainSpecification to)\n        {\n            From = from ?? throw new ArgumentNullException(nameof(from));\n            To = to ?? throw new ArgumentNullException(nameof(to));\n        }\n\n        /// <summary>\n        /// Initializes a new instance by converting the string parameters to NamespaceSpecification objects.\n        /// </summary>\n        /// <param name=\"from\">A namespace specification in string format. The source of the dependency.</param>\n        /// <param name=\"to\">A namespace specification in string format. The target of the dependency.</param>\n        public DependencyRule(string from, string to)\n            : this(DomainSpecificationParser.Parse(from), DomainSpecificationParser.Parse(to))\n        { }\n\n        /// <summary>\n        /// Returns the string representation of a namespace dependency.\n        /// </summary>\n        /// <returns>The string representation of a namespace dependency.</returns>\n        public override string ToString()\n        {\n            var builder = new StringBuilder();\n            builder.Append(From);\n            builder.Append(\"->\");\n            builder.Append(To);\n            return builder.ToString();\n        }\n\n        public bool Equals(DependencyRule other)\n        {\n            return Equals(From, other.From) && Equals(To, other.To);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((DependencyRule)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return ((From != null ? From.GetHashCode() : 0) * 397) ^ (To != null ? To.GetHashCode() : 0);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Domain.cs",
    "content": "﻿using System;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Represents a domain, eg. 'A.B'. Immutable.\n    /// </summary>\n    /// <remarks>\n    /// The global domain is also a domain and it's represented by '.' (a dot)\n    /// </remarks>\n    [Serializable]\n    public sealed class Domain : DomainSpecification\n    {\n        public const string RootDomainMarker = \".\";\n\n        /// <summary>\n        /// Represents the global domain.\n        /// </summary>\n        public static readonly Domain GlobalDomain = new Domain(RootDomainMarker);\n\n        /// <summary>\n        /// Creates a new instance from a string representation.\n        /// </summary>\n        /// <param name=\"domainAsString\">The string representation of a domain.</param>\n        /// <param name=\"validate\">True means validate the input string.</param>\n        public Domain(string domainAsString, bool validate = true)\n            : base(Normalize(domainAsString), validate, IsValid)\n        {\n        }\n\n        public override int GetMatchRelevance(Domain domain)\n        {\n            return this == domain\n                ? int.MaxValue\n                : 0;\n        }\n\n        /// <summary>\n        /// Determines whether this domain is a sub-domain of the given other one.\n        /// </summary>\n        /// <param name=\"parentCandidate\">The domain to test whether it's a parent of the current domain.</param>\n        /// <returns>True if this domain is a sub-domain of the given one, false otherwise.</returns>\n        public bool IsSubDomain(Domain parentCandidate)\n        {\n            if (this == GlobalDomain)\n                return false;\n\n            if (parentCandidate == GlobalDomain)\n                return true;\n\n            var parentPrefix = parentCandidate.Value + DomainPartSeparator;\n            return Value.StartsWith(parentPrefix);\n        }\n\n        /// <summary>\n        /// Validates that the given string represents a valid domain specification.\n        /// </summary>\n        /// <param name=\"domainAsString\">A domain specification in string format.</param>\n        /// <returns>True if the given string represents a valid domain specification.</returns>\n        public static bool IsValid(string domainAsString)\n        {\n            if (domainAsString == RootDomainMarker)\n                return true;\n\n            if (domainAsString.Any(c => c == WildcardDomain.AnyDomainMarker[0] || c == WildcardDomain.SingleDomainMarker[0]))\n                return false;\n\n            var pieces = domainAsString.Split(new[] { DomainPartSeparator }, StringSplitOptions.None);\n\n            return pieces.All(i => !string.IsNullOrWhiteSpace(i));\n        }\n\n        /// <summary>\n        /// Converts the input string into a standard representation (removes ambiguities).\n        /// </summary>\n        /// <param name=\"domainAsString\">A domain specification in string format.</param>\n        /// <returns>The standard representation of the given domain specification string.</returns>\n        private static string Normalize(string domainAsString)\n        {\n            // Global domain representations:\n            //   Roslyn: \"<global namespace>\"\n            //   NRefactory: \"\" (empty string)\n            //   NsDepCop: \".\" (dot)\n            if (domainAsString == \"\" ||\n                domainAsString == \"<global namespace>\")\n                domainAsString = RootDomainMarker;\n\n            return domainAsString;\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/DomainSpecification.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Represents a domain or a domain pattern. Immutable.\n    /// </summary>\n    [Serializable]\n    public abstract class DomainSpecification\n    {\n        public const char DomainPartSeparator = '.';\n\n        /// <summary>\n        /// The domain specification stored as a string.\n        /// </summary>\n        protected readonly string Value;\n\n        /// <summary>\n        /// Initializes a new instance. Also validates the input format if needed.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the domain specification.</param>\n        /// <param name=\"validate\">True means validate the input string.</param>\n        /// <param name=\"validator\">A delegate that validates the input string.</param>\n        protected DomainSpecification(string value, bool validate, Func<string, bool> validator)\n        {\n            if (value == null)\n                throw new ArgumentNullException(nameof(value));\n\n            if (validate &&\n                validator != null &&\n                !validator.Invoke(value))\n                throw new FormatException($\"'{value}' is not a valid {GetType().Name}.\");\n\n            Value = value;\n        }\n\n        /// <summary>\n        /// Returns a number indicating how well this domain specification matches a concrete domain.\n        /// </summary>\n        /// <param name=\"domain\">A domain.</param>\n        /// <returns>Zero means no match. Higher value means more relevant match.</returns>\n        public abstract int GetMatchRelevance(Domain domain);\n\n        /// <summary>\n        /// Returns a value indicating whether this domain specification matches a given domain.\n        /// </summary>\n        /// <param name=\"domain\">A domain.</param>\n        /// <returns>True if this domain specification matches the given domain.</returns>\n        public bool Matches(Domain domain) => GetMatchRelevance(domain) > 0;\n\n        public override string ToString() => Value;\n\n        public bool Equals(DomainSpecification other)\n        {\n            if (ReferenceEquals(null, other)) return false;\n            if (ReferenceEquals(this, other)) return true;\n            return String.Equals(Value, other.Value);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((DomainSpecification)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (Value != null ? Value.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(DomainSpecification left, DomainSpecification right)\n        {\n            return Equals(left, right);\n        }\n\n        public static bool operator !=(DomainSpecification left, DomainSpecification right)\n        {\n            return !Equals(left, right);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/DomainSpecificationParser.cs",
    "content": "namespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Converts a string to a domain specification.\n    /// </summary>\n    public static class DomainSpecificationParser\n    {\n        /// <summary>\n        /// Creates a domain specification from a string representation.\n        /// </summary>\n        /// <param name=\"domainSpecificationAsString\">A domain specification in string format.</param>\n        /// <returns>The domain specification created from the given string.</returns>\n        /// <remarks>\n        /// Throws an exception if the string cannot be parsed.\n        /// </remarks>\n        public static DomainSpecification Parse(string domainSpecificationAsString)\n        {\n            if (domainSpecificationAsString.StartsWith(RegexDomain.Delimiter) && domainSpecificationAsString.EndsWith(RegexDomain.Delimiter))\n                return new RegexDomain(domainSpecificationAsString);\n            if (domainSpecificationAsString.Contains(WildcardDomain.SingleDomainMarker) || domainSpecificationAsString.Contains(WildcardDomain.AnyDomainMarker))\n                return new WildcardDomain(domainSpecificationAsString);\n            return new Domain(domainSpecificationAsString);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Factory/ConfigProviderFactory.cs",
    "content": "﻿using Codartis.NsDepCop.Config.Implementation;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Factory\n{\n    /// <summary>\n    /// Creates config provider objects.\n    /// </summary>\n    public class ConfigProviderFactory : IConfigProviderFactory\n    {\n        private readonly MessageHandler _traceMessageHandler;\n\n        public ConfigProviderFactory(MessageHandler traceMessageHandler)\n        {\n            _traceMessageHandler = traceMessageHandler;\n        }\n\n        public IUpdateableConfigProvider CreateFromXmlConfigFile(string configFilePath)\n        {\n            return new XmlFileConfigProvider(configFilePath, _traceMessageHandler);\n        }\n\n        public IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(string folderPath)\n        {\n            return new MultiLevelXmlFileConfigProvider(folderPath, _traceMessageHandler);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/IAnalyzerConfig.cs",
    "content": "using Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// The configuration for an analyzer.\n    /// </summary>\n    public interface IAnalyzerConfig : IDependencyRules, IDiagnosticSupport\n    {\n        /// <summary>\n        /// Gets a value indicating whether analysis is enabled.\n        /// </summary>\n        bool IsEnabled { get; }\n\n        /// <summary>\n        /// Gets the max number of issues reported.\n        /// </summary>\n        int MaxIssueCount { get; }\n\n        /// <summary>\n        /// Gets a value indicating whether MaxIssueCount is automatically updated whenever a lower count is achieved.\n        /// </summary>\n        bool AutoLowerMaxIssueCount { get; }\n\n        /// <summary>\n        /// Gets an array of file path exclusions patterns. Source files that match any of these patterns won't be analyzed.\n        /// </summary>\n        /// <remarks>\n        /// Uses https://github.com/dazinator/DotNet.Glob patterns.\n        /// </remarks>\n        string[] SourcePathExclusionPatterns { get; }\n\n        /// <summary>\n        /// Gets a value indicating whether the assembly dependencies check should be performed.\n        /// </summary>\n        bool CheckAssemblyDependencies { get; }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/IConfigProvider.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Provides config info and config state from some kind of repository.\n    /// </summary>\n    public interface IConfigProvider\n    {\n        /// <summary>\n        /// Gets the config used by the analyzers.\n        /// </summary>\n        IAnalyzerConfig Config { get; }\n\n        /// <summary>\n        /// Gets the state of the analyzer's config.\n        /// </summary>\n        AnalyzerConfigState ConfigState { get; }\n\n        /// <summary>\n        /// Gets the config exception or null if there was no exception.\n        /// </summary>\n        Exception ConfigException { get; }\n\n        /// <summary>\n        /// Gets the config location as a string.\n        /// </summary>\n        string ConfigLocation { get; }\n\n        /// <summary>\n        /// Reloads the config from its repository.\n        /// </summary>\n        void RefreshConfig();\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/IConfigProviderFactory.cs",
    "content": "﻿namespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Creates config provider objects.\n    /// </summary>\n    public interface IConfigProviderFactory\n    {\n        /// <summary>\n        /// Creates a config provider for an xml config file.\n        /// </summary>\n        /// <param name=\"configFilePath\">The full path of an xml config file.</param>\n        /// <returns>A config provider.</returns>\n        IUpdateableConfigProvider CreateFromXmlConfigFile(string configFilePath);\n\n        /// <summary>\n        /// Creates a multi level config provider for the xml config files found in the specified folder and its parents.\n        /// </summary>\n        /// <param name=\"folderPath\">The full path of the folder where the search for config files begins.</param>\n        /// <returns>A config provider.</returns>\n        IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(string folderPath);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/IDependencyRules.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Describes dependency rules.\n    /// </summary>\n    public interface IDependencyRules\n    {\n        /// <summary>\n        /// True means that all child namespaces can depend on any of their parent namespaces without an explicit Allowed rule.\n        /// True is in line with how C# type resolution works: it searches parent namespaces without an explicit using statement.\n        /// False means that all dependencies must be explicitly allowed with a rule.\n        /// False is the default for backward compatibility.\n        /// </summary>\n        bool ChildCanDependOnParentImplicitly { get; }\n        bool ParentCanDependOnChildImplicitly { get; }\n\n        /// <summary>\n        /// Dictionary of allowed dependency rules. The key is a namespace dependency rule, \n        /// the value is a set of type names defined in the target namespace and visible for the source namespace(s).\n        /// </summary>\n        Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }\n\n        /// <summary>\n        /// The set of disallowed dependency rules.\n        /// </summary>\n        HashSet<DependencyRule> DisallowRules { get; }\n\n        /// <summary>\n        /// Dictionary of visible types by target namespace. The key is the name of a namespace, \n        /// the value is a set of type names defined in the namespace and visible outside of the namespace.\n        /// </summary>\n        Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }\n\n        HashSet<DependencyRule> AllowedAssemblyRules { get; }\n\n        HashSet<DependencyRule> DisallowedAssemblyRules { get; }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/IUpdateableConfigProvider.cs",
    "content": "﻿namespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Provides config info and config state. Some config data can also be updated.\n    /// </summary>\n    public interface IUpdateableConfigProvider: IConfigProvider\n    {\n        /// <summary>\n        /// Updates the MaxIssueCount config parameter to the given value and persists the changes.\n        /// </summary>\n        /// <param name=\"newValue\">The new value for MaxIssueCount.</param>\n        void UpdateMaxIssueCount(int newValue);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfig.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Describes the config for a dependency analyzer. Immutable.\n    /// </summary>\n    [Serializable]\n    internal class AnalyzerConfig : IAnalyzerConfig\n    {\n        public bool IsEnabled { get; }\n        public string[] SourcePathExclusionPatterns { get; }\n        public bool CheckAssemblyDependencies { get; }\n        public bool ChildCanDependOnParentImplicitly { get; }\n        public bool ParentCanDependOnChildImplicitly { get; }\n        public Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }\n        public HashSet<DependencyRule> DisallowRules { get; }\n        public Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }\n        public HashSet<DependencyRule> AllowedAssemblyRules { get; }\n        public HashSet<DependencyRule> DisallowedAssemblyRules { get; }\n        public int MaxIssueCount { get; }\n        public bool AutoLowerMaxIssueCount { get; }\n\n        public AnalyzerConfig(\n            bool isEnabled,\n            string[] sourcePathExclusionPatterns,\n            bool checkAssemblyDependencies,\n            bool childCanDependOnParentImplicitly,\n            bool parentCanDependOnChildImplicitly,\n            Dictionary<DependencyRule, TypeNameSet> allowRules,\n            HashSet<DependencyRule> disallowRules,\n            Dictionary<Domain, TypeNameSet> visibleTypesByNamespace,\n            HashSet<DependencyRule> allowedAssemblyRules,\n            HashSet<DependencyRule> disallowedAssemblyRules,\n            int maxIssueCount,\n            bool autoLowerMaxIssueCount)\n        {\n            IsEnabled = isEnabled;\n            SourcePathExclusionPatterns = sourcePathExclusionPatterns;\n            CheckAssemblyDependencies = checkAssemblyDependencies;\n\n            ChildCanDependOnParentImplicitly = childCanDependOnParentImplicitly;\n            ParentCanDependOnChildImplicitly = parentCanDependOnChildImplicitly;\n            AllowRules = allowRules;\n            DisallowRules = disallowRules;\n            VisibleTypesByNamespace = visibleTypesByNamespace;\n            AllowedAssemblyRules = allowedAssemblyRules;\n            DisallowedAssemblyRules = disallowedAssemblyRules;\n            MaxIssueCount = maxIssueCount;\n            AutoLowerMaxIssueCount = autoLowerMaxIssueCount;\n        }\n\n        public IEnumerable<string> ToStrings()\n        {\n            yield return $\"IsEnabled={IsEnabled}\";\n            yield return $\"SourcePathExclusionPatterns={string.Join(\",\", SourcePathExclusionPatterns)}\";\n            yield return $\"ChildCanDependOnParentImplicitly={ChildCanDependOnParentImplicitly}\";\n            foreach (var s in AllowRules.ToStrings()) yield return s;\n            foreach (var s in DisallowRules.ToStrings()) yield return s;\n            foreach (var s in AllowedAssemblyRules.ToStrings()) yield return s;\n            foreach (var s in DisallowedAssemblyRules.ToStrings()) yield return s;\n            foreach (var s in VisibleTypesByNamespace.ToStrings()) yield return s;\n            yield return $\"MaxIssueCount={MaxIssueCount}\";\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfigBuilder.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Builds analyzer config objects.\n    /// </summary>\n    public class AnalyzerConfigBuilder\n    {\n        public int? InheritanceDepth { get; private set; }\n        public bool? IsEnabled { get; private set; }\n        public List<string> SourcePathExclusionPatterns { get; private set; }\n        public bool? CheckAssemblyDependencies { get; private set; }\n        public bool? ChildCanDependOnParentImplicitly { get; private set; }\n        public bool? ParentCanDependOnChildImplicitly { get; private set; }\n        public Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }\n        public HashSet<DependencyRule> DisallowRules { get; }\n        public Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }\n        public HashSet<DependencyRule> AllowedAssemblyRules { get; }\n        public HashSet<DependencyRule> DisallowedAssemblyRules { get; }\n        public int? MaxIssueCount { get; private set; }\n        public bool? AutoLowerMaxIssueCount { get; private set; }\n\n        public AnalyzerConfigBuilder()\n        {\n            SourcePathExclusionPatterns = new List<string>();\n            AllowRules = new Dictionary<DependencyRule, TypeNameSet>();\n            DisallowRules = new HashSet<DependencyRule>();\n            VisibleTypesByNamespace = new Dictionary<Domain, TypeNameSet>();\n            AllowedAssemblyRules = new HashSet<DependencyRule>();\n            DisallowedAssemblyRules = new HashSet<DependencyRule>();\n        }\n\n        public IAnalyzerConfig ToAnalyzerConfig()\n        {\n            return new AnalyzerConfig(\n                IsEnabled ?? ConfigDefaults.IsEnabled,\n                SourcePathExclusionPatterns.ToArray(),\n                CheckAssemblyDependencies ?? ConfigDefaults.CheckAssemblyDependencies,\n                ChildCanDependOnParentImplicitly ?? ConfigDefaults.ChildCanDependOnParentImplicitly,\n                ParentCanDependOnChildImplicitly ?? ConfigDefaults.ParentCanDependOnChildImplicitly,\n                AllowRules,\n                DisallowRules,\n                VisibleTypesByNamespace,\n                AllowedAssemblyRules,\n                DisallowedAssemblyRules,\n                MaxIssueCount ?? ConfigDefaults.MaxIssueCount,\n                AutoLowerMaxIssueCount ?? ConfigDefaults.AutoLowerMaxIssueCount\n            );\n        }\n\n        public AnalyzerConfigBuilder Combine(AnalyzerConfigBuilder analyzerConfigBuilder)\n        {\n            // Note that InheritanceDepth is not combined.\n\n            SetIsEnabled(analyzerConfigBuilder.IsEnabled);\n            AddSourcePathExclusionPatterns(analyzerConfigBuilder.SourcePathExclusionPatterns);\n            SetCheckAssemblyDependencies(analyzerConfigBuilder.CheckAssemblyDependencies);\n            SetChildCanDependOnParentImplicitly(analyzerConfigBuilder.ChildCanDependOnParentImplicitly);\n            SetParentCanDependOnChildImplicitly(analyzerConfigBuilder.ParentCanDependOnChildImplicitly);\n            AddAllowRules(analyzerConfigBuilder.AllowRules);\n            AddDisallowRules(analyzerConfigBuilder.DisallowRules);\n            AddVisibleTypesByNamespace(analyzerConfigBuilder.VisibleTypesByNamespace);\n            AddAllowedAssemblyRules(analyzerConfigBuilder.AllowedAssemblyRules);\n            AddDisallowedAssemblyRules(analyzerConfigBuilder.DisallowedAssemblyRules);\n            SetMaxIssueCount(analyzerConfigBuilder.MaxIssueCount);\n            SetAutoLowerMaxIssueCount(analyzerConfigBuilder.AutoLowerMaxIssueCount);\n\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetInheritanceDepth(int? inheritanceDepth)\n        {\n            if (inheritanceDepth.HasValue)\n                InheritanceDepth = inheritanceDepth;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetIsEnabled(bool? isEnabled)\n        {\n            if (isEnabled.HasValue)\n                IsEnabled = isEnabled;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddSourcePathExclusionPatterns(IEnumerable<string> sourcePathExclusionPatterns)\n        {\n            if (sourcePathExclusionPatterns != null)\n                SourcePathExclusionPatterns.AddRange(sourcePathExclusionPatterns);\n\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetCheckAssemblyDependencies(bool? checkAssemblyDependencies)\n        {\n            if (checkAssemblyDependencies.HasValue)\n                CheckAssemblyDependencies = checkAssemblyDependencies;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder MakePathsRooted(string rootPath)\n        {\n            if (!Path.IsPathRooted(rootPath))\n                throw new ArgumentException($\"Rooted path expected: {rootPath}\");\n\n            SourcePathExclusionPatterns = SourcePathExclusionPatterns.Select(i => ToRootedPath(rootPath, i)).ToList();\n\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetChildCanDependOnParentImplicitly(bool? childCanDependOnParentImplicitly)\n        {\n            if (childCanDependOnParentImplicitly.HasValue)\n                ChildCanDependOnParentImplicitly = childCanDependOnParentImplicitly;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetParentCanDependOnChildImplicitly(bool? parentCanDependOnChildImplicitly)\n        {\n            if (parentCanDependOnChildImplicitly.HasValue)\n                ParentCanDependOnChildImplicitly = parentCanDependOnChildImplicitly;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddAllowRule(DependencyRule dependencyRule, TypeNameSet typeNameSet = null)\n        {\n            AllowRules.AddOrUnion<DependencyRule, TypeNameSet, string>(dependencyRule, typeNameSet);\n            return this;\n        }\n\n        private AnalyzerConfigBuilder AddAllowRules(IEnumerable<KeyValuePair<DependencyRule, TypeNameSet>> allowRules)\n        {\n            foreach (var keyValuePair in allowRules)\n                AddAllowRule(keyValuePair.Key, keyValuePair.Value);\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddDisallowRule(DependencyRule dependencyRule)\n        {\n            DisallowRules.Add(dependencyRule);\n            return this;\n        }\n\n        private AnalyzerConfigBuilder AddDisallowRules(IEnumerable<DependencyRule> disallowRules)\n        {\n            foreach (var dependencyRule in disallowRules)\n                AddDisallowRule(dependencyRule);\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddAllowedAssemblyRule(DependencyRule assemblyDependencyRule)\n        {\n            AllowedAssemblyRules.Add(assemblyDependencyRule);\n            return this;\n        }\n\n        private AnalyzerConfigBuilder AddAllowedAssemblyRules(IEnumerable<DependencyRule> assemblyDependencyRules)\n        {\n            foreach (var assemblyDependencyRule in assemblyDependencyRules)\n                AddAllowedAssemblyRule(assemblyDependencyRule);\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddDisallowedAssemblyRule(DependencyRule assemblyDependencyRule)\n        {\n            DisallowedAssemblyRules.Add(assemblyDependencyRule);\n            return this;\n        }\n\n        private AnalyzerConfigBuilder AddDisallowedAssemblyRules(IEnumerable<DependencyRule> assemblyDependencyRules)\n        {\n            foreach (var assemblyDependencyRule in assemblyDependencyRules)\n                AddDisallowedAssemblyRule(assemblyDependencyRule);\n            return this;\n        }\n\n        public AnalyzerConfigBuilder AddVisibleTypesByNamespace(Domain domain, TypeNameSet typeNameSet)\n        {\n            VisibleTypesByNamespace.AddOrUnion<Domain, TypeNameSet, string>(domain, typeNameSet);\n            return this;\n        }\n\n        private AnalyzerConfigBuilder AddVisibleTypesByNamespace(IEnumerable<KeyValuePair<Domain, TypeNameSet>> visibleTypesByNamespace)\n        {\n            foreach (var keyValuePair in visibleTypesByNamespace)\n                AddVisibleTypesByNamespace(keyValuePair.Key, keyValuePair.Value);\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetMaxIssueCount(int? maxIssueCount)\n        {\n            if (maxIssueCount.HasValue)\n                MaxIssueCount = maxIssueCount;\n            return this;\n        }\n\n        public AnalyzerConfigBuilder SetAutoLowerMaxIssueCount(bool? autoLowerMaxIssueCount)\n        {\n            if (autoLowerMaxIssueCount.HasValue)\n                AutoLowerMaxIssueCount = autoLowerMaxIssueCount;\n            return this;\n        }\n\n        public IEnumerable<string> ToStrings()\n        {\n            if (InheritanceDepth.HasValue) yield return $\"InheritanceDepth={InheritanceDepth}\";\n            if (IsEnabled.HasValue) yield return $\"IsEnabled={IsEnabled}\";\n            if (SourcePathExclusionPatterns != null) yield return $\"SourcePathExclusionPatterns={string.Join(\";\", SourcePathExclusionPatterns)}\";\n            if (CheckAssemblyDependencies.HasValue) yield return $\"CheckAssemblyDependencies={CheckAssemblyDependencies}\";\n            if (ChildCanDependOnParentImplicitly.HasValue) yield return $\"ChildCanDependOnParentImplicitly={ChildCanDependOnParentImplicitly}\";\n            if (ParentCanDependOnChildImplicitly.HasValue) yield return $\"ParentCanDependOnChildImplicitly={ParentCanDependOnChildImplicitly}\";\n            if (AllowRules.Any())\n                foreach (var s in AllowRules.ToStrings())\n                    yield return s;\n            if (DisallowRules.Any())\n                foreach (var s in DisallowRules.ToStrings())\n                    yield return s;\n            if (AllowedAssemblyRules.Any())\n                foreach (var s in AllowedAssemblyRules.ToStrings())\n                    yield return s;\n            if (DisallowedAssemblyRules.Any())\n                foreach (var s in DisallowedAssemblyRules.ToStrings())\n                    yield return s;\n            if (VisibleTypesByNamespace.Any())\n                foreach (var s in VisibleTypesByNamespace.ToStrings())\n                    yield return s;\n            if (MaxIssueCount.HasValue) yield return $\"MaxIssueCount={MaxIssueCount}\";\n        }\n\n        private static string ToRootedPath(string rootPath, string path)\n        {\n            if (rootPath == null || Path.IsPathRooted(path))\n                return path;\n\n            return Path.Combine(rootPath, path);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/ConfigLoadResult.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Describes the result of a config load operation.\n    /// </summary>\n    public readonly struct ConfigLoadResult \n    {\n        public AnalyzerConfigState ConfigState { get; }\n        public AnalyzerConfigBuilder ConfigBuilder { get; }\n        public IAnalyzerConfig Config { get; }\n        public Exception ConfigException { get; }\n\n        private ConfigLoadResult(AnalyzerConfigState configState, AnalyzerConfigBuilder configBuilder, \n           IAnalyzerConfig config, Exception configException)\n        {\n            ConfigState = configState;\n            ConfigBuilder = configBuilder;\n            Config = config;\n            ConfigException = configException;\n        }\n\n        public static ConfigLoadResult CreateWithError(Exception configException)\n        {\n            if (configException == null)\n                throw new ArgumentNullException(nameof(configException));\n\n            return new ConfigLoadResult(AnalyzerConfigState.ConfigError, null, null, configException);\n        }\n\n        public static ConfigLoadResult CreateWithNoConfig()\n        {\n            return new ConfigLoadResult(AnalyzerConfigState.NoConfig, null, null, null);\n        }\n\n        public static ConfigLoadResult CreateWithConfig(AnalyzerConfigBuilder configBuilder)\n        {\n            if (configBuilder == null)\n                throw new ArgumentNullException(nameof(configBuilder));\n\n            var config = configBuilder.ToAnalyzerConfig();\n            return config.IsEnabled \n                ? new ConfigLoadResult(AnalyzerConfigState.Enabled, configBuilder, config, null) \n                : new ConfigLoadResult(AnalyzerConfigState.Disabled, null, null, null);\n        }\n\n        public IEnumerable<string> ToStrings()\n        {\n            yield return $\"ConfigState={ConfigState}\";\n            if (ConfigException != null) yield return $\"ConfigException={ConfigException}\";\n            if (Config != null) foreach (var s in Config.ToStrings()) yield return s;\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/ConfigProviderBase.cs",
    "content": "﻿using System;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Abstract base class for config provider implementations.\n    /// </summary>\n    /// <remarks>\n    /// Uses locking to ensure that no property can be read while refreshing the config.\n    /// </remarks>\n    public abstract class ConfigProviderBase : IUpdateableConfigProvider\n    {\n        private bool _isInitialized;\n        private ConfigLoadResult _configLoadResult;\n\n        /// <summary>\n        /// This lock ensures that no property can be read while loading or saving the config.\n        /// </summary>\n        protected readonly object SaveLoadLockObject = new();\n\n        protected MessageHandler TraceMessageHandler { get; }\n\n        protected ConfigProviderBase(MessageHandler traceMessageHandler)\n        {\n            TraceMessageHandler = traceMessageHandler;\n        }\n\n        public abstract string ConfigLocation { get; }\n\n        public IAnalyzerConfig Config\n        {\n            get\n            {\n                lock (SaveLoadLockObject)\n                {\n                    EnsureInitialized();\n                    return _configLoadResult.Config;\n                }\n            }\n        }\n\n        public AnalyzerConfigBuilder ConfigBuilder\n        {\n            get\n            {\n                lock (SaveLoadLockObject)\n                {\n                    EnsureInitialized();\n                    return _configLoadResult.ConfigBuilder;\n                }\n            }\n        }\n\n        public AnalyzerConfigState ConfigState\n        {\n            get\n            {\n                lock (SaveLoadLockObject)\n                {\n                    EnsureInitialized();\n                    return _configLoadResult.ConfigState;\n                }\n            }\n        }\n\n        public Exception ConfigException\n        {\n            get\n            {\n                lock (SaveLoadLockObject)\n                {\n                    EnsureInitialized();\n                    return _configLoadResult.ConfigException;\n                }\n            }\n        }\n\n        public void RefreshConfig()\n        {\n            lock (SaveLoadLockObject)\n            {\n                EnsureInitialized();\n                _configLoadResult = RefreshConfigCore();\n            }\n        }\n\n        public void UpdateMaxIssueCount(int newValue)\n        {\n            lock (SaveLoadLockObject)\n            {\n                EnsureInitialized();\n\n                if (_configLoadResult.ConfigState != AnalyzerConfigState.Enabled)\n                    throw new InvalidOperationException($\"Cannot {nameof(UpdateMaxIssueCount)} in {_configLoadResult.ConfigState} state.\");\n\n                _configLoadResult = UpdateMaxIssueCountCore(newValue);\n            }\n        }\n\n        protected abstract ConfigLoadResult LoadConfigCore();\n        protected abstract ConfigLoadResult RefreshConfigCore();\n        protected abstract ConfigLoadResult UpdateMaxIssueCountCore(int newValue);\n\n        protected void EnsureInitialized()\n        {\n            lock (SaveLoadLockObject)\n            {\n                if (_isInitialized)\n                    return;\n\n                _isInitialized = true;\n                _configLoadResult = LoadConfigCore();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/FileConfigProviderBase.cs",
    "content": "﻿using System;\nusing System.IO;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Abstract base class for file based config implementations.\n    /// Reloads only if the file changed.\n    /// </summary>\n    /// <remarks>\n    /// Base class ensures that all operations are executed in an atomic way so no extra locking needed.\n    /// </remarks>\n    public abstract class FileConfigProviderBase : ConfigProviderBase\n    {\n        private bool _configFileExists;\n        private DateTime _configLastLoadUtc;\n        private ConfigLoadResult _lastConfigLoadResult;\n\n        protected string ConfigFilePath { get; }\n\n        protected FileConfigProviderBase(string configFilePath, MessageHandler traceMessageHandler)\n            : base(traceMessageHandler)\n        {\n            ConfigFilePath = configFilePath;\n        }\n\n        public override string ConfigLocation => ConfigFilePath;\n\n        public int InheritanceDepth => ConfigBuilder?.InheritanceDepth ?? ConfigDefaults.InheritanceDepth;\n\n        public bool HasConfigFileChanged()\n        {\n            return ConfigFileCreatedOrDeleted()\n                || ConfigFileModifiedSinceLastLoad();\n        }\n\n        protected override ConfigLoadResult LoadConfigCore()\n        {\n            _lastConfigLoadResult = LoadConfigFromFile();\n            return _lastConfigLoadResult;\n        }\n\n        protected override ConfigLoadResult RefreshConfigCore()\n        {\n            if (!HasConfigFileChanged())\n                return _lastConfigLoadResult;\n\n            LogTraceMessage($\"Refreshing config {this}.\");\n            return LoadConfigCore();\n        }\n\n        private ConfigLoadResult LoadConfigFromFile()\n        {\n            try\n            {\n                _configFileExists = File.Exists(ConfigFilePath);\n                if (!_configFileExists)\n                    return ConfigLoadResult.CreateWithNoConfig();\n\n                _configLastLoadUtc = DateTime.UtcNow;\n\n                var configBuilder = CreateConfigBuilderFromFile(ConfigFilePath)\n                     .MakePathsRooted(Path.GetDirectoryName(ConfigFilePath));\n\n                return ConfigLoadResult.CreateWithConfig(configBuilder);\n            }\n            catch (Exception e)\n            {\n                LogTraceMessage($\"BuildConfig exception: {e}\");\n                return ConfigLoadResult.CreateWithError(e);\n            }\n        }\n\n        protected abstract AnalyzerConfigBuilder CreateConfigBuilderFromFile(string configFilePath);\n\n        private bool ConfigFileCreatedOrDeleted()\n        {\n            return _configFileExists != File.Exists(ConfigFilePath);\n        }\n\n        private bool ConfigFileModifiedSinceLastLoad()\n        {\n            return File.Exists(ConfigFilePath)\n                && _configLastLoadUtc < File.GetLastWriteTimeUtc(ConfigFilePath);\n        }\n\n        private void LogTraceMessage(string message) => TraceMessageHandler?.Invoke(message);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/MultiLevelXmlFileConfigProvider.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Traverses the source tree and reads one or multiple config files to create a composite config.\n    /// Starts from the specified folder and traverses the folder tree upwards till the root or the max inheritance level is reached.\n    /// </summary>\n    /// <remarks>\n    /// Base class ensures that all operations are executed in an atomic way so no extra locking needed.\n    /// </remarks>\n    public sealed class MultiLevelXmlFileConfigProvider : ConfigProviderBase\n    {\n        private ConfigLoadResult _lastConfigLoadResult;\n        private int _lastInheritanceDepth;\n\n        /// <summary>\n        /// The collection of all file config providers that must be composed to a single config.\n        /// </summary>\n        /// <remarks>\n        /// The list is sorted from the project folder's config to increasingly farther configs in the folder tree.\n        /// The configs must be combined in reverse order (from the farthest to the closest).\n        /// </remarks>\n        private List<XmlFileConfigProvider> _fileConfigProviders;\n\n        private string ProjectFolder { get; }\n\n        public MultiLevelXmlFileConfigProvider(string projectFolder, MessageHandler traceMessageHandler)\n            : base(traceMessageHandler)\n        {\n            ProjectFolder = projectFolder;\n        }\n\n        public override string ConfigLocation => ProjectFolder;\n\n        public int InheritanceDepth\n        {\n            get\n            {\n                lock (SaveLoadLockObject)\n                {\n                    EnsureInitialized();\n                    return _fileConfigProviders.First().InheritanceDepth;\n                }\n            }\n        }\n\n        public override string ToString() => $\"MultiLevelXmlConfig:'{ProjectFolder}'\";\n\n        protected override ConfigLoadResult LoadConfigCore()\n        {\n            LogTraceMessage($\"Loading config {this}\");\n\n            var projectLevelConfigProvider = new XmlFileConfigProvider(GetConfigFilePath(ProjectFolder), TraceMessageHandler);\n\n            _fileConfigProviders = CreateFileConfigProviderList(projectLevelConfigProvider, ProjectFolder);\n\n            return CombineFileConfigProvidersAndSaveResult();\n        }\n\n        protected override ConfigLoadResult RefreshConfigCore()\n        {\n            if (!AnyChildConfigChanged())\n                return _lastConfigLoadResult;\n\n            LogTraceMessage($\"Refreshing config {this}.\");\n\n            var projectLevelConfigProvider = _fileConfigProviders[0];\n            projectLevelConfigProvider.RefreshConfig();\n\n            if (InheritanceDepth != _lastInheritanceDepth)\n            {\n                _fileConfigProviders = CreateFileConfigProviderList(projectLevelConfigProvider, ProjectFolder);\n            }\n            else\n            {\n                foreach (var configProvider in _fileConfigProviders.Skip(1))\n                    configProvider.RefreshConfig();\n            }\n\n            return CombineFileConfigProvidersAndSaveResult();\n        }\n\n        protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)\n        {\n            _fileConfigProviders.First().UpdateMaxIssueCount(newValue);\n\n            return CombineFileConfigProvidersAndSaveResult();\n        }\n\n        private ConfigLoadResult CombineFileConfigProvidersAndSaveResult()\n        {\n            _lastInheritanceDepth = InheritanceDepth;\n            _lastConfigLoadResult = CombineFileConfigProviders();\n\n            LogTraceMessage(IndentHelper.Indent(\"Effective config:\", 1).Concat(IndentHelper.Indent(_lastConfigLoadResult.ToStrings(), 2)));\n\n            return _lastConfigLoadResult;\n        }\n\n        private ConfigLoadResult CombineFileConfigProviders()\n        {\n            var configBuilder = CreateAnalyzerConfigBuilder();\n\n            var anyConfigFound = false;\n            foreach (var childConfigProvider in Enumerable.Reverse(_fileConfigProviders))\n            {\n                var childConfigState = childConfigProvider.ConfigState;\n\n                LogTraceMessage(IndentHelper.Indent($\"Combining {childConfigProvider}, state={childConfigState}\", 1));\n\n                switch (childConfigState)\n                {\n                    case AnalyzerConfigState.NoConfig:\n                        break;\n\n                    case AnalyzerConfigState.Disabled:\n                        anyConfigFound = true;\n                        configBuilder.SetIsEnabled(false);\n                        break;\n\n                    case AnalyzerConfigState.Enabled:\n                        anyConfigFound = true;\n\n                        var childConfigBuilder = childConfigProvider.ConfigBuilder;\n                        configBuilder.Combine(childConfigBuilder);\n                        LogTraceMessage(IndentHelper.Indent(childConfigBuilder.ToStrings(), 2));\n                        break;\n\n                    case AnalyzerConfigState.ConfigError:\n                        return ConfigLoadResult.CreateWithError(childConfigProvider.ConfigException);\n\n                    default:\n                        throw new ArgumentOutOfRangeException(nameof(childConfigState), childConfigState, \"Unexpected value.\");\n                }\n            }\n\n            return anyConfigFound\n                ? ConfigLoadResult.CreateWithConfig(configBuilder)\n                : ConfigLoadResult.CreateWithNoConfig();\n        }\n\n        private static AnalyzerConfigBuilder CreateAnalyzerConfigBuilder() => new();\n\n        private bool AnyChildConfigChanged() => _fileConfigProviders.Any(i => i.HasConfigFileChanged());\n\n        private List<XmlFileConfigProvider> CreateFileConfigProviderList(XmlFileConfigProvider firstConfigProvider, string startFolderPath)\n        {\n            var fileConfigProviders = new List<XmlFileConfigProvider> { firstConfigProvider };\n\n            LogTraceMessage(IndentHelper.Indent($\"InheritanceDepth={firstConfigProvider.InheritanceDepth}\", 1));\n\n            var currentFolder = startFolderPath;\n            for (var i = 0; i < firstConfigProvider.InheritanceDepth; i++)\n            {\n                currentFolder = Directory.GetParent(currentFolder)?.FullName;\n                if (string.IsNullOrWhiteSpace(currentFolder))\n                    break;\n\n                var higherLevelConfigProvider = new XmlFileConfigProvider(GetConfigFilePath(currentFolder), TraceMessageHandler);\n                fileConfigProviders.Add(higherLevelConfigProvider);\n            }\n\n            return fileConfigProviders;\n        }\n\n        private static string GetConfigFilePath(string folderPath) => Path.Combine(folderPath, ProductConstants.DefaultConfigFileName);\n\n        private void LogTraceMessage(IEnumerable<string> messages)\n        {\n            foreach (var message in messages)\n                LogTraceMessage(message);\n        }\n\n        private void LogTraceMessage(string message) => TraceMessageHandler?.Invoke(message);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/RuleConfigToStringsFormatter.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Static helper class for formatting rule config data into strings.\n    /// </summary>\n    public static class RuleConfigToStringsFormatter\n    {\n        public static IEnumerable<string> ToStrings(this IDictionary<DependencyRule, TypeNameSet> allowRules)\n        {\n            yield return $\"AllowRules={allowRules.Count}\";\n            foreach (var allowRule in allowRules)\n                yield return $\"  {allowRule.Key}, {allowRule.Value?.ToString() ?? \"{}\"}\";\n        }\n\n        public static IEnumerable<string> ToStrings(this ISet<DependencyRule> disallowRules)\n        {\n            yield return $\"DisallowRules={disallowRules.Count}\";\n            foreach (var disallowRule in disallowRules)\n                yield return $\"  {disallowRule}\";\n        }\n\n        public static IEnumerable<string> ToStrings(this IDictionary<Domain, TypeNameSet> visibleTypesByNamespaces)\n        {\n            yield return $\"VisibleTypesByNamespace={visibleTypesByNamespaces.Count}\";\n            foreach (var visibleTypesByNamespace in visibleTypesByNamespaces)\n                yield return $\"  {visibleTypesByNamespace.Key}, {visibleTypesByNamespace.Value?.ToString() ?? \"{}\"}\";\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/XmlConfigParser.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Xml;\nusing System.Xml.Linq;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Parses a config provided in XML format.\n    /// </summary>\n    public static class XmlConfigParser\n    {\n        private const string RootElementName = \"NsDepCopConfig\";\n        private const string InheritanceDepthAttributeName = \"InheritanceDepth\";\n        private const string IsEnabledAttributeName = \"IsEnabled\";\n        private const string MaxIssueCountAttributeName = \"MaxIssueCount\";\n        private const string AutoLowerMaxIssueCountAttributeName = \"AutoLowerMaxIssueCount\";\n        private const string ImplicitParentDependencyAttributeName = \"ChildCanDependOnParentImplicitly\";\n        private const string ImplicitChildDependencyAttributeName = \"ParentCanDependOnChildImplicitly\";\n        private const string SourcePathExclusionPatternsAttributeName = \"ExcludedFiles\";\n        private const string CheckAssemblyDependenciesAttributeName = \"CheckAssemblyDependencies\";\n        private const string AllowedElementName = \"Allowed\";\n        private const string DisallowedElementName = \"Disallowed\";\n        private const string AllowedAssemblyElementName = \"AllowedAssembly\";\n        private const string DisallowedAssemblyElementName = \"DisallowedAssembly\";\n        private const string VisibleMembersElementName = \"VisibleMembers\";\n        private const string TypeElementName = \"Type\";\n        private const string OfNamespaceAttributeName = \"OfNamespace\";\n        private const string FromAttributeName = \"From\";\n        private const string ToAttributeName = \"To\";\n        private const string TypeNameAttributeName = \"Name\";\n\n        public static AnalyzerConfigBuilder Parse(XDocument configXml)\n        {\n            var configBuilder = new AnalyzerConfigBuilder();\n\n            var rootElement = GetRootElement(configXml);\n            ParseRootNodeAttributes(rootElement, configBuilder);\n            ParseChildElements(rootElement, configBuilder);\n\n            return configBuilder;\n        }\n\n        public static void UpdateMaxIssueCount(XDocument configXml, int newValue)\n        {\n            var rootElement = GetRootElement(configXml);\n\n            AddOrUpdateAttribute(rootElement, MaxIssueCountAttributeName, newValue.ToString());\n        }\n\n        private static XElement GetRootElement(XDocument configXml)\n        {\n            var rootElement = configXml.Element(RootElementName);\n            if (rootElement == null)\n                throw new Exception($\"'{RootElementName}' root element not found.\");\n            return rootElement;\n        }\n\n        private static void ParseRootNodeAttributes(XElement rootElement, AnalyzerConfigBuilder configBuilder)\n        {\n            configBuilder.SetIsEnabled(ParseValueType<bool>(rootElement, IsEnabledAttributeName, bool.TryParse));\n            configBuilder.SetInheritanceDepth(ParseValueType<int>(rootElement, InheritanceDepthAttributeName, int.TryParse));\n            configBuilder.AddSourcePathExclusionPatterns(ParseStringList(rootElement, SourcePathExclusionPatternsAttributeName, ','));\n            configBuilder.SetCheckAssemblyDependencies(ParseValueType<bool>(rootElement, CheckAssemblyDependenciesAttributeName, bool.TryParse));\n            configBuilder.SetChildCanDependOnParentImplicitly(ParseValueType<bool>(rootElement, ImplicitParentDependencyAttributeName, bool.TryParse));\n            configBuilder.SetParentCanDependOnChildImplicitly(ParseValueType<bool>(rootElement, ImplicitChildDependencyAttributeName, bool.TryParse));\n            configBuilder.SetMaxIssueCount(ParseValueType<int>(rootElement, MaxIssueCountAttributeName, int.TryParse));\n            configBuilder.SetAutoLowerMaxIssueCount(ParseValueType<bool>(rootElement, AutoLowerMaxIssueCountAttributeName, bool.TryParse));\n        }\n\n        private static IEnumerable<string> ParseStringList(XElement element, string attributeName, char separatorChar)\n        {\n            var attribute = element.Attribute(attributeName);\n            var parts = Split(attribute?.Value, separatorChar);\n            return parts?.ToList();\n        }\n\n        private static IEnumerable<string> Split(string s, char separatorChar)\n        {\n            return s?.Split(new[] { separatorChar }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim());\n        }\n\n        private static void ParseChildElements(XElement rootElement, AnalyzerConfigBuilder configBuilder)\n        {\n            foreach (var xElement in rootElement.Elements())\n            {\n                switch (xElement.Name.ToString())\n                {\n                    case AllowedElementName:\n                        ParseAllowedElement(xElement, configBuilder);\n                        break;\n                    case DisallowedElementName:\n                        ParseDisallowedElement(xElement, configBuilder);\n                        break;\n                    case AllowedAssemblyElementName:\n                        ParseAllowedAssemblyElement(xElement, configBuilder);\n                        break;\n                    case DisallowedAssemblyElementName:\n                        ParseDisallowedAssemblyElement(xElement, configBuilder);\n                        break;\n                    case VisibleMembersElementName:\n                        ParseVisibleMembersElement(xElement, configBuilder);\n                        break;\n                    default:\n                        Trace.WriteLine($\"Unexpected element '{xElement.Name}' ignored.\");\n                        break;\n                }\n            }\n        }\n\n        private static void ParseAllowedElement(XElement element, AnalyzerConfigBuilder configBuilder)\n        {\n            var allowedDependencyRule = ParseDependencyRule(element);\n\n            var visibleTypeNames = ParseVisibleMembersInsideAllowedRule(element, allowedDependencyRule);\n            if (visibleTypeNames.IsNullOrEmpty())\n                visibleTypeNames = null;\n\n            configBuilder.AddAllowRule(allowedDependencyRule, visibleTypeNames);\n        }\n\n        private static void ParseDisallowedElement(XElement element, AnalyzerConfigBuilder configBuilder)\n        {\n            var disallowedDependencyRule = ParseDependencyRule(element);\n\n            configBuilder.AddDisallowRule(disallowedDependencyRule);\n        }\n\n        private static void ParseAllowedAssemblyElement(XElement element, AnalyzerConfigBuilder configBuilder)\n        {\n            var allowedAssemblyDependencyRule = ParseAssemblyDependencyRule(element);\n\n            configBuilder.AddAllowedAssemblyRule(allowedAssemblyDependencyRule);\n        }\n\n        private static void ParseDisallowedAssemblyElement(XElement element, AnalyzerConfigBuilder configBuilder)\n        {\n            var disallowedAssemblyDependencyRule = ParseAssemblyDependencyRule(element);\n\n            configBuilder.AddDisallowedAssemblyRule(disallowedAssemblyDependencyRule);\n        }\n\n        private static TypeNameSet ParseVisibleMembersInsideAllowedRule(XElement element, DependencyRule allowedRule)\n        {\n            var visibleMembersChild = element.Element(VisibleMembersElementName);\n            if (visibleMembersChild == null)\n                return null;\n\n            if (allowedRule.To is not Domain)\n                throw new Exception($\"{GetLineInfo(element)}The target namespace '{allowedRule.To}' must be a single namespace.\");\n\n            if (visibleMembersChild.Attribute(OfNamespaceAttributeName) != null)\n                throw new Exception(\n                    $\"{GetLineInfo(element)}If {VisibleMembersElementName} is embedded in a dependency specification then '{OfNamespaceAttributeName}' attribute must not be defined.\");\n\n            return ParseTypeNameSet(visibleMembersChild, TypeElementName);\n        }\n\n        private static void ParseVisibleMembersElement(XElement element, AnalyzerConfigBuilder configBuilder)\n        {\n            var targetNamespaceName = GetAttributeValue(element, OfNamespaceAttributeName);\n            if (targetNamespaceName == null)\n                throw new Exception($\"{GetLineInfo(element)}'{OfNamespaceAttributeName}' attribute missing.\");\n\n            var targetNamespace = TryAndReportError(element, () => new Domain(targetNamespaceName.Trim()));\n\n            var visibleTypeNames = ParseTypeNameSet(element, TypeElementName);\n            if (!visibleTypeNames.Any())\n                return;\n\n            configBuilder.AddVisibleTypesByNamespace(targetNamespace, visibleTypeNames);\n        }\n\n        private static DependencyRule ParseDependencyRule(XElement element)\n        {\n            var fromValue = GetAttributeValue(element, FromAttributeName);\n            if (fromValue == null)\n                throw new Exception($\"{GetLineInfo(element)}'{FromAttributeName}' attribute missing.\");\n\n            var toValue = GetAttributeValue(element, ToAttributeName);\n            if (toValue == null)\n                throw new Exception($\"{GetLineInfo(element)}'{ToAttributeName}' attribute missing.\");\n\n            var from = TryAndReportError(element, () => DomainSpecificationParser.Parse(fromValue.Trim()));\n            var to = TryAndReportError(element, () => DomainSpecificationParser.Parse(toValue.Trim()));\n\n            return new DependencyRule(from, to);\n        }\n\n        private static DependencyRule ParseAssemblyDependencyRule(XElement element)\n        {\n            var fromValue = GetAttributeValue(element, FromAttributeName);\n            if (fromValue == null)\n                throw new Exception($\"{GetLineInfo(element)}'{FromAttributeName}' attribute missing.\");\n\n            var toValue = GetAttributeValue(element, ToAttributeName);\n            if (toValue == null)\n                throw new Exception($\"{GetLineInfo(element)}'{ToAttributeName}' attribute missing.\");\n\n            var from = TryAndReportError(element, () => DomainSpecificationParser.Parse(fromValue.Trim()));\n            var to = TryAndReportError(element, () => DomainSpecificationParser.Parse(toValue.Trim()));\n\n            return new DependencyRule(from, to);\n        }\n\n        private static T TryAndReportError<T>(XObject xObject, Func<T> parserDelegate)\n        {\n            try\n            {\n                return parserDelegate();\n            }\n            catch (Exception e)\n            {\n                throw new Exception($\"{GetLineInfo(xObject)}{e.Message}\", e);\n            }\n        }\n\n        private static TypeNameSet ParseTypeNameSet(XElement element, string childElementName)\n        {\n            var typeNameSet = new TypeNameSet();\n\n            foreach (var xElement in element.Elements(childElementName))\n            {\n                var typeName = GetAttributeValue(xElement, TypeNameAttributeName);\n                if (typeName == null)\n                    throw new Exception($\"{GetLineInfo(xElement)}'{TypeNameAttributeName}' attribute missing.\");\n\n                if (!string.IsNullOrWhiteSpace(typeName))\n                    typeNameSet.Add(typeName.Trim());\n            }\n\n            return typeNameSet;\n        }\n\n        /// <summary>\n        /// Returns an attribute's value, or null if the attribute was not found.\n        /// </summary>\n        /// <param name=\"element\">The parent element of the attribute.</param>\n        /// <param name=\"attributeName\">The name of the attribute.</param>\n        /// <returns>The value of the attribute or null if the attribute was not found.</returns>\n        private static string GetAttributeValue(XElement element, string attributeName)\n        {\n            return element.Attribute(attributeName)?.Value;\n        }\n\n        private static void AddOrUpdateAttribute(XElement element, string attributeName, string newValue)\n        {\n            var attribute = element.Attribute(attributeName);\n\n            if (attribute == null)\n                element.Add(new XAttribute(attributeName, newValue));\n            else\n                attribute.Value = newValue;\n        }\n\n        /// <summary>\n        /// Defines the signature of a TryParse-like method, that is used to parse a value of T from string.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the parse result.</typeparam>\n        /// <param name=\"s\">The string that must be parsed.</param>\n        /// <param name=\"t\">The successfully parsed value.</param>\n        /// <returns>True if successfully parsed, false otherwise.</returns>\n        private delegate bool TryParseMethod<T>(string s, out T t);\n\n        private static T? ParseValueType<T>(XElement element, string attributeName, TryParseMethod<T> tryParseMethod)\n            where T : struct\n        {\n            var attribute = element.Attribute(attributeName);\n            if (attribute == null)\n                return null;\n\n            if (tryParseMethod(attribute.Value, out var parseResult))\n                return parseResult;\n\n            throw new FormatException($\"{GetLineInfo(element)}Error parsing '{attribute.Name}' value '{attribute.Value}'.\");\n        }\n\n        private static string GetLineInfo(XObject xObject)\n        {\n            var xmlLineInfo = xObject as IXmlLineInfo;\n\n            return xmlLineInfo.HasLineInfo()\n                ? $\"[Line: {xmlLineInfo.LineNumber}, Pos: {xmlLineInfo.LinePosition}] \"\n                : string.Empty;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/Implementation/XmlFileConfigProvider.cs",
    "content": "﻿using System.Xml.Linq;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n    /// <summary>\n    /// Extracts config information from an xml config file.\n    /// </summary>\n    /// <remarks>\n    /// Base class handles config load errors so no need to catch exceptions here.\n    /// </remarks>\n    public sealed class XmlFileConfigProvider : FileConfigProviderBase\n    {\n        private XDocument _configXDocument;\n\n        public XmlFileConfigProvider(string configFilePath, MessageHandler traceMessageHandler)\n            : base(configFilePath, traceMessageHandler)\n        {\n        }\n\n        public override string ToString() => $\"XmlConfig:'{ConfigFilePath}'\";\n\n        protected override AnalyzerConfigBuilder CreateConfigBuilderFromFile(string configFilePath)\n        {\n            _configXDocument = XDocument.Load(configFilePath, LoadOptions.SetLineInfo);\n            return XmlConfigParser.Parse(_configXDocument);\n        }\n\n        protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)\n        {\n            XmlConfigParser.UpdateMaxIssueCount(_configXDocument, newValue);\n            _configXDocument.Save(ConfigFilePath);\n\n            return LoadConfigCore();\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/RegexCompilationMode.cs",
    "content": "namespace Codartis.NsDepCop.Config;\n\npublic enum RegexCompilationMode\n{\n    Compiled,\n    Interpreted\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/RegexDomain.cs",
    "content": "using System;\nusing System.Text.RegularExpressions;\n\nnamespace Codartis.NsDepCop.Config;\n\n/// <summary>\n/// Represents a domain specification with a regular expression pattern.\n/// The given pattern must follow the dotnet regex specification found at:\n/// https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference\n/// </summary>\n/// <remarks>\n/// This class provides functionality to define a domain using a regular expression\n/// and supports validation and matching of other domains against the specified pattern.\n/// </remarks>\n[Serializable]\npublic sealed class RegexDomain : DomainSpecification\n{\n    public const string Delimiter = \"/\";\n\n    private static readonly TimeSpan DefaultRegexTimeout = TimeSpan.FromMilliseconds(100);\n\n    private readonly Regex _regex;\n    private readonly RegexOptions _regexOptions;\n    private readonly TimeSpan _regexTimeout;\n\n    public RegexDomain(\n        string value,\n        bool validate = true,\n        RegexUsageMode regexUsageMode = RegexUsageMode.Instance,\n        RegexCompilationMode regexCompilationMode = RegexCompilationMode.Interpreted,\n        TimeSpan? regexTimeout = null)\n        : base(value, validate, IsValid)\n    {\n        _regexTimeout = regexTimeout ?? DefaultRegexTimeout;\n        _regexOptions = RegexOptions.Singleline;\n\n        if (regexCompilationMode == RegexCompilationMode.Compiled)\n            _regexOptions |= RegexOptions.Compiled;\n\n        if (regexUsageMode == RegexUsageMode.Instance)\n            _regex = new Regex(Normalize(Value), _regexOptions, _regexTimeout);\n    }\n\n    public override int GetMatchRelevance(Domain domain)\n    {\n        try\n        {\n            if (_regex != null)\n                return _regex.IsMatch(domain.ToString()) ? 1 : 0;\n\n            return Regex.IsMatch(domain.ToString(), Normalize(Value), _regexOptions, _regexTimeout) ? 1 : 0;\n        }\n        catch (RegexMatchTimeoutException)\n        {\n            return 0;\n        }\n    }\n\n    private static bool IsValid(string domainAsString)\n    {\n        if (!domainAsString.StartsWith(Delimiter, StringComparison.Ordinal)\n            || !domainAsString.EndsWith(Delimiter, StringComparison.Ordinal))\n        {\n            return false;\n        }\n\n        var normalizedDomainAsString = Normalize(domainAsString);\n        if (string.IsNullOrWhiteSpace(normalizedDomainAsString))\n            return false;\n\n        try\n        {\n            _ = new Regex(normalizedDomainAsString);\n            return true;\n        }\n        catch (ArgumentException)\n        {\n            return false;\n        }\n    }\n\n    private static string Normalize(string domainAsString)\n        => domainAsString.Trim(Delimiter.ToCharArray());\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/RegexUsageMode.cs",
    "content": "namespace Codartis.NsDepCop.Config;\n\npublic enum RegexUsageMode\n{\n    Static,\n    Instance\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/TypeNameSet.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.Serialization;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// A set of type names represented as strings (without namespace part).\n    /// </summary>\n    [Serializable]\n    public class TypeNameSet : HashSet<string>\n    {\n        public TypeNameSet()\n        {\n        }\n\n        public TypeNameSet(IEnumerable<string> collection)\n            : base(collection)\n        {\n        }\n\n        protected TypeNameSet(SerializationInfo info, StreamingContext context) \n            : base(info, context)\n        {\n        }\n\n        public override string ToString() => this.Any() ? $\"{{{string.Join(\",\", this)}}}\" : \"{}\";\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Config/WildcardDomain.cs",
    "content": "﻿using System;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Config\n{\n    /// <summary>\n    /// Represents a domain specification with wildcards, eg. 'System.IO.*' or 'System.?.?.Generic'.\n    /// Each '?' can be replaced with exactly one domain component when matching against a domain.\n    /// Each '*' can be replaced with any number of domain components.\n    /// <br/>\n    /// This class is immutable.\n    /// </summary>\n    /// <remarks>\n    /// The 'any domain' (represented by a star '*') is also a domain that contains every domain.\n    /// </remarks>\n    [Serializable]\n    public sealed class WildcardDomain : DomainSpecification\n    {\n        private readonly string[] _domainComponents;\n        public const string SingleDomainMarker = \"?\";\n        public const string AnyDomainMarker = \"*\";\n\n        /// <summary>\n        /// Creates a new instance from a string representation.\n        /// </summary>\n        /// <param name=\"wildcardDomainAsString\">The string representation of a domain pattern containing wildcards.</param>\n        /// <param name=\"validate\">True means validate the input string.</param>\n        public WildcardDomain(string wildcardDomainAsString, bool validate = true)\n            : base(wildcardDomainAsString, validate, IsValid)\n        {\n            _domainComponents = wildcardDomainAsString.Split(DomainPartSeparator);\n        }\n\n        /// <inheritdoc />\n        public override int GetMatchRelevance(Domain domain)\n        {\n            var actualList = domain.ToString().Split(DomainPartSeparator);\n\n            var distance = CalcDistance(actualList, _domainComponents, 0);\n\n            return int.MaxValue - distance;\n        }\n\n        /// <summary>\n        /// Returns a boolean value indication if the given <paramref name=\"domainAsString\"/> is a valid <see cref=\"WildcardDomain\"/>.\n        /// </summary>\n        /// <param name=\"domainAsString\">The domain string to check.</param>\n        /// <returns>True, if and only if the <paramref name=\"domainAsString\"/> is valid.</returns>\n        public static bool IsValid(string domainAsString)\n        {\n            var parts = domainAsString.Split(DomainPartSeparator);\n\n            bool validChars = parts.All(s =>\n                !string.IsNullOrWhiteSpace(s)\n                && (s is SingleDomainMarker or AnyDomainMarker || (!s.Contains(SingleDomainMarker) && !s.Contains(AnyDomainMarker)))\n                );\n            bool anyWildcard = parts.Any(s => s is SingleDomainMarker or AnyDomainMarker);\n            bool notAdjacentTrees = parts.Length > 0 && parts.Zip(parts.Skip(1), (a, b) => (a, b)).All(p => p.a != AnyDomainMarker || p.b != AnyDomainMarker);\n\n            return validChars && anyWildcard && notAdjacentTrees;\n        }\n\n        /// <summary>\n        /// Calculates the edit distance between <paramref name=\"remainingPattern\"/> and <paramref name=\"remainingActual\"/>.\n        /// <br/>\n        /// The edit distance is calculated as the sum of all edit operations which are needed to replace the wildcards with\n        /// the domain names. The costs are as follows:\n        /// <ul>\n        /// <li>* Replacing a `?` has a cost of 1.</li>\n        /// <li>* Replacing a `*` has a cost of 1 and additionally a cost of 1 per sub-domain that replaces the `*`.</li>\n        /// </ul>\n        /// </summary>\n        /// <param name=\"remainingActual\">A span of nested domain names to match.</param>\n        /// <param name=\"remainingPattern\">A span of nested domain names or wildcards to match with.</param>\n        /// <param name=\"actualDistance\">The edit cost of the parent domain.</param>\n        /// <returns>\n        /// The sum of actualDistance and the edit distance between <paramref name=\"remainingActual\"/> and <paramref name=\"remainingPattern\"/>.\n        /// </returns>\n        private static int CalcDistance(ReadOnlySpan<string> remainingActual, ReadOnlySpan<string> remainingPattern, int actualDistance)\n        {\n            if (remainingPattern.IsEmpty)\n            {\n                if (remainingActual.IsEmpty)\n                {\n                    // completely matched\n                    return actualDistance;\n                }\n\n                // no match, as the pattern is exhausted\n                return int.MaxValue;\n            }\n\n            if (remainingActual.IsEmpty)\n            {\n                if (remainingPattern.Length == 1 && remainingPattern[0] is AnyDomainMarker)\n                {\n                    // removing the trailing star costs one point\n                    return actualDistance + 1;\n                }\n\n                // no match, as no more input can be matched against the pattern\n                return int.MaxValue;\n            }\n\n            System.Diagnostics.Debug.Assert(!remainingActual.IsEmpty && !remainingPattern.IsEmpty);\n            switch (remainingPattern[0])\n            {\n                case SingleDomainMarker:\n                    {\n                        // replace single wildcard at cost 1\n                        return CalcDistance(remainingActual.Slice(1), remainingPattern.Slice(1), actualDistance + 1);\n                    }\n\n                case AnyDomainMarker:\n                    {\n                        // try both options: (This moves the algorithm to complexity class O(NM).)\n                        // remove wildcard\n                        int v1 = CalcDistance(remainingActual, remainingPattern.Slice(1), actualDistance + 1);\n\n                        // use wildcard to substitute one domain component\n                        int v2 = CalcDistance(remainingActual.Slice(1), remainingPattern, actualDistance + 1);\n\n                        return Math.Min(v1, v2);\n                    }\n\n                default:\n                    {\n                        if (remainingPattern[0] == remainingActual[0])\n                        {\n                            // full match\n                            return CalcDistance(remainingActual.Slice(1), remainingPattern.Slice(1), actualDistance);\n                        }\n\n                        // no match\n                        return int.MaxValue;\n                    }\n\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/GlobalSettings.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop\n{\n    public static class GlobalSettings\n    {\n        public static bool IsToolDisabled()\n        {\n            var environmentVariableValue = Environment.GetEnvironmentVariable(ProductConstants.DisableToolEnvironmentVariableName);\n\n            return environmentVariableValue == \"1\" ||\n                   string.Equals(environmentVariableValue, \"true\", StringComparison.OrdinalIgnoreCase);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <RootNamespace>Codartis.NsDepCop</RootNamespace>\n    <IsPackable>false</IsPackable>\n    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n    <LangVersion>latest</LangVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <AdditionalFiles Include=\"config.nsdepcop\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Include\\CommonAssemblyInfo.cs\" Link=\"Properties\\CommonAssemblyInfo.cs\" />\n    <Compile Include=\"..\\Include\\VersionInfo.cs\" Link=\"Properties\\VersionInfo.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"DotNet.Glob\" Version=\"2.1.1\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"3.9.0\" />\n    <PackageReference Include=\"NsDepCop\" Version=\"2.7.0\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/ISyntaxNodeAnalyzer.cs",
    "content": "using System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.ParserAdapter.Roslyn\n{\n    /// <summary>\n    /// Analyzer logic for a single syntax node.\n    /// </summary>\n    public interface ISyntaxNodeAnalyzer\n    {\n        /// <summary>\n        /// Returns type dependencies for a syntax node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the current document.</param>\n        /// <returns>A list of type dependencies. Can be empty.</returns>\n        IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node, SemanticModel semanticModel);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp.Syntax;\n\nnamespace Codartis.NsDepCop.ParserAdapter.Roslyn\n{\n    /// <summary>\n    /// Enumerates type dependencies for a syntax node using Roslyn 1.x.\n    /// </summary>\n    public class SyntaxNodeAnalyzer : ISyntaxNodeAnalyzer\n    {\n        /// <summary>\n        /// The list of those type kinds that can occur as a declaration.\n        /// </summary>\n        private static readonly List<TypeKind> DeclarationTypeKinds = new()\n        {\n            TypeKind.Class,\n            TypeKind.Delegate,\n            TypeKind.Enum,\n            TypeKind.Interface,\n            TypeKind.Struct,\n        };\n\n        /// <summary>\n        /// Returns type dependencies for a syntax node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the current document.</param>\n        /// <returns>A list of type dependencies. Can be empty.</returns>\n        public IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node, SemanticModel semanticModel)\n        {\n            // Determine the type that contains the current syntax node.\n            var enclosingType = DetermineEnclosingType(node, semanticModel);\n            if (!IsAnalyzableDeclarationType(enclosingType))\n                yield break;\n\n            // Determine the type referenced by the symbol represented by the current syntax node.\n            var referencedType = DetermineReferencedType(node, semanticModel);\n            foreach (var type in GetConstituentTypes(referencedType, node))\n                yield return CreateTypeDependency(enclosingType, type, node);\n\n            // If this is an extension method invocation then determine the type declaring the extension method.\n            var declaringType = DetermineExtensionOrStaticMethodDeclaringType(node, semanticModel);\n            if (IsAnalyzableDeclarationType(declaringType))\n                yield return CreateTypeDependency(enclosingType, declaringType, node);\n        }\n\n        private static bool IsAnalyzableDeclarationType(ITypeSymbol typeSymbol)\n        {\n            return typeSymbol?.ContainingNamespace != null\n                   && !typeSymbol.IsAnonymousType\n                   && DeclarationTypeKinds.Contains(typeSymbol.TypeKind)\n                   && !string.IsNullOrWhiteSpace(typeSymbol.MetadataName);\n        }\n\n        protected virtual IEnumerable<ITypeSymbol> GetConstituentTypes(ITypeSymbol typeSymbol, SyntaxNode syntaxNode)\n        {\n            if (typeSymbol == null ||\n                typeSymbol.IsAnonymousType)\n                yield break;\n\n            var typeKind = typeSymbol.TypeKind;\n            switch (typeKind)\n            {\n                case TypeKind.Array:\n                    var arrayTypeSymbol = (IArrayTypeSymbol) typeSymbol;\n                    foreach (var type in GetConstituentTypes(arrayTypeSymbol.ElementType, syntaxNode))\n                        yield return type;\n                    break;\n\n                case TypeKind.Pointer:\n                    var pointerTypeSymbol = (IPointerTypeSymbol) typeSymbol;\n                    foreach (var type in GetConstituentTypes(pointerTypeSymbol.PointedAtType, syntaxNode))\n                        yield return type;\n                    break;\n\n                case TypeKind.Class:\n                case TypeKind.Delegate:\n                case TypeKind.Enum:\n                case TypeKind.Interface:\n                case TypeKind.Struct:\n                    var namedTypeSymbol = typeSymbol as INamedTypeSymbol;\n                    if (namedTypeSymbol == null)\n                        yield break;\n\n                    if (namedTypeSymbol.IsGenericType)\n                    {\n                        yield return namedTypeSymbol.ConstructedFrom;\n\n                        // If the syntax node has any identifier descendants then those will trigger analysis for the type arguments\n                        // so there's no need to recurse into the type arguments here.\n                        if (syntaxNode.HasDescendant<IdentifierNameSyntax>())\n                            yield break;\n\n                        foreach (var typeArgument in namedTypeSymbol.TypeArguments)\n                        foreach (var type in GetConstituentTypes(typeArgument, syntaxNode))\n                            yield return type;\n                    }\n                    else\n                    {\n                        yield return namedTypeSymbol;\n                    }\n\n                    break;\n\n                case TypeKind.Dynamic:\n                case TypeKind.Error:\n                case TypeKind.Module:\n                case TypeKind.Unknown:\n                case TypeKind.Submission:\n                case TypeKind.TypeParameter:\n                    yield break;\n\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(typeKind), typeKind, \"Unexpected value.\");\n            }\n        }\n\n        /// <summary>\n        /// Returns a type dependency object for the given types.\n        /// </summary>\n        /// <param name=\"fromType\">The referring type.</param>\n        /// <param name=\"toType\">The referenced type.</param>\n        /// <param name=\"node\">The syntax node currently analyzed.</param>\n        /// <returns>A type dependency object.</returns>\n        private static TypeDependency CreateTypeDependency(ITypeSymbol fromType, ITypeSymbol toType, SyntaxNode node)\n        {\n            return new TypeDependency(\n                fromType.ContainingNamespace.ToDisplayString(), fromType.MetadataName,\n                toType.ContainingNamespace.ToDisplayString(), toType.MetadataName,\n                GetSourceSegment(node));\n        }\n\n        /// <summary>\n        /// Determines the type declaring the given extension method syntax node or\n        /// the declaring type of a static method when the type is statically imported.\n        /// e.g. <code>\n        /// using static A.ClassA;\n        /// StaticMethodOfClassA(); // in contrast to A.ClassA.StaticMethodOfClassA();\n        /// </code>\n        /// </summary>\n        /// <param name=\"node\">A syntax node representing a static or extension method.</param>\n        /// <param name=\"semanticModel\">The semantic model of the project.</param>\n        /// <returns>The type declaring the given static or extension method syntax node, or null if not found.</returns>\n        private static ITypeSymbol DetermineExtensionOrStaticMethodDeclaringType(SyntaxNode node, SemanticModel semanticModel)\n        {\n            var methodSymbol = semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol;\n\n            bool isExtensionMethodOrCallOnStaticImport =\n                methodSymbol != null\n                && (methodSymbol.IsExtensionMethod\n                    || (methodSymbol.IsStatic && node.Parent is not MemberAccessExpressionSyntax));\n\n            return isExtensionMethodOrCallOnStaticImport ? methodSymbol.ContainingType : null;\n        }\n\n        /// <summary>\n        /// Determines the type referenced by the given syntax node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the project.</param>\n        /// <returns>The type referenced by the given syntax node, or null if no type was referenced.</returns>\n        protected virtual ITypeSymbol DetermineReferencedType(SyntaxNode node, SemanticModel semanticModel)\n        {\n            var typeSymbol = semanticModel.GetTypeInfo(node).Type;\n            if (typeSymbol != null && typeSymbol.TypeKind != TypeKind.Error)\n                return typeSymbol;\n\n            // Special case: deconstructing declaration with var outside, e.g.: var (d, e) = Method2();\n            if (node.Parent is DeclarationExpressionSyntax &&\n                node.Parent.ChildNodes().Any(i => i is ParenthesizedVariableDesignationSyntax))\n                return DetermineReferencedType(node.Parent, semanticModel);\n\n            // In same cases GetTypeInfo(node).Type does not return the desired type symbol but GetSymbolInfo(node).Symbol does.\n            // E.g.: IdentifierNameSyntax inside an ObjectCreationExpression\n            var symbolInfo = semanticModel.GetSymbolInfo(node);\n            if (symbolInfo.Symbol is ITypeSymbol symbolInfoTypeSymbol)\n                return symbolInfoTypeSymbol;\n\n            // Special case: for method invocations we should check the return type\n            if (symbolInfo.Symbol is IMethodSymbol methodSymbol)\n                return methodSymbol.ReturnType;\n\n            // Could not determine referenced type.\n            return null;\n        }\n\n        /// <summary>\n        /// Determines the type that contains the given syntax node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        /// <param name=\"semanticModel\">The semantic model of the project.</param>\n        /// <returns>The type that contains the given syntax node. Or null if can't determine.</returns>\n        private static ITypeSymbol DetermineEnclosingType(SyntaxNode node, SemanticModel semanticModel)\n        {\n            // Find the type declaration that contains the current syntax node.\n            var typeDeclarationSyntaxNode = node.Ancestors().FirstOrDefault(i => i.IsTypeDeclaration() || i is CompilationUnitSyntax);\n            if (typeDeclarationSyntaxNode == null)\n                return null;\n\n            if (typeDeclarationSyntaxNode is CompilationUnitSyntax)\n            {\n                return semanticModel.GetDeclaredSymbol(typeDeclarationSyntaxNode)?.ContainingType;\n            }\n\n            // Determine the type of the type declaration that contains the current syntax node.\n            return semanticModel.GetDeclaredSymbol(typeDeclarationSyntaxNode) as ITypeSymbol;\n        }\n\n        /// <summary>\n        /// Gets the source segment of the given syntax node.\n        /// </summary>\n        /// <param name=\"syntaxNode\">A syntax node.</param>\n        /// <returns>The source segment of the given syntax node.</returns>\n        private static SourceSegment GetSourceSegment(SyntaxNode syntaxNode)\n        {\n            var lineSpan = syntaxNode.GetLocation().GetLineSpan();\n\n            return new SourceSegment\n            (\n                lineSpan.StartLinePosition.Line + 1,\n                lineSpan.StartLinePosition.Character + 1,\n                lineSpan.EndLinePosition.Line + 1,\n                lineSpan.EndLinePosition.Character + 1,\n                syntaxNode.ToString(),\n                lineSpan.Path\n            );\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeExtensions.cs",
    "content": "﻿using System;\nusing System.Linq;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp.Syntax;\n\nnamespace Codartis.NsDepCop.ParserAdapter.Roslyn\n{\n    public static class SyntaxNodeExtensions\n    {\n        public static bool IsTypeDeclaration(this SyntaxNode syntaxNode)\n        {\n            return syntaxNode is BaseTypeDeclarationSyntax \n                || syntaxNode is DelegateDeclarationSyntax;\n        }\n\n        public static bool HasDescendant<T>(this SyntaxNode syntaxNode)\n            where T : SyntaxNode\n        {\n            if (syntaxNode == null)\n                throw new ArgumentNullException(nameof(syntaxNode));\n\n            return syntaxNode.ChildNodes().Any(i => i.IsOrHasDescendant<T>());\n        }\n\n        public static bool IsOrHasDescendant<T>(this SyntaxNode syntaxNode)\n            where T : SyntaxNode\n        {\n            if (syntaxNode == null)\n                return false;\n\n            if (syntaxNode.GetType() == typeof(T))\n                return true;\n\n            return syntaxNode.ChildNodes().Any(i => i.IsOrHasDescendant<T>());\n        }\n\n        public static bool HasParent<T>(this SyntaxNode syntaxNode)\n            where T : SyntaxNode\n        {\n            var parent = syntaxNode.Parent;\n            if (parent == null)\n                return false;\n\n            if (parent.GetType() == typeof(T))\n                return true;\n\n            return parent.HasParent<T>();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumerator.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Util;\nusing DotNet.Globbing;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace Codartis.NsDepCop.ParserAdapter.Roslyn\n{\n    /// <summary>\n    /// Implements a type dependency enumerators that use Roslyn as the parser.\n    /// </summary>\n    public class TypeDependencyEnumerator : ITypeDependencyEnumerator\n    {\n        private static readonly CSharpParseOptions ParseOptions = new(LanguageVersion.Latest);\n\n        private readonly ISyntaxNodeAnalyzer _syntaxNodeAnalyzer;\n        private readonly MessageHandler _traceMessageHandler;\n\n        public TypeDependencyEnumerator(ISyntaxNodeAnalyzer syntaxNodeAnalyzer, MessageHandler traceMessageHandler)\n        {\n            _syntaxNodeAnalyzer = syntaxNodeAnalyzer ?? throw new ArgumentNullException(nameof(syntaxNodeAnalyzer));\n            _traceMessageHandler = traceMessageHandler;\n        }\n\n        private static TypeDependencyEnumeratorSyntaxVisitor CreateSyntaxVisitor(\n            SemanticModel semanticModel,\n            ISyntaxNodeAnalyzer syntaxNodeAnalyzer)\n        {\n            return new(semanticModel, syntaxNodeAnalyzer);\n        }\n\n        public IEnumerable<TypeDependency> GetTypeDependencies(\n            IEnumerable<string> sourceFilePaths,\n            IEnumerable<string> referencedAssemblyPaths,\n            IEnumerable<Glob> sourcePathExclusionGlobs)\n        {\n            var referencedAssemblies = referencedAssemblyPaths.Select(LoadMetadata).Where(i => i != null).ToList();\n            var syntaxTrees = sourceFilePaths.Select(ParseFile).Where(i => i != null).ToList();\n\n            var compilation = CSharpCompilation.Create(\"NsDepCopProject\", syntaxTrees, referencedAssemblies,\n                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true));\n\n            return syntaxTrees.Where(i => !IsExcludedFilePath(i.FilePath, sourcePathExclusionGlobs))\n                .SelectMany(i => GetTypeDependenciesForSyntaxTree(compilation, i, _syntaxNodeAnalyzer));\n        }\n\n        private static bool IsExcludedFilePath(string filePath, IEnumerable<Glob> sourcePathExclusionGlobs)\n        {\n            return sourcePathExclusionGlobs.Any(i => i.IsMatch(filePath));\n        }\n\n        private static IEnumerable<TypeDependency> GetTypeDependenciesForSyntaxTree(\n            Compilation compilation,\n            SyntaxTree syntaxTree,\n            ISyntaxNodeAnalyzer syntaxNodeAnalyzer)\n        {\n            var documentRootNode = syntaxTree.GetRoot();\n            var semanticModel = compilation.GetSemanticModel(syntaxTree);\n            var syntaxVisitor = CreateSyntaxVisitor(semanticModel, syntaxNodeAnalyzer);\n            syntaxVisitor.Visit(documentRootNode);\n            return syntaxVisitor.TypeDependencies;\n        }\n\n        public IEnumerable<TypeDependency> GetTypeDependencies(\n            SyntaxNode syntaxNode,\n            SemanticModel semanticModel,\n            IEnumerable<Glob> sourcePathExclusionGlobs)\n        {\n            return IsExcludedFilePath(syntaxNode?.SyntaxTree.FilePath, sourcePathExclusionGlobs)\n                ? Enumerable.Empty<TypeDependency>()\n                : _syntaxNodeAnalyzer.GetTypeDependencies(syntaxNode, semanticModel);\n        }\n\n  \n        private MetadataReference LoadMetadata(string fileName)\n        {\n            try\n            {\n                return MetadataReference.CreateFromFile(fileName);\n            }\n            catch (Exception e)\n            {\n                LogTraceMessage($\"Error loading metadata file '{fileName}': {e}\");\n                return null;\n            }\n        }\n\n        private SyntaxTree ParseFile(string fileName)\n        {\n            try\n            {\n                using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))\n                using (var streamReader = new StreamReader(stream))\n                {\n                    var sourceText = streamReader.ReadToEnd();\n                    return CSharpSyntaxTree.ParseText(sourceText, ParseOptions, fileName);\n                }\n            }\n            catch (Exception e)\n            {\n                LogTraceMessage($\"Error parsing source file '{fileName}': {e}\");\n                return null;\n            }\n        }\n\n        private void LogTraceMessage(string message) => _traceMessageHandler?.Invoke(message);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumeratorSyntaxVisitor.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing Microsoft.CodeAnalysis.CSharp.Syntax;\n\nnamespace Codartis.NsDepCop.ParserAdapter.Roslyn\n{\n    /// <summary>\n    /// Implements a syntax visitor that traverses the syntax tree and finds all type dependencies. \n    /// </summary>\n    /// <remarks>\n    /// WARNING: when adding a new SyntaxNode type to the visitor,\n    /// also add it to NsDepCopDiagnosticAnalyzerBase.GetSyntaxKindsToRegister\n    /// </remarks>\n    public class TypeDependencyEnumeratorSyntaxVisitor : CSharpSyntaxVisitor\n    {\n        /// <summary>\n        /// The semantic model of the current document.\n        /// </summary>\n        private readonly SemanticModel _semanticModel;\n\n        /// <summary>\n        /// Implements the analysis logic for a single syntax node.\n        /// </summary>\n        private readonly ISyntaxNodeAnalyzer _syntaxNodeAnalyzer;\n\n        /// <summary>\n        /// The collection of type dependencies that the syntax visitor found.\n        /// </summary>\n        private readonly List<TypeDependency> _typeDependencies;\n\n        /// <summary>\n        /// Initializes a new instance.\n        /// </summary>\n        /// <param name=\"semanticModel\">The semantic model for the document.</param>\n        /// <param name=\"syntaxNodeAnalyzer\">Syntax node analyzer logic.</param>\n        public TypeDependencyEnumeratorSyntaxVisitor(SemanticModel semanticModel, ISyntaxNodeAnalyzer syntaxNodeAnalyzer)\n        {\n            _semanticModel = semanticModel ?? throw new ArgumentNullException(nameof(semanticModel));\n            _syntaxNodeAnalyzer = syntaxNodeAnalyzer ?? throw new ArgumentNullException(nameof(syntaxNodeAnalyzer));\n\n            _typeDependencies = new List<TypeDependency>();\n        }\n\n        public IEnumerable<TypeDependency> TypeDependencies => _typeDependencies;\n\n        /// <summary>\n        /// Visits all child nodes of a given node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        public override void DefaultVisit(SyntaxNode node)\n        {\n            foreach (var childNode in node.ChildNodes())\n                Visit(childNode);\n        }\n\n        public override void VisitIdentifierName(IdentifierNameSyntax node)\n        {\n            AnalyzeNode(node);\n            // No need to call DefaultVisit, because it cannot have such child nodes that need to be checked.\n        }\n\n        public override void VisitGenericName(GenericNameSyntax node)\n        {\n            AnalyzeNode(node);\n            DefaultVisit(node);\n        }\n\n        public override void VisitLiteralExpression(LiteralExpressionSyntax node)\n        {\n            if (node.Kind() == SyntaxKind.DefaultLiteralExpression)\n                AnalyzeNode(node);\n        }\n\n        /// <summary>\n        /// Collects type dependencies for a given syntax node.\n        /// </summary>\n        /// <param name=\"node\">A syntax node.</param>\n        private void AnalyzeNode(SyntaxNode node)\n        {\n            var typeDependencies = _syntaxNodeAnalyzer.GetTypeDependencies(node, _semanticModel);\n            _typeDependencies.AddRange(typeDependencies);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/ProductConstants.cs",
    "content": "﻿using System.Reflection;\n\nnamespace Codartis.NsDepCop\n{\n    /// <summary>\n    /// Product-wide constant values.\n    /// </summary>\n    public static class ProductConstants\n    {\n        public const string ToolName = \"NsDepCop\";\n        public const string DefaultConfigFileName = \"config.nsdepcop\";\n        public const string DisableToolEnvironmentVariableName = \"DisableNsDepCop\";\n\n        public static readonly string Version = $\"{Assembly.GetExecutingAssembly().GetName().Version}\";\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\n\n[assembly: AssemblyTitle(\"NsDepCop.Analyzer\")]\n[assembly: AssemblyDescription(\"Static code analysis tool for enforcing namespace-based type dependency rules in C# projects.\")]\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/RoslynAnalyzer/AnalyzerProvider.cs",
    "content": "using System;\nusing System.Collections.Concurrent;\nusing System.IO;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n    /// <summary>\n    /// Creates and stores dependency analyzers for C# projects.\n    /// Ensures that the analyzers' configs are always refreshed.\n    /// </summary>\n    public sealed class AnalyzerProvider : IAnalyzerProvider\n    {\n        private readonly IDependencyAnalyzerFactory _dependencyAnalyzerFactory;\n        private readonly IAssemblyDependencyAnalyzerFactory _assemblyDependencyAnalyzerFactory;\n        private readonly IConfigProviderFactory _configProviderFactory;\n        private readonly ITypeDependencyEnumerator _typeDependencyEnumerator;\n\n        /// <summary>\n        /// Maps project files to their corresponding dependency analyzer. The key is the project file name with full path.\n        /// </summary>\n        private readonly ConcurrentDictionary<string, IDependencyAnalyzer> _projectFileToDependencyAnalyzerMap = new();\n        private readonly ConcurrentDictionary<string, IAssemblyDependencyAnalyzer> _projectFileToAssemblyDependencyAnalyzerMap = new();\n\n        public AnalyzerProvider(\n            IDependencyAnalyzerFactory dependencyAnalyzerFactory,\n            IAssemblyDependencyAnalyzerFactory assemblyDependencyAnalyzerFactory,\n            IConfigProviderFactory configProviderFactory,\n            ITypeDependencyEnumerator typeDependencyEnumerator)\n        {\n            _dependencyAnalyzerFactory = dependencyAnalyzerFactory ?? throw new ArgumentNullException(nameof(dependencyAnalyzerFactory));\n            _assemblyDependencyAnalyzerFactory = assemblyDependencyAnalyzerFactory ?? throw new ArgumentNullException(nameof(assemblyDependencyAnalyzerFactory));\n            _configProviderFactory = configProviderFactory ?? throw new ArgumentNullException(nameof(configProviderFactory));\n            _typeDependencyEnumerator = typeDependencyEnumerator ?? throw new ArgumentNullException(nameof(typeDependencyEnumerator));\n        }\n\n        public IDependencyAnalyzer GetDependencyAnalyzer(string csprojFilePath)\n        {\n            if (string.IsNullOrWhiteSpace(csprojFilePath))\n                throw new ArgumentException(\"Filename must not be null or whitespace.\", nameof(csprojFilePath));\n\n            var dependencyAnalyzer = _projectFileToDependencyAnalyzerMap.GetOrAdd(csprojFilePath, CreateDependencyAnalyzer, out var added);\n\n            if (!added)\n                dependencyAnalyzer.RefreshConfig();\n\n            return dependencyAnalyzer;\n        }\n\n        private IDependencyAnalyzer CreateDependencyAnalyzer(string projectFilePath)\n        {\n            var projectFileDirectory = Path.GetDirectoryName(projectFilePath);\n            var configProvider = _configProviderFactory.CreateFromMultiLevelXmlConfigFile(projectFileDirectory);\n            return _dependencyAnalyzerFactory.Create(configProvider, _typeDependencyEnumerator);\n        }\n\n        public IAssemblyDependencyAnalyzer GetAssemblyDependencyAnalyzer(string csprojFilePath)\n        {\n            if (string.IsNullOrWhiteSpace(csprojFilePath))\n                throw new ArgumentException(\"Filename must not be null or whitespace.\", nameof(csprojFilePath));\n\n            var dependencyAnalyzer = _projectFileToAssemblyDependencyAnalyzerMap.GetOrAdd(csprojFilePath, CreateAssemblyDependencyAnalyzer, out var added);\n\n            if (!added)\n                dependencyAnalyzer.RefreshConfig();\n\n            return dependencyAnalyzer;\n        }\n\n        private IAssemblyDependencyAnalyzer CreateAssemblyDependencyAnalyzer(string projectFilePath)\n        {\n            var projectFileDirectory = Path.GetDirectoryName(projectFilePath);\n            var configProvider = _configProviderFactory.CreateFromMultiLevelXmlConfigFile(projectFileDirectory);\n            return _assemblyDependencyAnalyzerFactory.Create(configProvider);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/RoslynAnalyzer/DiagnosticDefinitions.cs",
    "content": "using System.Globalization;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n    /// <summary>\n    /// Defines the diagnostics that the tool can report.\n    /// </summary>\n    public static class DiagnosticDefinitions\n    {\n        /// <summary>\n        /// Format string to create a help link for diagnostics. The parameter is the ID of the diagnostic in lowercase.\n        /// </summary>\n        private const string HelpLinkFormat = @\"https://github.com/realvizu/NsDepCop/blob/master/doc/Diagnostics.md#{0}\";\n\n        public static readonly DiagnosticDescriptor IllegalDependency = CreateDiagnosticDescriptor(\n            \"NSDEPCOP01\",\n            \"Illegal namespace reference.\",\n            \"Illegal namespace reference: {0}->{1} (Type: {2}->{3}){4}\",\n            DiagnosticSeverity.Warning,\n            \"This type cannot reference the other type because their namespaces cannot depend on each other according to the current rules.\" +\n            \" Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this namespace dependency.\"\n        );\n\n        public static readonly DiagnosticDescriptor TooManyDependencyIssues = CreateDiagnosticDescriptor(\n            \"NSDEPCOP02\",\n            \"Too many dependency issues, analysis was stopped.\",\n            \"Maximum dependency issue count ({0}) reached, analysis in this compilation was stopped.\",\n            DiagnosticSeverity.Warning,\n            \"The number of dependency issues in this compilation has exceeded the configured maximum value.\" +\n            \" Correct the reported issues and run the build again or set the MaxIssueCount attribute in your 'config.nsdepcop' file to a higher number.\"\n        );\n\n        public static readonly DiagnosticDescriptor NoConfigFile = CreateDiagnosticDescriptor(\n            \"NSDEPCOP03\",\n            \"No config file found, analysis skipped.\",\n            \"No config file found, analysis skipped.\",\n            DiagnosticSeverity.Info,\n            \"This analyzer requires that you add a file called 'config.nsdepcop' to your project with build action 'C# analyzer additional file'.\" +\n            \" If there's no such file, the analyzer skips this project.\"\n        );\n\n        public static readonly DiagnosticDescriptor ConfigDisabled = CreateDiagnosticDescriptor(\n            \"NSDEPCOP04\",\n            \"Analysis is disabled in the config file.\",\n            \"Analysis is disabled in the file 'config.nsdepcop'.\",\n            DiagnosticSeverity.Info,\n            \"The IsEnabled attribute was set to false in this project's 'config.nsdepcop' file, so the analyzer skips this project.\"\n        );\n\n        public static readonly DiagnosticDescriptor ConfigException = CreateDiagnosticDescriptor(\n            \"NSDEPCOP05\",\n            \"Error loading config.\",\n            \"Error when loading the file 'config.nsdepcop': {0}\",\n            DiagnosticSeverity.Error,\n            \"There was an error while loading the 'config.nsdepcop' file, see the message for details.\" +\n            \" Some common reasons: malformed content, file permission or file locking problem.\"\n        );\n\n        public static readonly DiagnosticDescriptor ToolDisabled = CreateDiagnosticDescriptor(\n            \"NSDEPCOP06\",\n            \"Analysis is disabled with environment variable.\",\n            $\"NsDepCop is disabled with environment variable: '{ProductConstants.DisableToolEnvironmentVariableName}'.\",\n            DiagnosticSeverity.Info,\n            $\"If the '{ProductConstants.DisableToolEnvironmentVariableName}' environment variable is set to 'True' or '1' then all analysis is skipped.\"\n        );\n\n        public static readonly DiagnosticDescriptor IllegalAssemblyDependency = CreateDiagnosticDescriptor(\n            \"NSDEPCOP07\",\n            \"Illegal assembly reference.\",\n            \"Illegal assembly reference: {0}->{1}\",\n            DiagnosticSeverity.Warning,\n            \"The assembly cannot reference the other assembly because their dependency is prohibited according to the current rules.\" +\n            \" Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this assembly dependency.\"\n        );\n\n        private static DiagnosticDescriptor CreateDiagnosticDescriptor(\n            string id,\n            string title,\n            string messageFormat,\n            DiagnosticSeverity defaultSeverity,\n            string description)\n        {\n            return new(\n                id,\n                title,\n                messageFormat,\n                category: ProductConstants.ToolName,\n                defaultSeverity,\n                isEnabledByDefault: true,\n                description,\n                helpLinkUri: string.Format(HelpLinkFormat, id.ToLower(CultureInfo.InvariantCulture))\n            );\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/RoslynAnalyzer/IAnalyzerProvider.cs",
    "content": "using Codartis.NsDepCop.Analysis;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n    /// <summary>\n    /// Provides configured dependency analyzer instances.\n    /// </summary>\n    public interface IAnalyzerProvider\n    {\n        /// <summary>\n        /// Retrieves an up-to-date analyzer for a C# project file (csproj).\n        /// </summary>\n        /// <param name=\"csprojFilePath\">The full path of a C# project file.</param>\n        /// <returns>A dependency analyzer, or null if cannot be retrieved.</returns>\n        IDependencyAnalyzer GetDependencyAnalyzer(string csprojFilePath);\n\n        IAssemblyDependencyAnalyzer GetAssemblyDependencyAnalyzer(string csprojFilePath);\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/RoslynAnalyzer/NsDepCopAnalyzer.cs",
    "content": "﻿using System;\nusing System.Collections.Immutable;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Factory;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Config.Factory;\nusing Codartis.NsDepCop.ParserAdapter.Roslyn;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing Microsoft.CodeAnalysis.Diagnostics;\nusing Microsoft.CodeAnalysis.Text;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n    /// <summary>\n    /// Wraps the dependency analyzer in a Roslyn <see cref=\"DiagnosticAnalyzer\"/>.\n    /// </summary>\n    [DiagnosticAnalyzer(LanguageNames.CSharp)]\n    // ReSharper disable once UnusedType.Global\n    public sealed class NsDepCopAnalyzer : DiagnosticAnalyzer\n    {\n        private static readonly ImmutableArray<DiagnosticDescriptor> DiagnosticDescriptors =\n            ImmutableArray.Create(\n                DiagnosticDefinitions.IllegalDependency,\n                DiagnosticDefinitions.TooManyDependencyIssues,\n                DiagnosticDefinitions.NoConfigFile,\n                DiagnosticDefinitions.ConfigDisabled,\n                DiagnosticDefinitions.ConfigException,\n                DiagnosticDefinitions.ToolDisabled,\n                DiagnosticDefinitions.IllegalAssemblyDependency\n            );\n\n        private static readonly ImmutableArray<SyntaxKind> SyntaxKindsToRegister =\n            ImmutableArray.Create(\n                SyntaxKind.IdentifierName,\n                SyntaxKind.GenericName,\n                SyntaxKind.DefaultLiteralExpression\n            );\n\n        private readonly IAnalyzerProvider _analyzerProvider;\n\n        public NsDepCopAnalyzer()\n        {\n            _analyzerProvider = new AnalyzerProvider(\n                new DependencyAnalyzerFactory(LogTraceMessage),\n                new AssemblyDependencyAnalyzerFactory(),\n                new ConfigProviderFactory(LogTraceMessage),\n                new TypeDependencyEnumerator(new SyntaxNodeAnalyzer(), LogTraceMessage)\n            );\n        }\n\n        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => DiagnosticDescriptors;\n\n        public override void Initialize(AnalysisContext analysisContext)\n        {\n            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);\n            analysisContext.EnableConcurrentExecution();\n\n            analysisContext.RegisterCompilationStartAction(OnCompilationStart);\n            analysisContext.RegisterCompilationAction(OnCompilation);\n        }\n\n        private void OnCompilationStart(CompilationStartAnalysisContext compilationStartContext)\n        {\n            if (GlobalSettings.IsToolDisabled())\n            {\n                compilationStartContext.RegisterSyntaxTreeAction(i => ReportForSyntaxTree(i, DiagnosticDefinitions.ToolDisabled));\n                return;\n            }\n\n            var configFilePath = GetConfigFilePath(compilationStartContext.Options.AdditionalFiles);\n            if (configFilePath == null || !File.Exists(configFilePath))\n            {\n                compilationStartContext.RegisterSyntaxTreeAction(i => ReportForSyntaxTree(i, DiagnosticDefinitions.NoConfigFile));\n                return;\n            }\n\n            var dependencyAnalyzer = _analyzerProvider.GetDependencyAnalyzer(configFilePath);\n            if (dependencyAnalyzer.ConfigState == AnalyzerConfigState.ConfigError)\n            {\n                var exceptionMessage = dependencyAnalyzer.ConfigException.Message;\n                compilationStartContext.RegisterSyntaxTreeAction(i => ReportForSyntaxTree(i, DiagnosticDefinitions.ConfigException, exceptionMessage));\n                return;\n            }\n\n            if (dependencyAnalyzer.ConfigState == AnalyzerConfigState.Disabled)\n            {\n                compilationStartContext.RegisterSyntaxTreeAction(i => ReportForSyntaxTree(i, DiagnosticDefinitions.ConfigDisabled));\n                return;\n            }\n\n            // Per-compilation dependency issue counter.\n            var issueCount = 0;\n\n            compilationStartContext.RegisterSyntaxNodeAction(\n                i => AnalyzeSyntaxNodeAndReportDiagnostics(i, dependencyAnalyzer, ref issueCount),\n                SyntaxKindsToRegister);\n        }\n\n        private static void AnalyzeSyntaxNodeAndReportDiagnostics(\n            SyntaxNodeAnalysisContext syntaxNodeAnalysisContext,\n            IDependencyAnalyzer dependencyAnalyzer,\n            ref int issueCount)\n        {\n            var maxIssueCount = dependencyAnalyzer.Config.MaxIssueCount;\n\n            // Not sure whether this method will be called concurrently so to be on the safe side let's access issueCount with interlocked.\n            if (GetInterlocked(ref issueCount) > maxIssueCount)\n                return;\n\n            var analyzerMessages = dependencyAnalyzer.AnalyzeSyntaxNode(syntaxNodeAnalysisContext.Node, syntaxNodeAnalysisContext.SemanticModel);\n\n            foreach (var analyzerMessage in analyzerMessages.OfType<IllegalDependencyMessage>())\n            {\n                var currentIssueCount = Interlocked.Increment(ref issueCount);\n\n                if (currentIssueCount > maxIssueCount)\n                {\n                    ReportForSyntaxNode(syntaxNodeAnalysisContext, DiagnosticDefinitions.TooManyDependencyIssues, maxIssueCount);\n                    break;\n                }\n\n                string allowedMemberNames = string.Empty;\n\n                if (analyzerMessage.AllowedMemberNames.Length > 0)\n                {\n                    allowedMemberNames = $\" Allowed types are: {string.Join(\", \", analyzerMessage.AllowedMemberNames)}\";\n                }\n\n                ReportForSyntaxNode(\n                    syntaxNodeAnalysisContext,\n                    DiagnosticDefinitions.IllegalDependency,\n                    analyzerMessage.IllegalDependency.FromNamespaceName,\n                    analyzerMessage.IllegalDependency.ToNamespaceName,\n                    analyzerMessage.IllegalDependency.FromTypeName,\n                    analyzerMessage.IllegalDependency.ToTypeName,\n                    allowedMemberNames\n                );\n            }\n        }\n\n        /// <remarks>\n        /// Reading an int that's updated by Interlocked on other threads: https://stackoverflow.com/a/24893231/38186\n        /// </remarks>\n        private static int GetInterlocked(ref int issueCount) => Interlocked.CompareExchange(ref issueCount, 0, 0);\n\n        private void OnCompilation(CompilationAnalysisContext compilationAnalysisContext)\n        {\n            if (GlobalSettings.IsToolDisabled())\n            {\n                ReportForCompilationAnalysisContext(compilationAnalysisContext, DiagnosticDefinitions.ToolDisabled);\n                return;\n            }\n\n            var configFilePath = GetConfigFilePath(compilationAnalysisContext.Options.AdditionalFiles);\n            if (configFilePath == null || !File.Exists(configFilePath))\n            {\n                ReportForCompilationAnalysisContext(compilationAnalysisContext, DiagnosticDefinitions.NoConfigFile);\n                return;\n            }\n\n            var assemblyDependencyAnalyzer = _analyzerProvider.GetAssemblyDependencyAnalyzer(configFilePath);\n            if (assemblyDependencyAnalyzer.ConfigState == AnalyzerConfigState.ConfigError)\n            {\n                var exceptionMessage = assemblyDependencyAnalyzer.ConfigException.Message;\n                ReportForCompilationAnalysisContext(compilationAnalysisContext, DiagnosticDefinitions.ConfigException, exceptionMessage);\n                return;\n            }\n\n            if (assemblyDependencyAnalyzer.ConfigState == AnalyzerConfigState.Disabled)\n            {\n                ReportForCompilationAnalysisContext(compilationAnalysisContext, DiagnosticDefinitions.ConfigDisabled);\n                return;\n            }\n\n            AssemblyIdentity sourceAssembly = compilationAnalysisContext.Compilation.Assembly.Identity;\n            ImmutableArray<AssemblyIdentity> referencedAssemblies\n                = compilationAnalysisContext.Compilation.ReferencedAssemblyNames.ToImmutableArray();\n            var analyzerMessages = assemblyDependencyAnalyzer.AnalyzeProject(sourceAssembly, referencedAssemblies);\n\n            foreach (var illegalAssemblyDependencyMessage in analyzerMessages.OfType<IllegalAssemblyDependencyMessage>())\n            {\n                ReportForCompilationAnalysisContext(\n                    compilationAnalysisContext,\n                    DiagnosticDefinitions.IllegalAssemblyDependency,\n                    illegalAssemblyDependencyMessage.IllegalAssemblyDependency.FromAssembly.Name,\n                    illegalAssemblyDependencyMessage.IllegalAssemblyDependency.ToAssembly.Name\n                );\n            }\n        }\n\n        private static void ReportForSyntaxTree(\n            SyntaxTreeAnalysisContext syntaxTreeAnalysisContext,\n            DiagnosticDescriptor diagnosticDescriptor,\n            params object[] messageArgs)\n        {\n            var location = Location.Create(syntaxTreeAnalysisContext.Tree, TextSpan.FromBounds(0, 0));\n            var diagnostic = CreateDiagnostic(diagnosticDescriptor, location, messageArgs);\n            syntaxTreeAnalysisContext.ReportDiagnostic(diagnostic);\n        }\n\n        private static void ReportForSyntaxNode(\n            SyntaxNodeAnalysisContext syntaxNodeAnalysisContext,\n            DiagnosticDescriptor diagnosticDescriptor,\n            params object[] messageArgs)\n        {\n            var node = syntaxNodeAnalysisContext.Node;\n            var location = Location.Create(node.SyntaxTree, node.Span);\n            var diagnostic = CreateDiagnostic(diagnosticDescriptor, location, messageArgs);\n            syntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);\n        }\n\n        private static void ReportForCompilationAnalysisContext(\n            CompilationAnalysisContext compilationAnalysisContext,\n            DiagnosticDescriptor diagnosticDescriptor,\n            params object[] messageArguments)\n        {\n            var diagnostic = CreateDiagnostic(diagnosticDescriptor, null, messageArguments);\n            compilationAnalysisContext.ReportDiagnostic(diagnostic);\n        }\n\n        private static Diagnostic CreateDiagnostic(DiagnosticDescriptor diagnosticDescriptor, Location location, params object[] messageArgs)\n        {\n            return Diagnostic.Create(diagnosticDescriptor, location, messageArgs);\n        }\n\n        private static string GetConfigFilePath(ImmutableArray<AdditionalText> additionalFiles)\n        {\n            return additionalFiles.FirstOrDefault(IsConfigFile)?.Path;\n        }\n\n        private static bool IsConfigFile(AdditionalText additionalText)\n        {\n            return string.Equals(Path.GetFileName(additionalText.Path), ProductConstants.DefaultConfigFileName, StringComparison.OrdinalIgnoreCase);\n        }\n\n        private static void LogTraceMessage(string message) => Debug.WriteLine($\"[{ProductConstants.ToolName}] {message}\");\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/ConcurrentDictionaryExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Concurrent;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Extension methods for ConcurrentDictionary.\n    /// </summary>\n    public static class ConcurrentDictionaryExtensions\n    {\n        /// <summary>\n        /// Same as the built-in ConcurrentDictionary.GetOrAdd method \n        /// but also tells whether a new value was created or a stored value was returned.\n        /// </summary>\n        /// <typeparam name=\"TKey\">The type of the dictionary's key.</typeparam>\n        /// <typeparam name=\"TValue\">The type of the dictionary's value.</typeparam>\n        /// <param name=\"dict\">A concurrent dictionary object.</param>\n        /// <param name=\"key\">A key.</param>\n        /// <param name=\"generator\">A delegate that generates a value for a key.</param>\n        /// <param name=\"added\">True if a new value was generated and added, false otherwise.</param>\n        /// <returns>The value corresponding for the given key.</returns>\n        public static TValue GetOrAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict,\n            TKey key, Func<TKey, TValue> generator, out bool added)\n        {\n            while (true)\n            {\n                if (dict.TryGetValue(key, out TValue value))\n                {\n                    added = false;\n                    return value;\n                }\n\n                value = generator(key);\n                if (dict.TryAdd(key, value))\n                {\n                    added = true;\n                    return value;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/DictionaryExtensions.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Static helper class that implements extension methods for a dictionary whose value is a collection type.\n    /// </summary>\n    public static class DictionaryExtensions\n    {\n        /// <summary>\n        /// If the dictionary does not contain the given key then simply adds it with the given values.\n        /// If it already contains the key the union's it value with the given values.\n        /// </summary>\n        /// <typeparam name=\"TKey\">The type of the dictionary's key.</typeparam>\n        /// <typeparam name=\"TCollection\">The type of the dictionary's value. It must be a collection.</typeparam>\n        /// <typeparam name=\"TValue\">The type of the collection's elements.</typeparam>\n        /// <param name=\"dictionary\">A dictionary object.</param>\n        /// <param name=\"key\">The key to be added or updated.</param>\n        /// <param name=\"newValues\">The collection of newValues to be added or unioned into the dictionary,</param>\n        public static void AddOrUnion<TKey, TCollection, TValue>(this Dictionary<TKey, TCollection> dictionary, TKey key, TCollection newValues)\n            where TCollection : class, ICollection<TValue>, new()\n        {\n            if (!dictionary.ContainsKey(key))\n            {\n                dictionary.Add(key, newValues);\n                return;\n            }\n\n            var oldValues = dictionary[key];\n            if (oldValues == null && newValues != null)\n            {\n                dictionary[key] = newValues;\n                return;\n            }\n\n            if (oldValues != null && newValues != null)\n            {\n                var newCollection = new TCollection();\n                foreach (var value in oldValues.Union(newValues))\n                    newCollection.Add(value);\n                dictionary[key] = newCollection;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/EnumerableExtensions.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Static helper class that implements extension methods for IEnumerable[T]\n    /// </summary>\n    public static class EnumerableExtensions\n    {\n        /// <summary>\n        /// Returns an empty collection for a null value.\n        /// </summary>\n        /// <typeparam name=\"T\">Any type.</typeparam>\n        /// <param name=\"collection\">A collection.</param>\n        /// <returns>The collection itself if it was not null or an empty collection if it was null.</returns>\n        public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> collection)\n        {\n            return collection ?? Enumerable.Empty<T>();\n        }\n\n        /// <summary>\n        /// Returns a value indicating that the collection is null or empty.\n        /// </summary>\n        /// <typeparam name=\"T\">Any type.</typeparam>\n        /// <param name=\"collection\">A collection.</param>\n        /// <returns>True if the collection is null or empty. False if it is not empty.</returns>\n        public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)\n        {\n            return collection == null || !collection.Any();\n        }\n\n        /// <summary>\n        /// Converts a collection into a single string by concatenating the string representation of the collection elements \n        /// using optional separator and wrapper strings.\n        /// </summary>\n        /// <typeparam name=\"T\">Any type.</typeparam>\n        /// <param name=\"collection\">A collection.</param>\n        /// <param name=\"separator\">A string that will be put between every to item. Null means no separator.</param>\n        /// <param name=\"leftWrapper\">A string that will precede every item. Null means no left wrapper.</param>\n        /// <param name=\"rightWrapper\">A string that will follow every item. Null means no right wrapper.</param>\n        /// <returns>The string representation of the collection.</returns>\n        public static string ToSingleString<T>(this IEnumerable<T> collection, string separator, string leftWrapper, string rightWrapper)\n        {\n            var stringBuilder = new StringBuilder();\n\n            foreach (var item in collection)\n            {\n                // Apply separator if necessary.\n                if (stringBuilder.Length > 0)\n                {\n                    if (!string.IsNullOrEmpty(separator))\n                        stringBuilder.Append(separator);\n                }\n\n                // Apply left wrapper string if necessary.\n                if (!string.IsNullOrEmpty(leftWrapper))\n                    stringBuilder.Append(leftWrapper);\n\n                // Append the item's string representation.\n                stringBuilder.Append(item);\n\n                // Apply right wrapper string if necessary.\n                if (!string.IsNullOrEmpty(rightWrapper))\n                    stringBuilder.Append(rightWrapper);\n            }\n\n            return stringBuilder.ToString();\n        }\n\n        public static IEnumerable<T> ToEnumerable<T>(this T item)\n        {\n            if (item != null)\n                yield return item;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/ICacheStatistics.cs",
    "content": "﻿namespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Provides cache efficiency statistics.\n    /// </summary>\n    public interface ICacheStatisticsProvider\n    {\n        int HitCount { get; }\n        int MissCount { get; }\n        double EfficiencyPercent { get; }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/IDateTimeProvider.cs",
    "content": "﻿using System;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Provides date and time information.\n    /// </summary>\n    /// <remarks>\n    /// Introduced for testability.\n    /// </remarks>\n    public interface IDateTimeProvider\n    {\n        /// <summary>\n        /// Returns the current UTC date and time.\n        /// </summary>\n        DateTime UtcNow { get; }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/IDiagnosticSupport.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Provides diagnostic support operations.\n    /// </summary>\n    public interface IDiagnosticSupport\n    {\n        /// <summary>\n        /// Returns the state of the object as a string collection\n        /// </summary>\n        IEnumerable<string> ToStrings();\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/IndentHelper.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Static helper class that formats strings with indentation.\n    /// </summary>\n    public static class IndentHelper\n    {\n        public const int IndentSize = 2;\n\n        public static IEnumerable<string> Indent(string message, int indent = 0)\n            => Indent(new [] {message}, indent);\n\n        public static IEnumerable<string> Indent(IEnumerable<string> messages, int indent = 0) \n            => messages.Select(i => Format(i, indent));\n\n        private static string Format(string message, int indent = 0) \n            => $\"{new string(' ', indent * IndentSize)}{message}\";\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/LinqExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Util\n{\n    public static class LinqExtensions\n    {\n        public static TSource MinByOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)\n        {\n            return source.MinByOrDefault(selector, Comparer<TKey>.Default);\n        }\n\n        public static TSource MinByOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector,\n            IComparer<TKey> comparer)\n        {\n            if (source == null) throw new ArgumentNullException(nameof(source));\n            if (selector == null) throw new ArgumentNullException(nameof(selector));\n            if (comparer == null) throw new ArgumentNullException(nameof(comparer));\n\n            using (var sourceIterator = source.GetEnumerator())\n            {\n                if (!sourceIterator.MoveNext())\n                {\n                    return default(TSource);\n                }\n                var min = sourceIterator.Current;\n                var minKey = selector(min);\n                while (sourceIterator.MoveNext())\n                {\n                    var candidate = sourceIterator.Current;\n                    var candidateProjected = selector(candidate);\n                    if (comparer.Compare(candidateProjected, minKey) < 0)\n                    {\n                        min = candidate;\n                        minKey = candidateProjected;\n                    }\n                }\n                return min;\n            }\n        }\n\n        public static TSource MaxByOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)\n        {\n            return source.MaxByOrDefault(selector, Comparer<TKey>.Default);\n        }\n\n        public static TSource MaxByOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector,\n            IComparer<TKey> comparer)\n        {\n            if (source == null) throw new ArgumentNullException(nameof(source));\n            if (selector == null) throw new ArgumentNullException(nameof(selector));\n            if (comparer == null) throw new ArgumentNullException(nameof(comparer));\n\n            using (var sourceIterator = source.GetEnumerator())\n            {\n                if (!sourceIterator.MoveNext())\n                {\n                    return default(TSource);\n                }\n                var max = sourceIterator.Current;\n                var maxKey = selector(max);\n                while (sourceIterator.MoveNext())\n                {\n                    var candidate = sourceIterator.Current;\n                    var candidateProjected = selector(candidate);\n                    if (comparer.Compare(candidateProjected, maxKey) > 0)\n                    {\n                        max = candidate;\n                        maxKey = candidateProjected;\n                    }\n                }\n                return max;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/MathHelper.cs",
    "content": "namespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// Static helper class for simple math operations.\n    /// </summary>\n    public static class MathHelper\n    {\n        public static double CalculatePercent(double part, double total)\n        {\n            // ReSharper disable once CompareOfFloatsByEqualityOperator\n            return total == 0 \n                ? 0 \n                : part / total;\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Analyzer/Util/MessageHandler.cs",
    "content": "﻿namespace Codartis.NsDepCop.Util\n{\n    /// <summary>\n    /// A delegate that receives a string message.\n    /// </summary>\n    /// <param name=\"message\">A message.</param>\n    public delegate void MessageHandler(string message);\n}\n"
  },
  {
    "path": "source/NsDepCop.Analyzer/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"1\">\n\t<Allowed From=\"Codartis.NsDepCop.*\" To=\"DotNet.Globbing\" />\n\t<Allowed From=\"Codartis.NsDepCop.*\" To=\"Codartis.NsDepCop.Util.*\" />\n\n\t<Allowed From=\"Codartis.NsDepCop.Config.Factory\" To=\"Codartis.NsDepCop.Config.Implementation\" />\n\n\t<Allowed From=\"Codartis.NsDepCop.Analysis.*\" To=\"Codartis.NsDepCop.Config\" />\n\t<Allowed From=\"Codartis.NsDepCop.Analysis.*\" To=\"Codartis.NsDepCop.Analysis.Messages\" />\n\t<Allowed From=\"Codartis.NsDepCop.Analysis.Factory\" To=\"Codartis.NsDepCop.Analysis.Implementation\" />\n\n\t<Allowed From=\"Codartis.NsDepCop.ParserAdapter.Roslyn\" To=\"Codartis.NsDepCop.Analysis\" />\n\n\t<Allowed From=\"Codartis.NsDepCop.RoslynAnalyzer\" To=\"Codartis.NsDepCop.*\" />\n\t<Disallowed From=\"Codartis.NsDepCop.RoslynAnalyzer\" To=\"Codartis.NsDepCop.*.Implementation\" />\n\n\t<!-- This rule is for testing the RegexDomain -->\n\t<Allowed From=\"/Codartis\\.NsDepCop\\.(ParserAdapter|Analysis|RoslynAnalyzer)/\" To=\"Microsoft.CodeAnalysis.*\" />\n\n\t<AllowedAssembly From=\"*\" To=\"DotNet.Glob\" />\n\t<AllowedAssembly From=\"*\" To=\"Microsoft.*\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Benchmarks/NsDepCop.Benchmarks.RuleTypesBenchmarks-report-github.md",
    "content": "```\n\nBenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.5608/22H2/2022Update)\nIntel Core i7-10850H CPU 2.70GHz, 1 CPU, 12 logical and 6 physical cores\n.NET SDK 9.0.201\n  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2\n  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2\n\n\n```\n| Method             | Iterations | regexCompilationMode | useStaticRegexCache | Mean           | Error        | StdDev      | Gen0      | Gen1      | Allocated |\n|------------------- |----------- |--------------------- |-------------------- |---------------:|-------------:|------------:|----------:|----------:|----------:|\n| SimpleRule         | 1000       | ?                    | ?                   |       274.7 μs |      2.82 μs |     2.50 μs |  187.5000 |    0.4883 |   1.12 MB |\n| WildcardRule       | 1000       | ?                    | ?                   |       493.7 μs |      3.13 μs |     2.93 μs |  259.7656 |    0.9766 |   1.56 MB |\n| RegexRule_Instance | 1000       | Interpreted          | ?                   |       507.8 μs |      4.79 μs |     4.24 μs |  187.5000 |         - |   1.13 MB |\n| RegexRule_Static   | 1000       | Compiled             | True                |       536.1 μs |     10.63 μs |     9.94 μs |  221.6797 |         - |   1.33 MB |\n| RegexRule_Static   | 1000       | Interpreted          | True                |       642.8 μs |      6.56 μs |     6.13 μs |  221.6797 |         - |   1.33 MB |\n| RegexRule_Instance | 1000       | Compiled             | ?                   |     1,065.3 μs |      3.66 μs |     3.24 μs |  189.4531 |   19.5313 |   1.13 MB |\n| RegexRule_Static   | 1000       | Interpreted          | False               |     2,859.5 μs |     28.90 μs |    24.13 μs | 1312.5000 |         - |   7.94 MB |\n| RegexRule_Static   | 1000       | Compiled             | False               | 1,948,017.4 μs | 10,476.50 μs | 8,748.35 μs | 4000.0000 | 3000.0000 |  29.51 MB |\n"
  },
  {
    "path": "source/NsDepCop.Benchmarks/NsDepCop.Benchmarks.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>Exe</OutputType>\n\t\t<TargetFramework>net8.0</TargetFramework>\n\t\t<GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n\t\t<TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\t\t<LangVersion>latest</LangVersion>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<Compile Include=\"..\\Include\\CommonAssemblyInfo.cs\" Link=\"Properties\\CommonAssemblyInfo.cs\" />\n\t\t<Compile Include=\"..\\Include\\VersionInfo.cs\" Link=\"Properties\\VersionInfo.cs\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t  <PackageReference Include=\"BenchmarkDotNet\" Version=\"0.14.0\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t  <ProjectReference Include=\"..\\NsDepCop.Test\\NsDepCop.Test.csproj\" />\n\t</ItemGroup>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.Benchmarks/Program.cs",
    "content": "﻿using BenchmarkDotNet.Running;\n\nnamespace NsDepCop.Benchmarks;\n\npublic class Program\n{\n    public static void Main(string[] args)\n    {\n        BenchmarkRunner.Run<RuleTypesBenchmarks>();\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Benchmarks/RuleTypesBenchmarks.cs",
    "content": "﻿using System.Text.RegularExpressions;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Order;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Test.Implementation.Analysis;\nusing FluentAssertions;\n\nnamespace NsDepCop.Benchmarks;\n\n[MemoryDiagnoser]\n[Orderer(SummaryOrderPolicy.FastestToSlowest)]\npublic class RuleTypesBenchmarks\n{\n    [Params(1000)]\n    public int Iterations { get; set; }\n\n    [Benchmark]\n    public void SimpleRule()\n    {\n        var config = new DependencyRulesBuilder().AddAllowed(new Domain(\"A.B.C\"), new Domain(\"D.E.F\"));\n        BenchmarkCore(config, Iterations);\n    }\n\n    [Benchmark]\n    public void WildcardRule()\n    {\n        var config = new DependencyRulesBuilder().AddAllowed(new WildcardDomain(\"A.?.?\"), new WildcardDomain(\"D.*\"));\n        BenchmarkCore(config, Iterations);\n    }\n\n    /// <summary>\n    /// Benchmark using a Regex object instance, with or without RegexOptions.Compiled.\n    /// </summary>\n    [Benchmark]\n    [Arguments(RegexCompilationMode.Compiled)]\n    [Arguments(RegexCompilationMode.Interpreted)]\n    public void RegexRule_Instance(RegexCompilationMode regexCompilationMode)\n    {\n        var regexDomain = new RegexDomain(\"/[A-Z.]*/\", validate: true, RegexUsageMode.Instance, regexCompilationMode);\n        var config = new DependencyRulesBuilder().AddAllowed(regexDomain, regexDomain);\n        BenchmarkCore(config, Iterations);\n    }\n\n    /// <summary>\n    /// Benchmark using the static Regex.IsMatch method, with or without RegexOptions.Compiled,\n    /// and with or without using the built-in cache for static Regex.IsMatch calls.\n    /// The reason behind measuring performance also with the static Regex cache turned off,\n    /// is that in real-world usage there probably will be more than 15 different patterns,\n    /// so the cache won't be effective anyway.\n    /// </summary>\n    /// <remarks>\n    /// See: https://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-regex\n    /// By default, the last 15 most recently used static regular expression patterns are cached.\n    /// For applications that require a larger number of cached static regular expressions,\n    /// the size of the cache can be adjusted by setting the Regex.CacheSize property.\n    /// </remarks>\n    [Benchmark]\n    [Arguments(RegexCompilationMode.Compiled, true)]\n    [Arguments(RegexCompilationMode.Compiled, false)]\n    [Arguments(RegexCompilationMode.Interpreted, true)]\n    [Arguments(RegexCompilationMode.Interpreted, false)]\n    public void RegexRule_Static(RegexCompilationMode regexCompilationMode, bool useStaticRegexCache)\n    {\n        Regex.CacheSize = useStaticRegexCache ? 15 : 0;\n\n        var regexDomain = new RegexDomain(\"/[A-Z.]*/\", validate: true, RegexUsageMode.Static, regexCompilationMode);\n        var config = new DependencyRulesBuilder().AddAllowed(regexDomain, regexDomain);\n        BenchmarkCore(config, Iterations);\n    }\n\n    private static void BenchmarkCore(IDependencyRules config, int iterations)\n    {\n        var typeDependencyValidator = new TypeDependencyValidator(config);\n\n        for (var i = 0; i < iterations; i++)\n        {\n            var dependencyStatus = typeDependencyValidator.IsAllowedDependency(new TypeDependency(\"A.B.C\", \"T\", \"D.E.F\", \"T\", default));\n            dependencyStatus.IsAllowed.Should().BeTrue();\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Benchmarks/readme.txt",
    "content": "How to run the benchmarks?\n\n1. Build the solution with Release config.\n2. Run the NsDepCop.Benchmarks project.\n3. Compare the new results (in the NsDepCop.Benchmarks\\bin\\Release\\net8.0\\BenchmarkDotNet.Artifacts\\results folder)\n   with the saved result (in the NsDepCop.Benchmarks folder).\n"
  },
  {
    "path": "source/NsDepCop.ConfigSchema/NsDepCopCatalog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SchemaCatalog xmlns=\"http://schemas.microsoft.com/xsd/catalog\">\n  <Association extension=\"nsdepcop\" schema=\"%InstallRoot%/xml/schemas/NsDepCopConfig.xsd\" />\n</SchemaCatalog>"
  },
  {
    "path": "source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\"\n           xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n    <xs:element name=\"NsDepCopConfig\">\n        <xs:annotation>\n            <xs:documentation>\n                The root tag for NsDepCop config files. Add any number of Allowed, Disallowed and VisibleMembers children in any order.\n            </xs:documentation>\n        </xs:annotation>\n        <xs:complexType>\n            <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">\n                <xs:element name=\"Allowed\" type=\"AllowedNamespaceDependecySpecification\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            Defines an allowed namespace dependency.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:element>\n                <xs:element name=\"Disallowed\" type=\"NamespaceDependecySpecification\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            Defines a disallowed namespace dependency.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:element>\n                <xs:element name=\"VisibleMembers\" type=\"TypeListOfNamespace\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            Defines the types of a namespace that are visible for all other namespaces. Empty type list means no restriction.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:element>\n                <xs:element name=\"AllowedAssembly\" type=\"NamespaceDependecySpecification\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            Defines an allowed assembly dependency.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:element>\n                <xs:element name=\"DisallowedAssembly\" type=\"NamespaceDependecySpecification\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            Defines a disallowed assembly dependency.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:element>\n            </xs:choice>\n            <xs:attribute name=\"InheritanceDepth\" type=\"xs:int\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Set the number of folder levels to traverse upwards to find and combine config files. Default is 0 (no inheritance).\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"IsEnabled\" type=\"xs:boolean\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Set to true to perform analysis on the current project, false to skip analysis. Default is true.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"CodeIssueKind\" type=\"CodeIssueKind\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Sets the severity of the dependency violations: Info, Warning (default), Error.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"MaxIssueCount\" type=\"xs:int\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Sets the maximum number of issues reported from a project. After reaching this number analysis stops. Default is 100.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"MaxIssueCountSeverity\" type=\"CodeIssueKind\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Sets the severity of the event when MaxIssueCount is reached: Info, Warning (default), Error.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"AutoLowerMaxIssueCount\" type=\"xs:boolean\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        If set to true then after analysis automatically sets MaxIssueCount to the current issue count if it is lower than the current MaxIssueCount. Default is false.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"ChildCanDependOnParentImplicitly\" type=\"xs:boolean\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Set to true to enable types to depend on any other types defined in parent namespaces. Default is false (for backward compatibility).\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"ParentCanDependOnChildImplicitly\" type=\"xs:boolean\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Set to true to enable all parent namespaces to depend on any of their children namespaces. Default is false.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"InfoImportance\" type=\"MessageImportance\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Sets the importance level of NsDepCop information messages: Low, Normal (default), High. This setting combined with MsBuild verbosity will determine whether information messages show up in the output or not.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"AnalyzerServiceCallRetryTimeSpans\" type=\"xs:string\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Sets the interval lengths between subsequent retries when calling the analyzer service. Must be a list of integers (milliseconds) separated with comma. E.g.: 100,500,1000,5000\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"ExcludedFiles\" type=\"xs:string\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        File patterns that define which source files should be excluded from the analysis. Comma separated list of https://github.com/dazinator/DotNet.Glob patterns. Paths are relative to the config file's folder. E.g.: **/*.g.cs,TestFiles/*.cs\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n            <xs:attribute name=\"CheckAssemblyDependencies\" type=\"xs:boolean\" use=\"optional\">\n                <xs:annotation>\n                    <xs:documentation>\n                        We adopt the 'disallowed-by-default' approach for assembly dependencies check, similar to how we handle namespace dependencies (where everything is disallowed unless explicitly permitted). To ensure the backward compatibility, this configuration attribute has been introduced to explicitly enable the assembly dependency checking. By default this attribute is false.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:attribute>\n        </xs:complexType>\n    </xs:element>\n\n    <xs:simpleType name=\"CodeIssueKind\" >\n        <xs:restriction base=\"xs:NMTOKEN\">\n            <xs:enumeration value=\"Info\" />\n            <xs:enumeration value=\"Warning\" />\n            <xs:enumeration value=\"Error\" />\n        </xs:restriction>\n    </xs:simpleType>\n\n    <xs:simpleType name=\"MessageImportance\" >\n        <xs:restriction base=\"xs:NMTOKEN\">\n            <xs:enumeration value=\"Low\" />\n            <xs:enumeration value=\"Normal\" />\n            <xs:enumeration value=\"High\" />\n        </xs:restriction>\n    </xs:simpleType>\n\n    <xs:complexType name=\"NamespaceDependecySpecification\">\n        <xs:attribute name=\"From\" type=\"xs:string\" use=\"required\">\n            <xs:annotation>\n                <xs:documentation>\n                    The fully qualified name of the namespace that depends on the other namespace.\n                </xs:documentation>\n            </xs:annotation>\n        </xs:attribute>\n        <xs:attribute name=\"To\" type=\"xs:string\" use=\"required\">\n            <xs:annotation>\n                <xs:documentation>\n                    The fully qualified name of the namespace that the other namespace depends on.\n                </xs:documentation>\n            </xs:annotation>\n        </xs:attribute>\n    </xs:complexType>\n\n    <xs:complexType name=\"AllowedNamespaceDependecySpecification\">\n        <xs:complexContent>\n            <xs:extension base=\"NamespaceDependecySpecification\">\n                <xs:sequence>\n                    <xs:element name=\"VisibleMembers\" type=\"TypeList\" minOccurs=\"0\" maxOccurs=\"1\">\n                        <xs:annotation>\n                            <xs:documentation>\n                                Defines the types of the target namespace that are visible to the source namespace(s). Omitting this element or empty type list means no restriction.\n                            </xs:documentation>\n                        </xs:annotation>\n                    </xs:element>\n                </xs:sequence>\n            </xs:extension>\n        </xs:complexContent>\n    </xs:complexType>\n\n    <xs:complexType name=\"TypeList\">\n        <xs:sequence>\n            <xs:element name=\"Type\" type=\"TypeName\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n                <xs:annotation>\n                    <xs:documentation>\n                        Specifies a type.\n                    </xs:documentation>\n                </xs:annotation>\n            </xs:element>\n        </xs:sequence>\n    </xs:complexType>\n\n    <xs:complexType name=\"TypeListOfNamespace\">\n        <xs:complexContent>\n            <xs:extension base=\"TypeList\">\n                <xs:attribute name=\"OfNamespace\" type=\"xs:string\" use=\"required\">\n                    <xs:annotation>\n                        <xs:documentation>\n                            The fully qualified name of the namespace whose types are listed.\n                        </xs:documentation>\n                    </xs:annotation>\n                </xs:attribute>\n            </xs:extension>\n        </xs:complexContent>\n    </xs:complexType>\n\n    <xs:complexType name=\"TypeName\">\n        <xs:attribute name=\"Name\" type=\"xs:string\" use=\"required\">\n            <xs:annotation>\n                <xs:documentation>\n                    A type name without namespace qualification. Generic type names must be in metadata format (eg: List`1).\n                </xs:documentation>\n            </xs:annotation>\n        </xs:attribute>\n    </xs:complexType>\n</xs:schema>"
  },
  {
    "path": "source/NsDepCop.NuGet/NsDepCop.NuGet.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <IncludeBuildOutput>false</IncludeBuildOutput>\n    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>\n    <developmentDependency>true</developmentDependency>\n    <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>\n    <!-- Copies referenced nuget dlls to output too. -->\n    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <!-- https://github.com/NuGet/Home/issues/6754#issuecomment-592283619 -->\n    <AvoidCycleErrorOnSelfReference>true</AvoidCycleErrorOnSelfReference>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <PackageId>NsDepCop</PackageId>\n    <PackageVersion>2.7.0-local</PackageVersion>\n    <Title>NsDepCop - Namespace and Assembly Dependency Checker Tool for C#</Title>\n    <Description>NsDepCop is a static code analysis tool that enforces namespace and assembly dependency rules in C# projects.</Description>\n    <PackageTags>static code analysis analyzer tool C# csharp namespace type assembly dependency dependencies</PackageTags>\n    <Copyright>Copyright 2013-2025 Ferenc Vizkeleti</Copyright>\n    <Authors>Ferenc Vizkeleti</Authors>\n    <PackageLicenseExpression>GPL-2.0-only</PackageLicenseExpression>\n    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>\n    <PackageProjectUrl>https://github.com/realvizu/NsDepCop</PackageProjectUrl>\n    <RepositoryUrl>https://github.com/realvizu/NsDepCop.git</RepositoryUrl>\n    <PackageIconUrl>https://raw.githubusercontent.com/realvizu/NsDepCop/master/images/icons/NsDepCop_128.png</PackageIconUrl>\n    <NoPackageAnalysis>true</NoPackageAnalysis>\n    <PackageReleaseNotes>\n- Perf: Avoids unnecessary rebuilds when only a solution-level config.nsdepcop file is used (no project-level files).\n\t</PackageReleaseNotes>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <None Update=\"build\\**\" Pack=\"true\" PackagePath=\"\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"tools\\*.ps1\" Pack=\"true\" PackagePath=\"\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\NsDepCop.Analyzer\\NsDepCop.Analyzer.csproj\" />\n  </ItemGroup>\n\n  <PropertyGroup>\n    <TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput</TargetsForTfmSpecificContentInPackage>\n  </PropertyGroup>\n\n  <Target Name=\"_AddAnalyzersToOutput\">\n    <ItemGroup>\n      <TfmSpecificPackageFile Include=\"$(OutputPath)\\NsDepCop.Analyzer.dll\" PackagePath=\"analyzers/dotnet/cs\" />\n      <TfmSpecificPackageFile Include=\"$(OutputPath)\\DotNet.Glob.dll\" PackagePath=\"analyzers/dotnet/cs\" />\n    </ItemGroup>\n  </Target>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.NuGet/tools/install.ps1",
    "content": "param($installPath, $toolsPath, $package, $project)\n\nif($project.Object.SupportsPackageDependencyResolution)\n{\n    if($project.Object.SupportsPackageDependencyResolution())\n    {\n        # Do not install analyzers via install.ps1, instead let the project system handle it.\n        return\n    }\n}\n\n$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) \"analyzers\") * -Resolve\n\nforeach($analyzersPath in $analyzersPaths)\n{\n    if (Test-Path $analyzersPath)\n    {\n        # Install the language agnostic analyzers.\n        foreach ($analyzerFilePath in Get-ChildItem -Path \"$analyzersPath\\*.dll\" -Exclude *.resources.dll)\n        {\n            if($project.Object.AnalyzerReferences)\n            {\n                $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)\n            }\n        }\n    }\n}\n\n# $project.Type gives the language name like (C# or VB.NET)\n$languageFolder = \"\"\nif($project.Type -eq \"C#\")\n{\n    $languageFolder = \"cs\"\n}\nif($project.Type -eq \"VB.NET\")\n{\n    $languageFolder = \"vb\"\n}\nif($languageFolder -eq \"\")\n{\n    return\n}\n\nforeach($analyzersPath in $analyzersPaths)\n{\n    # Install language specific analyzers.\n    $languageAnalyzersPath = join-path $analyzersPath $languageFolder\n    if (Test-Path $languageAnalyzersPath)\n    {\n        foreach ($analyzerFilePath in Get-ChildItem -Path \"$languageAnalyzersPath\\*.dll\" -Exclude *.resources.dll)\n        {\n            if($project.Object.AnalyzerReferences)\n            {\n                $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)\n            }\n        }\n    }\n}\n# SIG # Begin signature block\n# MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor\n# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG\n# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA/i+qRUHsWzI0s\n# FVk99zLgt/HOEQ33uvkFsWtHTHZgf6CCDYEwggX/MIID56ADAgECAhMzAAABh3IX\n# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD\n# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy\n# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p\n# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw\n# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u\n# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy\n# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB\n# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH\n# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d\n# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ\n# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV\n# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE\n# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw\n# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1\n# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu\n# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu\n# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w\n# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3\n# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx\n# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy\n# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K\n# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV\n# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr\n# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx\n# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe\n# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g\n# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf\n# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI\n# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5\n# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea\n# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS\n# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK\n# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0\n# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0\n# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla\n# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS\n# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT\n# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB\n# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG\n# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S\n# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz\n# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7\n# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u\n# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33\n# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl\n# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP\n# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB\n# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF\n# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM\n# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ\n# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud\n# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO\n# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0\n# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y\n# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p\n# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y\n# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB\n# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw\n# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA\n# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY\n# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj\n# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd\n# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ\n# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf\n# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ\n# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j\n# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B\n# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96\n# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7\n# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I\n# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG\n# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx\n# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z\n# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN\n# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor\n# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgRjg7DcI6\n# uhYfXWwAQ6hK0mPW7iyr2tzHR0DHSDJkscIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS\n# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN\n# BgkqhkiG9w0BAQEFAASCAQCMjRK3YvDB0Sy30hadcXmGkSLrq7U7R+bkBh+FsWz8\n# CLSdV9Sh1z6mmVlEk6jHf7h3fiMEZwXGSvBEH4dc+equuU9KhYkhfTTfd3SSCER6\n# swWv/vqzQgz7WZOzuDuOrMc4lqCc3qUeLCeFnZEjfDKgymUi7UaTDofM0HNZtYA1\n# f2kLORo2CzvvZLHK+xQYvefFFrCsHSiNFvH5zM9142c1aMpGVgyuB6cBxL3johS/\n# 7i4myLHr9LB7GcSmEYqDH5q4mxgNNtunYqEyK0V0b/UI0b9q1p50KJPag9zh/HB0\n# Q+fY1t8guPwGoxkO+hqDV6k1R3tJBHG5c8kDSCVR/CbVoYIS8TCCEu0GCisGAQQB\n# gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME\n# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB\n# MDEwDQYJYIZIAWUDBAIBBQAEIHQWatv8aXHB68pc0SETnr9LF64Haou9lbLES5Og\n# 6ES0AgZgDz5A4W0YEzIwMjEwMTI4MTM1MzExLjc1N1owBIACAfSggdSkgdEwgc4x\n# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt\n# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p\n# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg\n# VFNTIEVTTjo2MEJDLUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt\n# U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABJt+6SyK5goIHAAAA\n# AAEmMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo\n# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y\n# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw\n# MB4XDTE5MTIxOTAxMTQ1OVoXDTIxMDMxNzAxMTQ1OVowgc4xCzAJBgNVBAYTAlVT\n# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK\n# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy\n# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo2MEJD\n# LUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj\n# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ4wvoacTvMNlXQTtfF/\n# Cx5Ol3X0fcjUNMvjLgTmO5+WHYJFbp725P3+qvFKDRQHWEI1Sz0gB24urVDIjXjB\n# h5NVNJVMQJI2tltv7M4/4IbhZJb3xzQW7LolEoZYUZanBTUuyly9osCg4o5joViT\n# 2GtmyxK+Fv5kC20l2opeaeptd/E7ceDAFRM87hiNCsK/KHyC+8+swnlg4gTOey6z\n# QqhzgNsG6HrjLBuDtDs9izAMwS2yWT0T52QA9h3Q+B1C9ps2fMKMe+DHpG+0c61D\n# 94Yh6cV2XHib4SBCnwIFZAeZE2UJ4qPANSYozI8PH+E5rCT3SVqYvHou97HsXvP2\n# I3MCAwEAAaOCARswggEXMB0GA1UdDgQWBBRJq6wfF7B+mEKN0VimX8ajNA5hQTAf\n# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH\n# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU\n# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF\n# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0\n# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG\n# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBAlvudaOlv9Cfzv56bnX41czF6tLtH\n# LB46l6XUch+qNN45ZmOTFwLot3JjwSrn4oycQ9qTET1TFDYd1QND0LiXmKz9OqBX\n# ai6S8XdyCQEZvfL82jIAs9pwsAQ6XvV9jNybPStRgF/sOAM/Deyfmej9Tg9FcRwX\n# ank2qgzdZZNb8GoEze7f1orcTF0Q89IUXWIlmwEwQFYF1wjn87N4ZxL9Z/xA2m/R\n# 1zizFylWP/mpamCnVfZZLkafFLNUNVmcvc+9gM7vceJs37d3ydabk4wR6ObR34sW\n# aLppmyPlsI1Qq5Lu6bJCWoXzYuWpkoK6oEep1gML6SRC3HKVS3UscZhtMIIGcTCC\n# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC\n# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV\n# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv\n# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN\n# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv\n# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0\n# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw\n# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0\n# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw\n# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe\n# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx\n# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G\n# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA\n# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7\n# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX\n# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v\n# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI\n# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j\n# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g\n# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93\n# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB\n# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA\n# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh\n# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS\n# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK\n# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon\n# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi\n# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/\n# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII\n# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0\n# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a\n# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ\n# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+\n# NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT\n# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD\n# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP\n# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo2\n# MEJDLUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy\n# dmljZaIjCgEBMAcGBSsOAwIaAxUACmcyOWmZxErpq06B8dy6oMZ6//yggYMwgYCk\n# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH\n# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD\n# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF\n# AOO8XzYwIhgPMjAyMTAxMjgwMTUyNTRaGA8yMDIxMDEyOTAxNTI1NFowdzA9Bgor\n# BgEEAYRZCgQBMS8wLTAKAgUA47xfNgIBADAKAgEAAgIbLwIB/zAHAgEAAgITKTAK\n# AgUA472wtgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB\n# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAC77bUsJUEVTSYlY\n# wKFpNKL8dbjlzb8EutPbxa952QSEIxgMUycq0Db9t3QSPfWd919JnobZ+0PCoE2A\n# Pu4Os73CDKVzF+bwFgLRnttBccwAsgy7d1pWtQcfyIh9O+l/HislSXsFH5zawEs5\n# 9uvH8UtGX1jExKlXKnmQriZYTlTCMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC\n# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV\n# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp\n# bWUtU3RhbXAgUENBIDIwMTACEzMAAAEm37pLIrmCggcAAAAAASYwDQYJYIZIAWUD\n# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B\n# CQQxIgQgfLtPMEgO0BfdMeIvsY3gSnjcAKLOUnkiV89CXQ7fmqkwgfoGCyqGSIb3\n# DQEJEAIvMYHqMIHnMIHkMIG9BCA2/c/vnr1ecAzvapOWZ2xGfAkzrkfpGcrvMW07\n# CQl1DzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u\n# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp\n# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB\n# Jt+6SyK5goIHAAAAAAEmMCIEILgdbWcIe050A6mMuy1I+6mT4dgtx0U15aTsUnn0\n# tfP4MA0GCSqGSIb3DQEBCwUABIIBAI2O4PAlewLHuXky0KYOlR03qPHYvVDSIZWv\n# ydszjrgdE02PX1qWo6ZyiuPuyM+ssKiHImpy/wCt2aQk/PPAOIgJVhyhsyc2N0h/\n# Hb1cBDGdpwfDndZquf5pwrqfNm2KM9tk7nDkKa0O0C7VpfOgSdamThZiaOZDJVhp\n# A3pTsR1LhA17Wih8bgDRsZRCiEPhrfeWBMb3nMjyox3zg+XL0yFmvfcyOWkn/I3o\n# 4jj8KKqJ2SwJTJqRWqNg036ilkaayzpFA2XX55s2cdAmPpVh8VuTRLrKVx00/TXS\n# hGHM1fgii3urBBNUn8TSXTcUZFpnb9dWJFbxi0aHcHq8iq0J90g=\n# SIG # End signature block\n"
  },
  {
    "path": "source/NsDepCop.NuGet/tools/uninstall.ps1",
    "content": "param($installPath, $toolsPath, $package, $project)\n\nif($project.Object.SupportsPackageDependencyResolution)\n{\n    if($project.Object.SupportsPackageDependencyResolution())\n    {\n        # Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it.\n        return\n    }\n}\n\n$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) \"analyzers\") * -Resolve\n\nforeach($analyzersPath in $analyzersPaths)\n{\n    # Uninstall the language agnostic analyzers.\n    if (Test-Path $analyzersPath)\n    {\n        foreach ($analyzerFilePath in Get-ChildItem -Path \"$analyzersPath\\*.dll\" -Exclude *.resources.dll)\n        {\n            if($project.Object.AnalyzerReferences)\n            {\n                $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)\n            }\n        }\n    }\n}\n\n# $project.Type gives the language name like (C# or VB.NET)\n$languageFolder = \"\"\nif($project.Type -eq \"C#\")\n{\n    $languageFolder = \"cs\"\n}\nif($project.Type -eq \"VB.NET\")\n{\n    $languageFolder = \"vb\"\n}\nif($languageFolder -eq \"\")\n{\n    return\n}\n\nforeach($analyzersPath in $analyzersPaths)\n{\n    # Uninstall language specific analyzers.\n    $languageAnalyzersPath = join-path $analyzersPath $languageFolder\n    if (Test-Path $languageAnalyzersPath)\n    {\n        foreach ($analyzerFilePath in Get-ChildItem -Path \"$languageAnalyzersPath\\*.dll\" -Exclude *.resources.dll)\n        {\n            if($project.Object.AnalyzerReferences)\n            {\n                try\n                {\n                    $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)\n                }\n                catch\n                {\n\n                }\n            }\n        }\n    }\n}\n# SIG # Begin signature block\n# MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor\n# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG\n# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDC68wb97fg0QGL\n# yXrxJhYfmibzcOh8caqC0uZprfczDaCCDYEwggX/MIID56ADAgECAhMzAAABh3IX\n# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD\n# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy\n# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p\n# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw\n# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u\n# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy\n# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB\n# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH\n# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d\n# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ\n# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV\n# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE\n# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw\n# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1\n# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu\n# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu\n# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w\n# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3\n# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx\n# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy\n# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K\n# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV\n# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr\n# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx\n# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe\n# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g\n# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf\n# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI\n# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5\n# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea\n# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS\n# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK\n# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0\n# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0\n# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla\n# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS\n# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT\n# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB\n# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG\n# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S\n# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz\n# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7\n# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u\n# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33\n# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl\n# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP\n# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB\n# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF\n# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM\n# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ\n# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud\n# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO\n# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0\n# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y\n# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p\n# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y\n# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB\n# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw\n# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA\n# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY\n# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj\n# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd\n# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ\n# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf\n# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ\n# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j\n# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B\n# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96\n# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7\n# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I\n# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG\n# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx\n# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z\n# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN\n# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor\n# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgF1ypFyzl\n# AvvWGVCeXczrfpXmJNm9vpyjcwd4y4ivfqowQgYKKwYBBAGCNwIBDDE0MDKgFIAS\n# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN\n# BgkqhkiG9w0BAQEFAASCAQAlvp3kobQ3njGrv7T9mKm8viQ7IsK06yFq43ZwDIob\n# rkxRRMZKKJfaJ2pkkTtMun/wzMjQ7hqbULUO22lywwNy3t7uNINETfPReIYNIG9p\n# KZ3t8zI1T+7B9Vpm5t9LC9hQp1yrj88LcA1QAaFcvjn1sxUOGlLFK2jsa2AUcrwr\n# QpiVDX+OOdExw+EJTUBil/kvAtXHdCT1qkH3JzzSBYiCLGq2pW4AuVvlL0iiRKeT\n# /AW6TY9SuOUoG0aOZZzLAuCp6qA7ovKqRAGoFpcAaGXQokWRLU4se3/2meBksksu\n# ZlP1paBMHbT1ZLJP095SzhwYfsw7IDkC0Zt1OLq7IdwwoYIS8TCCEu0GCisGAQQB\n# gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME\n# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB\n# MDEwDQYJYIZIAWUDBAIBBQAEIMdwQTCmst1vtKyhKIg+hpE9VQEH7XzRp1eSg9au\n# tOz7AgZgEAenLh4YEzIwMjEwMTI4MTM1MzExLjM0N1owBIACAfSggdSkgdEwgc4x\n# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt\n# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p\n# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg\n# VFNTIEVTTjo0NjJGLUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt\n# U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABJMvNAqEXcFyaAAAA\n# AAEkMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo\n# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y\n# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw\n# MB4XDTE5MTIxOTAxMTQ1N1oXDTIxMDMxNzAxMTQ1N1owgc4xCzAJBgNVBAYTAlVT\n# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK\n# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy\n# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo0NjJG\n# LUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj\n# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJCbKjgNnhjvMlnRNAtx\n# 7X3N5ZZkSfUFULyWsVJ1pnyMsSITimg1q3OQ1Ikf0/3gg8UG5TIRm7wH8sjBtoB3\n# nuzFz11CegIFcanYnt050JvnrUTKeAPUR5pLpTeP3QEgL+CWOc4lTg/XxjnQv01F\n# D7TTn9DEuO3kp0GQ87Mjd5ssxK0K1q4IWNFAyRpx5n8Vm3Vm1iiVL5FMDUKsl5G/\n# SqQdiEDn8cqYbqWMVzWH94PdKdw1mIHToBRCNsR9BHHWzNkSS+R0WRipBSSorKT7\n# cuLlEBYhDo8AY3uMGlv0kLRLHASZ+sz2nfkpW2CVt+bHhVmM6/5qiu2f7eYoTYJu\n# cFECAwEAAaOCARswggEXMB0GA1UdDgQWBBS7HdFyrGKIhDxvypLA1lD/wGRSsDAf\n# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH\n# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU\n# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF\n# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0\n# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG\n# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBo3QzNuNRgzdflwA4U7f3e2CcGlwdg\n# 6ii498cBiSrTpWKO3qqz5pvgHAk4hh6y/FLY80R59inLwcVuyD24S3JEdSie4y1t\n# C5JptweR1qlxRJCRM4vG7nPtIC4eAMKcXgovu0mTFv7xpFAVpRuvuepR91gIde32\n# 8lv1HTTJCV/LBBk83Xi7nCGPF59FxeIrcE32xt4YJgEpEAikeMqvWCTMyPqlmvx9\n# J92fxU3cQcw2j2EWwqOD5T3Nz2HWfPV80sihD1A6Y5HhjpS9taDPs7CI58I211F3\n# ysegNyOesG3MTrSJHyPMLKYFDxcG1neV0liktv+TW927sUOVczcSUhQLMIIGcTCC\n# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC\n# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV\n# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv\n# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN\n# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv\n# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0\n# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw\n# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0\n# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw\n# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe\n# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx\n# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G\n# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA\n# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7\n# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX\n# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v\n# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI\n# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j\n# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g\n# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93\n# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB\n# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA\n# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh\n# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS\n# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK\n# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon\n# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi\n# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/\n# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII\n# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0\n# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a\n# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ\n# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+\n# NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT\n# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD\n# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP\n# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo0\n# NjJGLUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy\n# dmljZaIjCgEBMAcGBSsOAwIaAxUAlwPlNCq+Un54UfxLe/wKS1Xc4nqggYMwgYCk\n# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH\n# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD\n# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF\n# AOO9KO8wIhgPMjAyMTAxMjgxNjEzMzVaGA8yMDIxMDEyOTE2MTMzNVowdzA9Bgor\n# BgEEAYRZCgQBMS8wLTAKAgUA470o7wIBADAKAgEAAgIdzgIB/zAHAgEAAgITSTAK\n# AgUA4756bwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB\n# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEiUh4QVb7vaceUo\n# /TtRAhp98XfrRN5mZ4KyZDuNDYKfBaGx8hnyD2BgIjkQ59KzIVNfkv8PBXhLaQK7\n# u7k4S23kUWQ/zsRYm5EutcKXB3zrW4Ym0TpwiMTJ8arMFj3BIYjZCMFqUxdAxiH/\n# CD+FIK0vvPSTRZ00KPqi5idqCj3TMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC\n# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV\n# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp\n# bWUtU3RhbXAgUENBIDIwMTACEzMAAAEky80CoRdwXJoAAAAAASQwDQYJYIZIAWUD\n# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B\n# CQQxIgQgrLzvm34azoh15/K+sBdmMol8NxD/FT4rQfDgBXN/atwwgfoGCyqGSIb3\n# DQEJEAIvMYHqMIHnMIHkMIG9BCBiOOHoohqL+X7Xa/25jp1wTrQxYlYGLszis/nA\n# TirjIDCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u\n# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp\n# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB\n# JMvNAqEXcFyaAAAAAAEkMCIEILvfBT5GpMSMrQo5TU1VuEC6URcoooi2maNoHgLo\n# yvsvMA0GCSqGSIb3DQEBCwUABIIBAIxWH4gHkyfHcF3w9aW9L1OaBOjv/Zmq7V1R\n# pj4tkkyuQKPqIi9gdq4wMxToI1m4IM/9I8FwLI1LH/6AWBLTfdkFr4mOMFyflO5v\n# gya84Pij48E/37XOOBG5S454c4Sgj6OQcZb1Ljb+QNf+6JovAhUdLL4ZLmdvuK5X\n# amv+cjYVV3jSJYMSx8d0w22rPmJVB25h1NZlJvPKZdKGc28ub2IxnvALF6SYaR5u\n# AQVzIzltI+lm1Owqt9JAuuif6YYhh/P4Z4PfXWtY/2xsIqYHbQwizlu/3Hs9UK60\n# VE+jyR89LdWrWqCW0orWrNwUFBiYIuupntcRH/1LMk6Tr/CJa64=\n# SIG # End signature block\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeatureTests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests analyzer features on source files.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    public class AnalyzerFeatureTests\n    {\n        [Fact]\n        public void AnalyzerFeature_AllowedDependency()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_DisallowedDependency()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(5, 19, 25)\n                .ExpectInvalidSegment(6, 17, 29)\n                .ExpectInvalidSegment(7, 24, 28)\n                .Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_ExcludedFiles()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_ExcludedFiles_WithWildcard()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_SameNamespaceAlwaysAllowed()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_ChildCanDependOnParentImplicitly()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n        \n        [Fact]\n        public void AnalyzerFeature_ParentCanDependOnChildImplicitly()\n        {\n            SourceTestSpecification.Create().Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_VisibleMembersOfNamespace()\n        {\n            string[] members = new[] { \"VisibleType\", \"OnlyGenericIsVisibleType`1\" };\n\n            SourceTestSpecification.Create()\n                \n                // A -> C\n                .ExpectInvalidSegment(6, 19, 32, members)\n                .ExpectInvalidSegment(8, 19, 43, members)\n                .ExpectInvalidSegment(9, 19, 47, members)\n\n                // B -> C\n                .ExpectInvalidSegment(20, 19, 32, members)\n                .ExpectInvalidSegment(22, 19, 43, members)\n                .ExpectInvalidSegment(23, 19, 47, members)\n                \n                .Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_VisibleMembersOfAllowedRule()\n        {\n            string[] members = new[] { \"VisibleType\", \"OnlyGenericIsVisibleType`1\" };\n            \n            SourceTestSpecification.Create()\n\n                // A -> C\n                .ExpectInvalidSegment(6, 19, 32, members)\n                .ExpectInvalidSegment(8, 19, 43, members)\n                .ExpectInvalidSegment(9, 19, 47, members)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void AnalyzerFeature_WithTopLevelStatement()\n        {\n            SourceTestSpecification.Create()\n\n                .ExpectInvalidSegment(1, 8, 12)\n\n                .Execute(Microsoft.CodeAnalysis.OutputKind.ConsoleApplication);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_AllowedDependency/AnalyzerFeature_AllowedDependency.cs",
    "content": "﻿namespace A\n{\n    public class NoIssue\n    {\n        private B.MyEnum field1;\n        private MyGlobalEnum field2;\n        private System.Type field3;\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    { }\n}\n\npublic enum MyGlobalEnum\n{ }"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_AllowedDependency/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\".\" />\n    <Allowed From=\"A\" To=\"System.*\" />\n    <Allowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ChildCanDependOnParentImplicitly/AnalyzerFeature_ChildCanDependOnParentImplicitly.cs",
    "content": "﻿namespace A.B\n{\n    public class NoIssue\n    {\n        private A.MyEnum field1;\n        private MyGlobalEnum field2;\n    }\n}\n\nnamespace A\n{\n    public enum MyEnum\n    { }\n}\n\npublic enum MyGlobalEnum\n{ }"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ChildCanDependOnParentImplicitly/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig ChildCanDependOnParentImplicitly=\"true\"/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_DisallowedDependency/AnalyzerFeature_DisallowedDependency.cs",
    "content": "﻿namespace A\n{\n    public class NoIssue\n    {\n        private B.MyEnum field1;\n        private MyGlobalEnum field2;\n        private System.Type field3;\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    { }\n}\n\npublic enum MyGlobalEnum\n{ }"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_DisallowedDependency/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" /> \n    <Disallowed From=\"*\" To=\".\" />\n    <Disallowed From=\"A\" To=\"System.*\" />\n    <Disallowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles/AnalyzerFeature_ExcludedFiles.cs",
    "content": "﻿namespace A\n{\n    public class MyClass\n    {\n        private B.MyEnum field1;\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles/config.nsdepcop",
    "content": "﻿<NsDepCopConfig ExcludedFiles=\"AnalyzerFeature_ExcludedFiles.cs\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles_WithWildcard/AnalyzerFeature_ExcludedFiles_WithWildcard.cs",
    "content": "﻿namespace A\n{\n    public class MyClass\n    {\n        private B.MyEnum field1;\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles_WithWildcard/config.nsdepcop",
    "content": "﻿<NsDepCopConfig ExcludedFiles=\"*.cs\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ParentCanDependOnChildImplicitly/AnalyzerFeature_ParentCanDependOnChildImplicitly.cs",
    "content": "﻿public class NoIssue\n{\n    private A.MyEnum field1;\n    private A.B.MyGlobalEnum field2;\n}\n\nnamespace A\n{\n    public enum MyEnum\n    { }\n}\n\nnamespace A.B\n{\n    public enum MyGlobalEnum\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_ParentCanDependOnChildImplicitly/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig ParentCanDependOnChildImplicitly=\"true\"/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs",
    "content": "﻿namespace A\n{\n    public class NoIssue\n    {\n        private A.MyEnum field;\n    }\n\n    public enum MyEnum\n    { }\n\n    public class OnlyTypeVisibleOutside\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <VisibleMembers OfNamespace=\"A\">\n        <Type Name=\"OnlyTypeVisibleOutside\" />\n    </VisibleMembers>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAlwaysAllowed/AnalyzerFeature_SameNamespaceAlwaysAllowed.cs",
    "content": "﻿namespace A\n{\n    public class NoIssue\n    {\n        private A.MyEnum field;\n    }\n\n    public enum MyEnum\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAlwaysAllowed/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfAllowedRule/AnalyzerFeature_VisibleMembersOfAllowedRule.cs",
    "content": "﻿namespace A\n{\n    public class MyClass\n    {\n        private C.VisibleType field1;\n        private C.InvisibleType field2;\n        private C.OnlyGenericIsVisibleType<MyEnum> field3;\n        private C.OnlyGenericIsVisibleType field4;\n        private C.InvisibleGenericType<MyEnum> field5;\n    }\n\n    public enum MyEnum { }\n}\n\nnamespace B\n{\n    public class MyClass\n    {\n        private C.VisibleType field1;\n        private C.InvisibleType field2;\n        private C.OnlyGenericIsVisibleType<MyEnum> field3;\n        private C.OnlyGenericIsVisibleType field4;\n        private C.InvisibleGenericType<MyEnum> field5;\n    }\n\n    public enum MyEnum { }\n}\n\nnamespace C\n{\n    public enum VisibleType\n    { }\n\n    public enum InvisibleType\n    { }\n\n    public class OnlyGenericIsVisibleType<T>\n    { }\n\n    public class OnlyGenericIsVisibleType\n    { }\n\n    public class InvisibleGenericType<T>\n    { }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfAllowedRule/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n\n    <Allowed From=\"A\" To=\"C\" >\n        <VisibleMembers>\n            <Type Name=\"VisibleType\" />\n            <Type Name=\"OnlyGenericIsVisibleType`1\" />\n        </VisibleMembers>\n    </Allowed>\n\n    <Allowed From=\"B\" To=\"C\" />\n\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfNamespace/AnalyzerFeature_VisibleMembersOfNamespace.cs",
    "content": "﻿namespace A\n{\n    public class MyClass\n    {\n        private C.VisibleType field1;\n        private C.InvisibleType field2;\n        private C.OnlyGenericIsVisibleType<MyEnum> field3;\n        private C.OnlyGenericIsVisibleType field4;\n        private C.InvisibleGenericType<MyEnum> field5;\n    }\n\n    public enum MyEnum { }\n}\n\nnamespace B\n{\n    public class MyClass\n    {\n        private C.VisibleType field1;\n        private C.InvisibleType field2;\n        private C.OnlyGenericIsVisibleType<MyEnum> field3;\n        private C.OnlyGenericIsVisibleType field4;\n        private C.InvisibleGenericType<MyEnum> field5;\n    }\n\n    public enum MyEnum { }\n}\n\nnamespace C\n{\n    public enum VisibleType\n    { }\n\n    public enum InvisibleType\n    { }\n\n    public class OnlyGenericIsVisibleType<T>\n    { }\n\n    public class OnlyGenericIsVisibleType\n    { }\n\n    public class InvisibleGenericType<T>\n    { }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfNamespace/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n\n    <Allowed From=\"A\" To=\"C\" />\n    <Allowed From=\"B\" To=\"C\" />\n\n    <VisibleMembers OfNamespace=\"C\">\n        <Type Name=\"VisibleType\" />\n        <Type Name=\"OnlyGenericIsVisibleType`1\" />\n    </VisibleMembers>\n    \n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_WithTopLevelStatement/AnalyzerFeature_WithTopLevelStatement.cs",
    "content": "﻿System.Type field3;"
  },
  {
    "path": "source/NsDepCop.SourceTest/AnalyzerFeature_WithTopLevelStatement/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6Tests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests that the analyzer handles various C# 6.0 constructs correctly.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    public class Cs6Tests\n    {\n        [Fact]\n        public void Cs6_AliasQualifiedName()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 25, 31)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_ArrayType()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 19, 25)\n                .ExpectInvalidSegment(11, 20, 27)\n                .ExpectInvalidSegment(12, 20, 27)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_QualifiedName()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(5, 19, 25)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_InvocationExpression()\n        {\n            SourceTestSpecification.Create()\n\n                // Class3\n                .ExpectInvalidSegment(9, 13, 20)\n                // Class3\n                .ExpectInvalidSegment(10, 26, 33)\n                // Class3\n                .ExpectInvalidSegment(11, 20, 27)\n                // Class4<Class3>\n                .ExpectInvalidSegment(12, 20, 27)\n                .ExpectInvalidSegment(12, 20, 27)\n                // Class3\n                .ExpectInvalidSegment(15, 11, 17)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_InvocationWithTypeArg()\n        {\n            SourceTestSpecification.Create()\n\n                // Class3\n                .ExpectInvalidSegment(10, 28, 34)\n\n                // Class4<Class3>\n                .ExpectInvalidSegment(11, 28, 42)\n                .ExpectInvalidSegment(11, 35, 41)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_MemberAccessExpression()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(9, 37, 47)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_GenericName()\n        {\n            SourceTestSpecification.Create()\n\n                // MyGenericClass<MyClass2>\n                .ExpectInvalidSegment(8, 17, 41)\n\n                // MyGenericClass2<MyClass3, MyClass2, MyClass3>\n                .ExpectInvalidSegment(11, 17, 62)\n                // MyClass3\n                .ExpectInvalidSegment(11, 33, 41)\n                // MyClass3\n                .ExpectInvalidSegment(11, 53, 61)\n\n                // MyGenericClass<MyGenericClass<MyClass3>>\n                .ExpectInvalidSegment(14, 17, 57)\n                // MyGenericClass<MyClass3>\n                .ExpectInvalidSegment(14, 32, 56)\n                // MyClass3\n                .ExpectInvalidSegment(14, 47, 55)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_GenericTypeArgument()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 32, 40)\n                .ExpectInvalidSegment(8, 36, 44)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_NestedType()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 17, 25)\n                .ExpectInvalidSegment(7, 26, 36)\n                .ExpectInvalidSegment(8, 19, 27)\n                .ExpectInvalidSegment(8, 28, 38)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_PointerType()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 19, 25)\n                .ExpectInvalidSegment(11, 20, 27)\n                .ExpectInvalidSegment(12, 20, 27)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_VeryComplexType()\n        {\n            SourceTestSpecification.Create()\n\n                // Class4<Class3[], Class4<Class3*[], Class3[][]>>\n                .ExpectInvalidSegment(10, 13, 60)\n                .ExpectInvalidSegment(10, 20, 26)\n                .ExpectInvalidSegment(10, 30, 59)\n                .ExpectInvalidSegment(10, 37, 43)\n                .ExpectInvalidSegment(10, 48, 54)\n\n                // Method2 return value\n                .ExpectInvalidSegment(10, 72, 79)\n                .ExpectInvalidSegment(10, 72, 79)\n                .ExpectInvalidSegment(10, 72, 79)\n                .ExpectInvalidSegment(10, 72, 79)\n                .ExpectInvalidSegment(10, 72, 79)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_NullableType()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 17, 25)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_EveryUserDefinedTypeKind()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 17, 24)\n                .ExpectInvalidSegment(8, 17, 29)\n                .ExpectInvalidSegment(9, 17, 25)\n                .ExpectInvalidSegment(10, 17, 23)\n                .ExpectInvalidSegment(11, 17, 27)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_ExtensionMethodInvocation()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(9, 27, 44)\n                .ExpectInvalidSegment(10, 27, 51)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_ObjectCreationExpression()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(9, 17, 29)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_Var()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(7, 13, 16)\n                .ExpectInvalidSegment(7, 23, 29)\n                .ExpectInvalidSegment(7, 30, 40)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_VarWithConstructedGenericType()\n        {\n            SourceTestSpecification.Create()\n\n                // var: ClassB`2, EnumB, EnumB\n                .ExpectInvalidSegment(8, 13, 16)\n                .ExpectInvalidSegment(8, 13, 16)\n                .ExpectInvalidSegment(8, 13, 16)\n\n                // ClassB<B.EnumB, EnumA, B.EnumB>\n                .ExpectInvalidSegment(8, 23, 54)\n                // EnumB\n                .ExpectInvalidSegment(8, 32, 37)\n                // EnumB\n                .ExpectInvalidSegment(8, 48, 53)\n\n                // Instance: ClassB`2, EnumB, EnumB\n                .ExpectInvalidSegment(8, 55, 63)\n                .ExpectInvalidSegment(8, 55, 63)\n                .ExpectInvalidSegment(8, 55, 63)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_Attributes()\n        {\n            SourceTestSpecification.Create()\n\n                // assembly and module attributes are not analyzed because there's no enclosing type\n                //// [assembly: A.AllowedAttributeWithTypeArg(typeof(B.ForbiddenType))]\n                //CreateLogEntryParameters(sourceFileName, 3, 14, 3, 41),\n                //CreateLogEntryParameters(sourceFileName, 3, 51, 3, 64),\n                //// [module: A.AllowedAttributeWithTypeArg(typeof(B.ForbiddenType))]\n                //CreateLogEntryParameters(sourceFileName, 4, 12, 4, 39),\n                //CreateLogEntryParameters(sourceFileName, 4, 49, 4, 62),\n                //// [assembly: B.ForbiddenAttribute(\"foo\")]\n                //CreateLogEntryParameters(sourceFileName, 5, 14, 5, 32),\n                //// [module: B.Forbidden(\"foo\")]\n                //CreateLogEntryParameters(sourceFileName, 6, 12, 6, 21),\n\n                // [Forbidden on class\n                .ExpectInvalidSegment(20, 6, 15)\n\n                // class attribute type parameter\n                .ExpectInvalidSegment(26, 41, 54)\n\n                // field attribute type parameter\n                .ExpectInvalidSegment(34, 45, 58)\n\n                // enum value attribute type parameter\n                .ExpectInvalidSegment(43, 45, 58)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_Delegates()\n        {\n            SourceTestSpecification.Create()\n\n                // delegate Class1<Class2> Delegate1(Class2 c);\n                .ExpectInvalidSegment(5, 14, 28)\n                .ExpectInvalidSegment(5, 21, 27)\n                .ExpectInvalidSegment(5, 39, 45)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_ElementAccess()\n        {\n            SourceTestSpecification.Create()\n\n                // var a = new Class2<Class3>[10];\n                .ExpectInvalidSegment(9, 13, 16)\n                .ExpectInvalidSegment(9, 13, 16)\n                .ExpectInvalidSegment(9, 25, 39)\n                .ExpectInvalidSegment(9, 32, 38)\n\n                // a[1] = a[2];\n                .ExpectInvalidSegment(10, 13, 14)\n                .ExpectInvalidSegment(10, 13, 14)\n                .ExpectInvalidSegment(10, 20, 21)\n                .ExpectInvalidSegment(10, 20, 21)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs6_StaticImport()\n        {\n            SourceTestSpecification.Create()\n                .ExpectInvalidSegment(9, 13, 32)\n                .ExpectInvalidSegment(10, 13, 34) // because of the return value\n                .ExpectInvalidSegment(10, 13, 34) // because of the declaring type\n                .Execute();\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_AliasQualifiedName/Cs6_AliasQualifiedName.cs",
    "content": "﻿enum MyEnum {}\n\nnamespace A\n{\n    class MyClass\n    {\n        private global::MyEnum e;\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_AliasQualifiedName/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ArrayType/Cs6_ArrayType.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class Class1\n    {\n        private C.Class3[] e;\n\n        private void Method1()\n        {\n            Class2.Method2();\n            Class2.Method3();\n        }\n    }\n}\n\nnamespace B\n{\n    using C;\n\n    class Class2\n    {\n        public static Class3[] Method2() { return null; }\n        public static Class3[][] Method3() { return null; }\n    }\n}\n\nnamespace C\n{\n    class Class3\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ArrayType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"B\" />\n    <Allowed From=\"B\" To=\"C\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Attributes/Cs6_Attributes.cs",
    "content": "﻿using System;\n\n// not analyzed: [assembly: A.AllowedAttributeWithTypeArg(typeof(B.ForbiddenType))]\n// not analyzed: [module: A.AllowedAttributeWithTypeArg(typeof(B.ForbiddenType))]\n// not analyzed: [assembly: B.ForbiddenAttribute(\"foo\")]\n// not analyzed: [module: B.Forbidden(\"foo\")]\n\nnamespace A\n{\n    using B;\n\n    [AttributeUsage(AttributeTargets.All)]\n    class AllowedAttributeWithTypeArg : Attribute\n    {\n        public AllowedAttributeWithTypeArg(Type t)\n        {\n        }\n    }\n\n    [Forbidden(\"Attributes defined in the foreign namespace detected ok\")]\n    class Foo2\n    {\n    }\n\n    // Reference to forbidden type in arg to attribute on class. Detected OK.\n    [AllowedAttributeWithTypeArg(typeof(ForbiddenType))]\n    class Foo3\n    {\n    }\n\n    class Foo4\n    {\n        // Reference to forbidden type in arg to attribute on class field. Detected OK.\n        [AllowedAttributeWithTypeArg(typeof(ForbiddenType))]\n        public int x;\n    }\n\n    enum Foo5\n    {\n        Value1,\n\n        // Reference to forbidden type in arg to attribute on enum value. Not Detected!\n        [AllowedAttributeWithTypeArg(typeof(ForbiddenType))]\n        Value2\n    }\n}\n\nnamespace B\n{\n    class ForbiddenAttribute : Attribute\n    {\n        public ForbiddenAttribute(string s)\n        { }\n    }\n\n    class ForbiddenType\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Attributes/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Delegates/Cs6_Delegates.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    delegate Class1<Class2> Delegate1(Class2 c);\n}\n\nnamespace B\n{\n    class Class1<T>\n    {\n    }\n\n    class Class2\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Delegates/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ElementAccess/Cs6_ElementAccess.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class Class1\n    {\n        public void Method1()\n        {\n            var a = new Class2<Class3>[10];\n            a[1] = a[2];\n        }\n    }\n}\n\nnamespace B\n{\n    class Class2<T>\n    {\n    }\n\n    class Class3\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ElementAccess/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_EveryUserDefinedTypeKind/Cs6_EveryUserDefinedTypeKind.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class Foo\n    {\n        private MyClass x1;\n        private IMyInterface x2;\n        private MyStruct x3;\n        private MyEnum x4;\n        private MyDelegate x5;\n    }\n}\n\nnamespace B\n{\n    class MyClass { }\n    interface IMyInterface { }\n    struct MyStruct { }\n    enum MyEnum { }\n    delegate void MyDelegate();\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_EveryUserDefinedTypeKind/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ExtensionMethodInvocation/Cs6_ExtensionMethodInvocation.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        void MyMethod()\n        {\n            new MyClass().MyExtensionMethod();\n            new MyClass().MyGenericExtensionMethod();\n        }\n    }\n}\n\nnamespace B\n{\n    using A;\n\n    static class MyClassExtensions\n    {\n        public static void MyExtensionMethod(this MyClass myClass)\n        {\n        }\n\n        public static void MyGenericExtensionMethod<T>(this T t)\n        {\n        }   \n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ExtensionMethodInvocation/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n    <Allowed From=\"B\" To=\"A\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_GenericName/Cs6_GenericName.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        // Generic type is not allowed\n        private MyGenericClass<MyClass2> e1;\n\n        // Generic type and some type arguments are not allowed\n        private MyGenericClass2<MyClass3, MyClass2, MyClass3> e2;\n\n        // Generic type, nested generic type and type argument are not allowed\n        private MyGenericClass<MyGenericClass<MyClass3>> e3;\n    }\n\n    class MyClass2 { }\n}\n\nnamespace B\n{\n    class MyGenericClass<T1> { }\n\n    class MyGenericClass2<T1, T2, T3> { }\n\n    class MyClass3 { }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_GenericName/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_GenericTypeArgument/Cs6_GenericTypeArgument.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        private MyGenericClass<MyClass2> e1;\n        private A.MyGenericClass<B.MyClass2> e2;\n    }\n\n    class MyGenericClass<T1> { }\n}\n\nnamespace B\n{\n    class MyClass2 { }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_GenericTypeArgument/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_InvocationExpression/Cs6_InvocationExpression.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class Class1\n    {\n        void Method1()\n        {\n            Method2();\n            new Class2().Method3();\n            Class2.Method4();\n            Class2.Method5();\n        }\n\n        C.Class3 Method2() { return null; }\n    }\n}\n\nnamespace B\n{\n    using C;\n\n    class Class2\n    {\n        public Class3 Method3()\n        {\n            return null;\n        }\n\n        public static Class3 Method4()\n        {\n            return null;\n        }\n\n        public static Class4<Class3> Method5()\n        {\n            return null;\n        }\n    }\n}\n\nnamespace C\n{\n    class Class3\n    {\n    }\n\n    class Class4<T>\n    {\n    }\n}\n\n\n\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_InvocationExpression/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"System\"/>\n    <Allowed From=\"A\" To=\"B\"/>\n    <Allowed From=\"B\" To=\"C\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_InvocationWithTypeArg/Cs6_InvocationWithTypeArg.cs",
    "content": "﻿namespace A\n{\n    using B;\n    using C;\n\n    class Class1\n    {\n        void Method1()\n        {\n            Class2.Method2<Class3>();\n            Class2.Method2<Class4<Class3>>();\n        }\n    }\n}\n\nnamespace B\n{\n    static class Class2\n    {\n        public static void Method2<T>()\n        {\n        }\n    }\n}\n\nnamespace C\n{\n    class Class3\n    {\n    }\n\n    class Class4<T>\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_InvocationWithTypeArg/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"System\"/>\n    <Allowed From=\"A\" To=\"B\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_MemberAccessExpression/Cs6_MemberAccessExpression.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        void MyMethod()\n        {\n            object o = MyOtherClass.MyProperty;\n        }\n    }\n}\n\nnamespace B\n{\n    static class MyOtherClass\n    {\n        public static C.MyEnum MyProperty { get; set; }\n    }\n}\n\nnamespace C\n{\n    enum MyEnum\n    {\n        Value1\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_MemberAccessExpression/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"System\"/>\n    <Allowed From=\"A\" To=\"B\"/>\n    <Allowed From=\"B\" To=\"C\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_NestedType/Cs6_NestedType.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        private MyClass2.MySubclass e1;\n        private B.MyClass2.MySubclass e2;\n    }\n}\n\nnamespace B\n{\n    class MyClass2 \n    {\n        public class MySubclass { }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_NestedType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_NullableType/Cs6_NullableType.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        private MyStruct? e;\n    }\n}\n\nnamespace B\n{\n    struct MyStruct { }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_NullableType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ObjectCreationExpression/Cs6_ObjectCreationExpression.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    class MyClass\n    {\n        void MyMethod()\n        {\n            new MyOtherClass();\n        }\n    }\n}\n\nnamespace B\n{\n    class MyOtherClass { }\n}\n\n\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_ObjectCreationExpression/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_PointerType/Cs6_PointerType.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    unsafe class Class1\n    {\n        private C.Class3* e;\n\n        private void Method1()\n        {\n            Class2.Method2();\n            Class2.Method3();\n        }\n    }\n}\n\nnamespace B\n{\n    using C;\n\n    unsafe class Class2\n    {\n        public static Class3* Method2() { return null; }\n        public static Class3** Method3() { return null; }\n    }\n}\n\nnamespace C\n{\n    struct Class3\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_PointerType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"B\" />\n    <Allowed From=\"B\" To=\"C\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_QualifiedName/Cs6_QualifiedName.cs",
    "content": "﻿namespace A\n{\n    class MyClass\n    {\n        private B.MyEnum e;\n    }\n}\n\nnamespace B\n{\n    enum MyEnum\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_QualifiedName/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_StaticImport/Cs6_StaticImport.cs",
    "content": "﻿namespace B\n{\n    using static A.ClassA;\n\n    public class ClassB\n    {\n        public void CallA()\n        {\n            IsCalledReturnsVoid();    // #60 call dependency itself is ignored\n            IsCalledReturnsClassA();  // #60 produces warning based on return type (but not on the call itself)\n        }\n    }\n}\n\nnamespace A\n{\n    public class ClassA\n    {\n        public static void IsCalledReturnsVoid() { _ = new ClassA();}\n        public static ClassA IsCalledReturnsClassA() { return new ClassA(); }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_StaticImport/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"B.*\" To=\"A.*\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Var/Cs6_Var.cs",
    "content": "﻿namespace A\n{\n    public class Class1\n    {\n        public void Method()\n        {\n            var a = B.MyEnum.EnumValue1;\n        }\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    {\n        EnumValue1\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_Var/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_VarWithConstructedGenericType/Cs6_VarWithConstructedGenericType.cs",
    "content": "﻿namespace A\n{\n    public class ClassA\n    {\n        public void Method()\n        {\n            // var and Instance should have 3 dependency violations each (generic type ClassB and type arguments EnumB)\n            var b = B.ClassB<B.EnumB, EnumA, B.EnumB>.Instance;\n        }\n    }\n\n    public enum EnumA\n    {\n    }\n}\n\nnamespace B\n{\n    public enum EnumB\n    {\n    }\n\n    public class ClassB<T1, T2, T3>\n    {\n        public static ClassB<T1, T2, T3> Instance;\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_VarWithConstructedGenericType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_VeryComplexType/Cs6_VeryComplexType.cs",
    "content": "﻿namespace A\n{\n    using B;\n    using C;\n\n    unsafe class Class1\n    {\n        private void Method1()\n        {\n            Class4<Class3[], Class4<Class3*[], Class3[][]>> a = Class2.Method2();\n        }\n    }\n}\n\nnamespace B\n{\n    using C;\n\n    unsafe class Class2\n    {\n        public static Class4<Class3[], Class4<Class3*[], Class3[][]>> Method2() { return null; }\n    }\n}\n\nnamespace C\n{\n    struct Class3\n    {\n    }\n\n    class Class4<T1, T2>\n    {\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs6_VeryComplexType/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"A\" To=\"B\" />\n    <Allowed From=\"B\" To=\"C\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7Tests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests that the analyzer handles various C# 7.0 constructs correctly.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    public class Cs7Tests\n    {\n        [Fact]\n        public void Cs7_Out()\n        {\n            SourceTestSpecification.Create()\n                // out MyEnum x -- this is a variable declaration so only the type name is checked and not the variable.\n                .ExpectInvalidSegment(11, 45, 51)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_Tuples()\n        {\n            SourceTestSpecification.Create()\n\n                // public (Class1, Class2) Method1()\n                .ExpectInvalidSegment(10, 25, 31)\n                // return (new Class1(), new Class2());\n                .ExpectInvalidSegment(13, 39, 45)\n\n                // public (Class1 class1, Class2 class2) Method2()\n                .ExpectInvalidSegment(17, 32, 38)\n                // return (class1: new Class1(), class2: new Class2());\n                .ExpectInvalidSegment(20, 55, 61)\n\n                // var a = Method2() | var -> Class2 | Method2 -> Class2\n                .ExpectInvalidSegment(26, 13, 16)\n                .ExpectInvalidSegment(26, 21, 28)\n\n                // a.Item2 = null; | a -> Class2 | Item2 -> Class2\n                .ExpectInvalidSegment(28, 13, 14)\n                .ExpectInvalidSegment(28, 15, 20)\n\n                // a.class4 = null; | a -> Class2 | class4 -> Class2\n                .ExpectInvalidSegment(30, 13, 14)\n                .ExpectInvalidSegment(30, 15, 21)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_Deconstruction()\n        {\n            SourceTestSpecification.Create()\n\n                // (var a, var b) = Method2();\n                .ExpectInvalidSegment(13, 21, 24)\n\n                // (_, var c) = Method2();\n                .ExpectInvalidSegment(16, 17, 20)\n\n                // var (d, e) = Method2();\n                .ExpectInvalidSegment(19, 13, 16)\n\n                // Class2 g;\n                .ExpectInvalidSegment(23, 13, 19)\n                // (f, g) = Method2();\n                .ExpectInvalidSegment(24, 17, 18)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_IsExpressionWithPattern()\n        {\n            SourceTestSpecification.Create()\n\n                // Class2 o\n                .ExpectInvalidSegment(7, 28, 34)\n\n                // o is Class3 class3 (type pattern)\n                .ExpectInvalidSegment(9, 17, 18)\n                .ExpectInvalidSegment(9, 22, 28)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_SwitchWithPattern()\n        {\n            SourceTestSpecification.Create()\n\n                // case Class2 class2 when class2 != null:\n                .ExpectInvalidSegment(11, 22, 28)\n                .ExpectInvalidSegment(11, 41, 47)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_LocalFunction()\n        {\n            SourceTestSpecification.Create()\n\n                // Class2 LocalFunction(Class2 class2)\n                .ExpectInvalidSegment(9, 13, 19)\n                .ExpectInvalidSegment(9, 34, 40)\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_ThrowExpression()\n        {\n            SourceTestSpecification.Create()\n\n                // throw new MyException();\n                .ExpectInvalidSegment(9, 43, 54)\n                .Execute();\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_1_DefaultLiteral/Cs7_1_DefaultLiteral.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        // https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.1/target-typed-default.md\n\n        public Class2 M1(Class2 p1 = default)\n        {\n            Class2 x = default;\n            var a = new[] {default, x};\n            return default;\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_1_DefaultLiteral/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_1_InferredTupleNames/Cs7_1_InferredTupleNames.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        // https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.1/infer-tuple-names.md\n\n        public void M1(Class2 p1)\n        {\n            var tuple = (p1.F1, p1.F2);\n\n            var f1 = tuple.F1;\n            var f2 = tuple.F2;\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    {\n        public int F1;\n        public int F2;\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_1_InferredTupleNames/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_1_Tests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests that the analyzer handles various C# 7.1 constructs correctly.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    // ReSharper disable once InconsistentNaming\n    public class Cs7_1_Tests\n    {\n        [Fact]\n        public void Cs7_1_DefaultLiteral()\n        {\n            SourceTestSpecification.Create()\n\n                // public Class2 M1(Class2 p1 = default)\n                .ExpectInvalidSegment(11, 16, 22)\n                .ExpectInvalidSegment(11, 26, 32)\n                .ExpectInvalidSegment(11, 38, 45)\n\n                // Class2 x = default;\n                .ExpectInvalidSegment(13, 13, 19)\n                .ExpectInvalidSegment(13, 24, 31)\n\n                // var a = new[] { default, x };\n                .ExpectInvalidSegment(14, 13, 16)\n                .ExpectInvalidSegment(14, 28, 35)\n                .ExpectInvalidSegment(14, 37, 38)\n\n                // return default;\n                .ExpectInvalidSegment(15, 20, 27)\n\n                .Execute();\n        }\n\n        [Fact]\n        public void Cs7_1_InferredTupleNames()\n        {\n            SourceTestSpecification.Create()\n                \n                // public void M1(Class2 p1)\n                .ExpectInvalidSegment(11, 24, 30)\n\n                // var tuple = (p1.F1, p1.F2);\n                .ExpectInvalidSegment(13, 26, 28)\n                .ExpectInvalidSegment(13, 33, 35)\n\n                .Execute();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_2_NonTrailingNamedArguments/Cs7_2_NonTrailingNamedArguments.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        // https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/non-trailing-named-arguments.md\n\n        public void M1(Class2 p1, Class2 p2)\n        {\n            M1(p1: p1, p2);\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_2_NonTrailingNamedArguments/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_2_Tests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests that the analyzer handles various C# 7.2 constructs correctly.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    // ReSharper disable once InconsistentNaming\n    public class Cs7_2_Tests\n    {\n        [Fact]\n        public void Cs7_2_NonTrailingNamedArguments()\n        {\n            SourceTestSpecification.Create()\n\n                // public void M1(Class2 p1, Class2 p2)\n                .ExpectInvalidSegment(11, 24, 30)\n                .ExpectInvalidSegment(11, 35, 41)\n\n                // M1(p1: p1, p2);\n                .ExpectInvalidSegment(13, 20, 22)\n                .ExpectInvalidSegment(13, 24, 26)\n\n                .Execute();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_3_AttributeOnPropertyBackingField/Cs7_3_AttributeOnPropertyBackingField.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    [Serializable]\n    public class Class1\n    {\n        [field: NonSerialized]\n        public Class1 P1 { get; set; }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_3_AttributeOnPropertyBackingField/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_3_Tests.cs",
    "content": "﻿using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Tests that the analyzer handles various C# 7.3 constructs correctly.\n    /// </summary>\n    /// <remarks>\n    /// The name of the source file and its containing folder is the same as the name of the test.\n    /// </remarks>\n    // ReSharper disable once InconsistentNaming\n    public class Cs7_3_Tests\n    {\n        [Fact]\n        public void Cs7_3_AttributeOnPropertyBackingField()\n        {\n            SourceTestSpecification.Create()\n\n                // [Serializable]\n                .ExpectInvalidSegment(5, 6, 18)\n\n                // [field: NonSerialized]\n                .ExpectInvalidSegment(8, 17, 30)\n\n                .Execute();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Deconstruction/Cs7_Deconstruction.cs",
    "content": "﻿using System;\nusing A;\nusing B;\nusing C;\n\nnamespace A\n{\n    public class Class1\n    {\n        public void Method()\n        {\n            // deconstructing declaration\n            (var a, var b) = Method2();\n\n            // deconstructing declaration with discard\n            (_, var c) = Method2();\n\n            // deconstructing declaration with var outside\n            var (d, e) = Method2();\n\n            // deconstructing assignment\n            Class1 f;\n            Class2 g;\n            (f, g) = Method2();\n        }\n\n        public Deconstructable Method2() => throw new NotImplementedException();\n    }\n}\n\nnamespace B\n{\n    public class Deconstructable\n    {\n        public Class1 Class1 { get; set; }\n        public Class2 Class2 { get; set; }\n\n        public void Deconstruct(out Class1 class1, out Class2 class2)\n        {\n            class1 = Class1;\n            class2 = Class2;\n        }\n    }\n}\n\nnamespace C\n{\n    public class Class2\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Deconstruction/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"A\" To=\"C\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_IsExpressionWithPattern/Cs7_IsExpressionWithPattern.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    public class Class1\n    {\n        public void Method(Class2 o)\n        {\n            if (o is Class3 class3) return;\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    { }\n\n    public class Class3 : Class2\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_IsExpressionWithPattern/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_LocalFunction/Cs7_LocalFunction.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    public class Class1\n    {\n        public void Method()\n        {\n            Class2 LocalFunction(Class2 class2) => null;\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_LocalFunction/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Out/Cs7_Out.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        public void Method()\n        {\n            Enum.TryParse(\"EnumValue1\", out MyEnum x);\n        }\n    }\n}\n\nnamespace B\n{\n    public enum MyEnum\n    {\n        EnumValue1\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Out/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_SwitchWithPattern/Cs7_SwitchWithPattern.cs",
    "content": "﻿namespace A\n{\n    using B;\n\n    public class Class1\n    {\n        public void Method(object o)\n        {\n            switch (o)\n            {\n                case Class2 class2 when class2 != null:\n                    break;\n            }\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_SwitchWithPattern/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_ThrowExpression/Cs7_ThrowExpression.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        public void Method() => throw new MyException();\n    }\n}\n\nnamespace B\n{\n    public class MyException : Exception\n    { }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_ThrowExpression/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"System\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Tuples/Cs7_Tuples.cs",
    "content": "﻿using System;\n\nnamespace A\n{\n    using B;\n\n    public class Class1\n    {\n        // Tuple return type\n        public (Class1, Class2) Method1()\n        {\n            // Tuple literal\n            return (new Class1(), new Class2());\n        }\n\n        // Named tuple elements\n        public (Class1 class1, Class2 class2) Method2()\n        {\n            // Named tuple elements in tuple literal\n            return (class1: new Class1(), class2: new Class2());\n        }\n\n        public void Method3()\n        {\n            // Get tuple value\n            var a = Method2();\n            // Access tuple element by defalt name\n            a.Item2 = null;\n            // Access tuple element by name\n            a.class2 = null;\n        }\n    }\n}\n\nnamespace B\n{\n    public class Class2\n    {\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/Cs7_Tuples/config.nsdepcop",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n    <Allowed From=\"*\" To=\"*\" />\n    <Disallowed From=\"A\" To=\"B\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.SourceTest/FileBasedTestsBase.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    /// <summary>\n    /// Abstract base class for test classes that manipulate test files.\n    /// </summary>\n    public abstract class FileBasedTestsBase\n    {\n        protected static string GetExecutingAssemblyDirectory() => GetAssemblyDirectory(Assembly.GetExecutingAssembly());\n\n        protected static string GetAssemblyPath(Assembly assembly)\n        {\n            return assembly.Location;\n        }\n\n        protected static string GetAssemblyDirectory(Assembly assembly)\n        {\n            var assemblyPath = GetAssemblyPath(assembly);\n            return Path.GetDirectoryName(assemblyPath);\n        }\n\n        protected static string GetBinFilePath(string filename)\n        {\n            return Path.Combine(GetExecutingAssemblyDirectory(), filename);\n        }\n\n        protected string LoadFile(string fullPath)\n        {\n            using (var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))\n            using (var streamReader = new StreamReader(stream))\n            {\n                return streamReader.ReadToEnd();\n            }\n        }\n\n        protected static void Rename(string fromFilename, string toFilename)\n        {\n            if (File.Exists(fromFilename))\n            {\n                if (File.Exists(toFilename))\n                    throw new InvalidOperationException($\"Cannot rename '{fromFilename}' to '{toFilename}' because it already exists.\");\n\n                File.Move(fromFilename, toFilename);\n            }\n        }\n\n        protected static void Delete(string filename)\n        {\n            if (File.Exists(filename))\n                File.Delete(filename);\n\n            while (File.Exists(filename))\n                Thread.Sleep(100);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.SourceTest/NsDepCop.SourceTest.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <RootNamespace>Codartis.NsDepCop.SourceTest</RootNamespace>\n    <IsPackable>false</IsPackable>\n    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n    <LangVersion>latest</LangVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Include\\CommonAssemblyInfo.cs\" Link=\"Properties\\CommonAssemblyInfo.cs\" />\n    <Compile Include=\"..\\Include\\VersionInfo.cs\" Link=\"Properties\\VersionInfo.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"FluentAssertions\" Version=\"7.0.0\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.12.0\" />\n    <PackageReference Include=\"xunit\" Version=\"2.9.2\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.8.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\NsDepCop.Analyzer\\NsDepCop.Analyzer.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Compile Remove=\"AnalyzerFeature_AllowedDependency\\AnalyzerFeature_AllowedDependency.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_SameNamespaceAlwaysAllowed\\AnalyzerFeature_SameNamespaceAlwaysAllowed.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined\\AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_ChildCanDependOnParentImplicitly\\AnalyzerFeature_ChildCanDependOnParentImplicitly.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_ParentCanDependOnChildImplicitly\\AnalyzerFeature_ParentCanDependOnChildImplicitly.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_VisibleMembersOfNamespace\\AnalyzerFeature_VisibleMembersOfNamespace.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_WithTopLevelStatement\\AnalyzerFeature_WithTopLevelStatement.cs\" />\n    <Compile Remove=\"Cs7_IsExpressionWithPattern\\Cs7_IsExpressionWithPattern.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_SwitchWithPattern\\Cs7_SwitchWithPattern.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_LocalFunction\\Cs7_LocalFunction.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_ThrowExpression\\Cs7_ThrowExpression.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_Deconstruction\\Cs7_Deconstruction.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_VisibleMembersOfAllowedRule\\AnalyzerFeature_VisibleMembersOfAllowedRule.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_DisallowedDependency\\AnalyzerFeature_DisallowedDependency.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_2_NonTrailingNamedArguments\\Cs7_2_NonTrailingNamedArguments.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_3_AttributeOnPropertyBackingField\\Cs7_3_AttributeOnPropertyBackingField.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_ExcludedFiles\\AnalyzerFeature_ExcludedFiles.cs\">\n\n    </Compile>\n    <Compile Remove=\"AnalyzerFeature_ExcludedFiles_WithWildcard\\AnalyzerFeature_ExcludedFiles_WithWildcard.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_1_DefaultLiteral\\Cs7_1_DefaultLiteral.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_1_InferredTupleNames\\Cs7_1_InferredTupleNames.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_ObjectCreationExpression\\Cs6_ObjectCreationExpression.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_VeryComplexType\\Cs6_VeryComplexType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_VarWithConstructedGenericType\\Cs6_VarWithConstructedGenericType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_Var\\Cs6_Var.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_QualifiedName\\Cs6_QualifiedName.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_StaticImport\\Cs6_StaticImport.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_PointerType\\Cs6_PointerType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_NullableType\\Cs6_NullableType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_NestedType\\Cs6_NestedType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_MemberAccessExpression\\Cs6_MemberAccessExpression.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_InvocationWithTypeArg\\Cs6_InvocationWithTypeArg.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_InvocationExpression\\Cs6_InvocationExpression.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_GenericTypeArgument\\Cs6_GenericTypeArgument.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_GenericName\\Cs6_GenericName.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_ExtensionMethodInvocation\\Cs6_ExtensionMethodInvocation.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_EveryUserDefinedTypeKind\\Cs6_EveryUserDefinedTypeKind.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_ElementAccess\\Cs6_ElementAccess.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_Delegates\\Cs6_Delegates.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_Tuples\\Cs7_Tuples.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs7_Out\\Cs7_Out.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_Attributes\\Cs6_Attributes.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_ArrayType\\Cs6_ArrayType.cs\">\n\n    </Compile>\n    <Compile Remove=\"Cs6_AliasQualifiedName\\Cs6_AliasQualifiedName.cs\">\n\n    </Compile>\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Include=\"AnalyzerFeature_AllowedDependency\\AnalyzerFeature_AllowedDependency.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_ParentCanDependOnChildImplicitly\\AnalyzerFeature_ParentCanDependOnChildImplicitly.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_SameNamespaceAlwaysAllowed\\AnalyzerFeature_SameNamespaceAlwaysAllowed.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined\\AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_ChildCanDependOnParentImplicitly\\AnalyzerFeature_ChildCanDependOnParentImplicitly.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_VisibleMembersOfNamespace\\AnalyzerFeature_VisibleMembersOfNamespace.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_WithTopLevelStatement\\AnalyzerFeature_WithTopLevelStatement.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_IsExpressionWithPattern\\Cs7_IsExpressionWithPattern.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_SwitchWithPattern\\Cs7_SwitchWithPattern.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_LocalFunction\\Cs7_LocalFunction.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_ThrowExpression\\Cs7_ThrowExpression.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_Deconstruction\\Cs7_Deconstruction.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_VisibleMembersOfAllowedRule\\AnalyzerFeature_VisibleMembersOfAllowedRule.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_DisallowedDependency\\AnalyzerFeature_DisallowedDependency.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_2_NonTrailingNamedArguments\\Cs7_2_NonTrailingNamedArguments.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_3_AttributeOnPropertyBackingField\\Cs7_3_AttributeOnPropertyBackingField.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_ExcludedFiles\\AnalyzerFeature_ExcludedFiles.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"AnalyzerFeature_ExcludedFiles_WithWildcard\\AnalyzerFeature_ExcludedFiles_WithWildcard.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_1_DefaultLiteral\\Cs7_1_DefaultLiteral.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_1_InferredTupleNames\\Cs7_1_InferredTupleNames.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_ObjectCreationExpression\\Cs6_ObjectCreationExpression.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_VeryComplexType\\Cs6_VeryComplexType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_VarWithConstructedGenericType\\Cs6_VarWithConstructedGenericType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_Var\\Cs6_Var.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_QualifiedName\\Cs6_QualifiedName.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_StaticImport\\Cs6_StaticImport.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_PointerType\\Cs6_PointerType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_NullableType\\Cs6_NullableType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_NestedType\\Cs6_NestedType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_MemberAccessExpression\\Cs6_MemberAccessExpression.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_InvocationWithTypeArg\\Cs6_InvocationWithTypeArg.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_InvocationExpression\\Cs6_InvocationExpression.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_GenericTypeArgument\\Cs6_GenericTypeArgument.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_GenericName\\Cs6_GenericName.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_ExtensionMethodInvocation\\Cs6_ExtensionMethodInvocation.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_EveryUserDefinedTypeKind\\Cs6_EveryUserDefinedTypeKind.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_ElementAccess\\Cs6_ElementAccess.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_Delegates\\Cs6_Delegates.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_Tuples\\Cs7_Tuples.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs7_Out\\Cs7_Out.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_Attributes\\Cs6_Attributes.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_ArrayType\\Cs6_ArrayType.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Cs6_AliasQualifiedName\\Cs6_AliasQualifiedName.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_ParentCanDependOnChildImplicitly\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"AnalyzerFeature_AllowedDependency\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_ChildCanDependOnParentImplicitly\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_DisallowedDependency\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_ExcludedFiles\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_ExcludedFiles_WithWildcard\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_SameNamespaceAlwaysAllowed\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_VisibleMembersOfAllowedRule\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_VisibleMembersOfNamespace\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"AnalyzerFeature_WithTopLevelStatement\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_AliasQualifiedName\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_ArrayType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_Attributes\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_Delegates\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_ElementAccess\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_EveryUserDefinedTypeKind\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_ExtensionMethodInvocation\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_GenericName\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_GenericTypeArgument\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_InvocationExpression\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_InvocationWithTypeArg\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_MemberAccessExpression\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_NestedType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_NullableType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_ObjectCreationExpression\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_PointerType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_QualifiedName\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_StaticImport\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_VarWithConstructedGenericType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_Var\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs6_VeryComplexType\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_1_DefaultLiteral\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_1_InferredTupleNames\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_2_NonTrailingNamedArguments\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_3_AttributeOnPropertyBackingField\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_Deconstruction\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_IsExpressionWithPattern\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_LocalFunction\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_Out\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_SwitchWithPattern\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_ThrowExpression\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Cs7_Tuples\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.SourceTest/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\n\n[assembly: AssemblyTitle(\"NsDepCop.Analyzer.SourceTest\")]\n[assembly: AssemblyDescription(\"Tests the dependency analyzer with source files.\")]\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/SourceLineSegment.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    public readonly struct SourceLineSegment\n    {\n        public int Line { get; }\n        public int StartColumn { get; }\n        public int EndColumn { get; }\n\n        public SourceLineSegment(int line, int startColumn, int endColumn)\n        {\n            Line = line;\n            StartColumn = startColumn;\n            EndColumn = endColumn;\n        }\n\n        public bool Equals(SourceSegment sourceSegment)\n        {\n            return Line == sourceSegment.StartLine\n                && Line == sourceSegment.EndLine\n                && StartColumn == sourceSegment.StartColumn\n                && EndColumn == sourceSegment.EndColumn;\n        }\n\n        public override string ToString() => $\"({Line},{StartColumn}-{EndColumn})\";\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.SourceTest/SourceTestSpecification.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Factory;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config.Factory;\nusing Codartis.NsDepCop.ParserAdapter.Roslyn;\nusing FluentAssertions;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n    internal sealed class SourceTestSpecification : FileBasedTestsBase\n    {\n        private static readonly CSharpParseOptions CSharpParseOptions = new(LanguageVersion.Latest);\n\n        private readonly string _name;\n        private readonly ITypeDependencyEnumerator _typeDependencyEnumerator;\n        private readonly List<SourceLineSegment> _invalidLineSegments = new();\n        private readonly List<string[]> _allowedMemberNames = new();\n\n        private SourceTestSpecification(string name, ITypeDependencyEnumerator typeDependencyEnumerator)\n        {\n            _name = name;\n            _typeDependencyEnumerator = typeDependencyEnumerator;\n        }\n\n        public static SourceTestSpecification Create([CallerMemberName] string name = null)\n            => new(name, new TypeDependencyEnumerator(new SyntaxNodeAnalyzer(), DebugMessageHandler));\n\n        public SourceTestSpecification ExpectInvalidSegment(int line, int startColumn, int endColumn)\n        {\n            _invalidLineSegments.Add(new SourceLineSegment(line, startColumn, endColumn));\n            return this;\n        }\n\n        public SourceTestSpecification ExpectInvalidSegment(int line, int startColumn, int endColumn, string[] expectedAllowedMemberNames)\n        {\n            _invalidLineSegments.Add(new SourceLineSegment(line, startColumn, endColumn));\n            _allowedMemberNames.Add(expectedAllowedMemberNames);\n            return this;\n        }\n\n        public void Execute(OutputKind? outputKind = null)\n        {\n            var sourceFilePaths = new[] {_name}.Select(GetTestFileFullPath).ToList();\n            var referencedAssemblyPaths = GetReferencedAssemblyPaths().ToList();\n\n            ValidateCompilation(sourceFilePaths, referencedAssemblyPaths, outputKind ?? OutputKind.DynamicallyLinkedLibrary);\n            AssertIllegalDependencies(sourceFilePaths, referencedAssemblyPaths);\n        }\n\n        private static void DebugMessageHandler(string message) => Debug.WriteLine(message);\n\n        private void ValidateCompilation(IEnumerable<string> sourceFiles, IEnumerable<string> referencedAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary)\n        {\n            var compilation = CSharpCompilation.Create(\n                \"NsDepCopProject\",\n                sourceFiles.Select(i => CSharpSyntaxTree.ParseText(LoadFile(i), CSharpParseOptions)),\n                referencedAssemblies.Select(i => MetadataReference.CreateFromFile(i)),\n                new CSharpCompilationOptions(outputKind, allowUnsafe: true));\n\n            var errors = compilation.GetDiagnostics().Where(i => i.Severity == DiagnosticSeverity.Error).ToList();\n            errors.Should().HaveCount(0);\n        }\n\n        private void AssertIllegalDependencies(IEnumerable<string> sourceFiles, IEnumerable<string> referencedAssemblies)\n        {\n            var baseFolder = GetBinFilePath(_name);\n            var illegalDependencies = GetIllegalDependencies(baseFolder, sourceFiles, referencedAssemblies).ToList();\n\n            illegalDependencies.Select(i => i.IllegalDependency.SourceSegment)\n                .Should().Equal(_invalidLineSegments,\n                    (typeDependency, sourceLineSegment) => sourceLineSegment.Equals(typeDependency));\n\n            List<string[]> membersFromGenerator = illegalDependencies\n                .Select(i => i.AllowedMemberNames)\n                .Where(amn => amn.Any())\n                .ToList();\n\n            membersFromGenerator.Count.Should().Be(_allowedMemberNames.Count);\n\n            for (int i = 0; i < membersFromGenerator.Count; i++)\n            {\n                membersFromGenerator[i].Should().BeEquivalentTo(_allowedMemberNames[i]);\n            }\n        }\n\n        private IEnumerable<IllegalDependencyMessage> GetIllegalDependencies(string baseFolder,\n            IEnumerable<string> sourceFiles, IEnumerable<string> referencedAssemblies)\n        {\n            var dependencyAnalyzerFactory = new DependencyAnalyzerFactory(DebugMessageHandler);\n            var configProvider = new ConfigProviderFactory(DebugMessageHandler).CreateFromMultiLevelXmlConfigFile(baseFolder);\n            var dependencyAnalyzer = dependencyAnalyzerFactory.Create(configProvider, _typeDependencyEnumerator);\n            return dependencyAnalyzer.AnalyzeProject(sourceFiles, referencedAssemblies).OfType<IllegalDependencyMessage>();\n        }\n\n        private static string GetTestFileFullPath(string testName)\n        {\n            var relativeTestFilePath = Path.Combine(testName, testName + \".cs\");\n            return Path.Combine(GetBinFilePath(relativeTestFilePath));\n        }\n\n        private static IEnumerable<string> GetReferencedAssemblyPaths()\n        {\n            return new[]\n            {\n                // mscorlib\n                GetAssemblyPath(typeof(object).Assembly),\n            };\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/FileBasedTestsBase.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace Codartis.NsDepCop.Test\n{\n    /// <summary>\n    /// Abstract base class for test classes that manipulate test files.\n    /// </summary>\n    public abstract class FileBasedTestsBase\n    {\n        protected static string GetExecutingAssemblyDirectory() => GetAssemblyDirectory(Assembly.GetExecutingAssembly());\n\n        protected static string GetAssemblyPath(Assembly assembly)\n        {\n            return assembly.Location;\n        }\n\n        protected static string GetAssemblyDirectory(Assembly assembly)\n        {\n            var assemblyPath = GetAssemblyPath(assembly);\n            return Path.GetDirectoryName(assemblyPath);\n        }\n\n        protected static string GetBinFilePath(string filename)\n        {\n            return Path.Combine(GetExecutingAssemblyDirectory(), filename);\n        }\n\n        protected string GetFilePathInTestClassFolder(string filename)\n        {\n            var namespacePrefix = $\"Codartis.{this.GetType().Assembly.GetName().Name}\";\n            var namespacePostfix = GetType().FullName.Remove(0, namespacePrefix.Length + 1).Replace('.', '/');\n\n            return GetBinFilePath(Path.Combine(namespacePostfix, filename));\n        }\n\n        protected string LoadFile(string fullPath)\n        {\n            using (var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))\n            using (var streamReader = new StreamReader(stream))\n            {\n                return streamReader.ReadToEnd();\n            }\n        }\n\n        protected static void Rename(string fromFilename, string toFilename)\n        {\n            if (File.Exists(fromFilename))\n            {\n                if (File.Exists(toFilename))\n                    throw new InvalidOperationException($\"Cannot rename '{fromFilename}' to '{toFilename}' because it already exists.\");\n\n                File.Move(fromFilename, toFilename);\n            }\n        }\n\n        protected static void Delete(string filename)\n        {\n            if (File.Exists(filename))\n                File.Delete(filename);\n\n            while (File.Exists(filename))\n                Thread.Sleep(100);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/AssemblyDependencyAnalyzerTests.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Microsoft.CodeAnalysis;\nusing Moq;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    public class AssemblyDependencyAnalyzerTests\n    {\n        private static AssemblyIdentity SourceAssembly = AssemblyIdentity.FromAssemblyDefinition(typeof(AssemblyDependencyAnalyzerTests).Assembly);\n        private static AssemblyIdentity ReferencedAssemblyOne = AssemblyIdentity.FromAssemblyDefinition(typeof(string).Assembly);\n        private static AssemblyIdentity ReferencedAssemblyTwo = AssemblyIdentity.FromAssemblyDefinition(typeof(Assert).Assembly);\n\n        private readonly Mock<IUpdateableConfigProvider> _configProviderMock = new();\n        private readonly Mock<IAnalyzerConfig> _configMock = new();\n\n        [Fact]\n        public void NoConfig_ReturnsNoConfigMessage()\n        {\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.NoConfig);\n\n            AnalyzeProject().OfType<NoConfigFileMessage>().Should().HaveCount(1);\n        }\n\n        [Fact]\n        public void ConfigDisabled_ReturnsConfigDisabledMessage()\n        {\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.Disabled);\n\n            AnalyzeProject().OfType<ConfigDisabledMessage>().Should().HaveCount(1);\n        }\n\n        [Fact]\n        public void ConfigError_ReturnsConfigErrorMessage()\n        {\n            var theException = new Exception();\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.ConfigError);\n            _configProviderMock.Setup(i => i.ConfigException).Returns(theException);\n\n            var configErrorMessages = AnalyzeProject().OfType<ConfigErrorMessage>().ToList();\n            configErrorMessages.Should().HaveCount(1);\n            configErrorMessages.First().Exception.Should().Be(theException);\n        }\n\n        [Fact]\n        public void AnalyzeProject_TwoIllegalAssemblyDependencyMessagesReturned()\n        {\n            // Arrange\n            SetUpEnabledConfig();\n\n            // Act\n            var actual = AnalyzeProject().OfType<IllegalAssemblyDependencyMessage>();\n\n            // Assert\n            actual.Should().HaveCount(2);\n        }\n\n        [Fact]\n        public void AnalyzeProject_NoIllegalAssemblyDependencyMessageReturned()\n        {\n            // Arrange\n            SetUpEnabledConfig(checkAssemblyDependencies: false);\n\n            // Act\n            var actual = AnalyzeProject().OfType<ConfigDisabledMessage>();\n\n            // Assert\n            actual.Should().HaveCount(1);\n        }\n\n        [Fact]\n        public void AnalyzeProject_NoIllegalAssemblyDependencyMessageReturnedWhenAllowedAssemblyRulesDefined()\n        {\n            // Arrange\n            SetUpEnabledConfig();\n            _configMock.Setup(i => i.AllowedAssemblyRules).Returns([\n                new DependencyRule(\n                    from: DomainSpecificationParser.Parse(SourceAssembly.Name),\n                    to: DomainSpecificationParser.Parse(ReferencedAssemblyOne.Name)\n                ),\n                new DependencyRule(\n                    from: DomainSpecificationParser.Parse(SourceAssembly.Name),\n                    to: DomainSpecificationParser.Parse(ReferencedAssemblyTwo.Name)\n                )\n            ]);\n\n            // Act\n            var actual = AnalyzeProject().OfType<IllegalAssemblyDependencyMessage>();\n\n            // Assert\n            actual.Should().BeEmpty();\n        }\n\n        [Fact]\n        public void AnalyzeProject_OneIllegalAssemblyDependencyMessageReturnedWhenDisallowedAssemblyRulesDefined()\n        {\n            // Arrange\n            SetUpEnabledConfig();\n            _configMock.Setup(i => i.AllowedAssemblyRules).Returns([\n                new DependencyRule(\n                    from: DomainSpecificationParser.Parse(\"*\"),\n                    to: DomainSpecificationParser.Parse(\"*\")\n                )\n            ]);\n            _configMock.Setup(i => i.DisallowedAssemblyRules).Returns([\n                new DependencyRule(\n                    from: DomainSpecificationParser.Parse(SourceAssembly.Name),\n                    to: DomainSpecificationParser.Parse(ReferencedAssemblyTwo.Name)\n                )\n            ]);\n\n            // Act\n            var actual = AnalyzeProject().OfType<IllegalAssemblyDependencyMessage>();\n\n            // Assert\n            actual.Should().HaveCount(1);\n        }\n\n        private void SetUpEnabledConfig(bool checkAssemblyDependencies = true)\n        {\n            _configMock.Setup(i => i.AllowedAssemblyRules).Returns(new HashSet<DependencyRule>());\n            _configMock.Setup(i => i.DisallowedAssemblyRules).Returns(new HashSet<DependencyRule>());\n            _configMock.Setup(i => i.CheckAssemblyDependencies).Returns(checkAssemblyDependencies);\n\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.Enabled);\n            _configProviderMock.Setup(i => i.ConfigException).Returns<Exception>(null);\n            _configProviderMock.Setup(i => i.Config).Returns(_configMock.Object);\n        }\n\n        private IEnumerable<AnalyzerMessageBase> AnalyzeProject()\n        {\n            return CreateDependencyAnalyzer().AnalyzeProject(\n                SourceAssembly, [ReferencedAssemblyOne, ReferencedAssemblyTwo]\n            );\n        }\n\n        private IAssemblyDependencyAnalyzer CreateDependencyAnalyzer()\n        {\n            return new AssemblyDependencyAnalyzer(_configProviderMock.Object);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/CachingTypeDependencyValidatorTests.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    public class CachingTypeDependencyValidatorTests\n    {\n        [Fact]\n        public void NoRule_SameNamespaceIsAlwaysAllowed()\n        {\n            var ruleConfig = new DependencyRulesBuilder();\n\n            var cachingTypeDependencyValidator = CreateCachingTypeDependencyValidator(ruleConfig);\n            cachingTypeDependencyValidator.IsAllowedDependency(\"N\", \"C1\", \"N\", \"C2\").Should().BeTrue();\n        }\n\n        [Fact]\n        public void ValidatingATypeDependencyTwice_FirstCacheMissThenCacheHit()\n        {\n            var ruleConfig = new DependencyRulesBuilder();\n\n            var cachingTypeDependencyValidator = CreateCachingTypeDependencyValidator(ruleConfig);\n\n            cachingTypeDependencyValidator.IsAllowedDependency(\"N1\", \"C1\", \"N2\", \"C2\").Should().BeFalse();\n            cachingTypeDependencyValidator.MissCount.Should().Be(1);\n            cachingTypeDependencyValidator.HitCount.Should().Be(0);\n\n            cachingTypeDependencyValidator.IsAllowedDependency(\"N1\", \"C1\", \"N2\", \"C2\").Should().BeFalse();\n            cachingTypeDependencyValidator.MissCount.Should().Be(1);\n            cachingTypeDependencyValidator.HitCount.Should().Be(1);\n        }\n\n        private static CachingTypeDependencyValidator CreateCachingTypeDependencyValidator(IDependencyRules ruleConfig)\n            => new CachingTypeDependencyValidator(ruleConfig, traceMessageHandler: null);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/DependencyAnalyzerTests.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Config;\nusing DotNet.Globbing;\nusing FluentAssertions;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing Moq;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    public class DependencyAnalyzerTests\n    {\n        private static readonly SourceSegment DummySourceSegment = new(1, 1, 1, 1, null, null);\n\n        private readonly Mock<IUpdateableConfigProvider> _configProviderMock = new();\n        private readonly Mock<IAnalyzerConfig> _configMock = new();\n        private readonly Mock<ITypeDependencyEnumerator> _typeDependencyEnumeratorMock = new();\n\n        [Fact]\n        public void NoConfig_ReturnsNoConfigMessage()\n        {\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.NoConfig);\n\n            AnalyzeProject().OfType<NoConfigFileMessage>().Should().HaveCount(1);\n            AnalyzeSyntaxNode().OfType<NoConfigFileMessage>().Should().HaveCount(1);\n        }\n\n        [Fact]\n        public void ConfigDisabled_ReturnsConfigDisabledMessage()\n        {\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.Disabled);\n\n            AnalyzeProject().OfType<ConfigDisabledMessage>().Should().HaveCount(1);\n            AnalyzeSyntaxNode().OfType<ConfigDisabledMessage>().Should().HaveCount(1);\n        }\n\n        [Fact]\n        public void ConfigError_ReturnsConfigErrorMessage()\n        {\n            var theException = new Exception();\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.ConfigError);\n            _configProviderMock.Setup(i => i.ConfigException).Returns(theException);\n\n            {\n                var configErrorMessages = AnalyzeProject().OfType<ConfigErrorMessage>().ToList();\n                configErrorMessages.Should().HaveCount(1);\n                configErrorMessages.First().Exception.Should().Be(theException);\n            }\n            {\n                var configErrorMessages = AnalyzeSyntaxNode().OfType<ConfigErrorMessage>().ToList();\n                configErrorMessages.Should().HaveCount(1);\n                configErrorMessages.First().Exception.Should().Be(theException);\n            }\n        }\n\n        [Fact]\n        public void AnalyzeProject_TypeDependenciesReturned()\n        {\n            SetUpEnabledConfig();\n\n            _typeDependencyEnumeratorMock\n                .Setup(i => i.GetTypeDependencies(It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<Glob>>()))\n                .Returns(Enumerable.Repeat(new TypeDependency(\"N1\", \"T1\", \"N2\", \"T2\", DummySourceSegment), 2));\n\n            AnalyzeProject().OfType<IllegalDependencyMessage>().Should().HaveCount(2);\n        }\n\n        [Fact]\n        public void AnalyzeSyntaxNode_TypeDependenciesReturned()\n        {\n            SetUpEnabledConfig();\n\n            _typeDependencyEnumeratorMock\n                .Setup(i => i.GetTypeDependencies(It.IsAny<SyntaxNode>(), It.IsAny<SemanticModel>(), It.IsAny<IEnumerable<Glob>>()))\n                .Returns(Enumerable.Repeat(new TypeDependency(\"N1\", \"T1\", \"N2\", \"T2\", DummySourceSegment), 2));\n\n            AnalyzeSyntaxNode().OfType<IllegalDependencyMessage>().Should().HaveCount(2);\n        }\n\n        [Fact(Skip = \"MaxIssueCount temporarily not working for AnalyzeProject.\")]\n        public void RefreshConfig_Works()\n        {\n            SetUpEnabledConfig(maxIssueCount: 2);\n\n            _typeDependencyEnumeratorMock\n                .Setup(i => i.GetTypeDependencies(It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<Glob>>()))\n                .Returns(Enumerable.Repeat(new TypeDependency(\"N1\", \"T1\", \"N2\", \"T2\", DummySourceSegment), 10));\n\n            var dependencyAnalyzer = CreateDependencyAnalyzer();\n            dependencyAnalyzer.AnalyzeProject(new List<string>(), new List<string>()).OfType<IllegalDependencyMessage>().Should().HaveCount(2);\n\n            SetUpEnabledConfig(maxIssueCount: 4);\n            dependencyAnalyzer.RefreshConfig();\n            dependencyAnalyzer.AnalyzeProject(new List<string>(), new List<string>()).OfType<IllegalDependencyMessage>().Should().HaveCount(4);\n        }\n\n        [Theory(Skip = \"This feature is temporarily commented out.\")]\n        [InlineData(3, 2, true)]\n        [InlineData(3, 3, false)]\n        [InlineData(3, 4, false)]\n        public void AutoLowerMaxIssueCount_Works(int maxIssueCount, int actualIssueCount, bool isUpdateCalled)\n        {\n            SetUpEnabledConfig(maxIssueCount: maxIssueCount, autoLowerMaxIssueCount: true);\n\n            _typeDependencyEnumeratorMock\n                .Setup(i => i.GetTypeDependencies(It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<IEnumerable<Glob>>()))\n                .Returns(Enumerable.Repeat(new TypeDependency(\"N1\", \"T1\", \"N2\", \"T2\", DummySourceSegment), actualIssueCount));\n\n            var expectedIssueCount = Math.Min(actualIssueCount, maxIssueCount);\n\n            AnalyzeProject().OfType<IllegalDependencyMessage>().Should().HaveCount(expectedIssueCount);\n\n            if (isUpdateCalled)\n                _configProviderMock.Verify(i => i.UpdateMaxIssueCount(expectedIssueCount));\n            else\n                _configProviderMock.Verify(i => i.UpdateMaxIssueCount(It.IsAny<int>()), Times.Never);\n        }\n\n        private void SetUpEnabledConfig(int maxIssueCount = 100, bool autoLowerMaxIssueCount = false)\n        {\n            _configMock.Setup(i => i.AllowRules).Returns(new Dictionary<DependencyRule, TypeNameSet>());\n            _configMock.Setup(i => i.DisallowRules).Returns(new HashSet<DependencyRule>());\n            _configMock.Setup(i => i.VisibleTypesByNamespace).Returns(new Dictionary<Domain, TypeNameSet>());\n            _configMock.Setup(i => i.MaxIssueCount).Returns(maxIssueCount);\n            _configMock.Setup(i => i.AutoLowerMaxIssueCount).Returns(autoLowerMaxIssueCount);\n\n            _configProviderMock.Setup(i => i.ConfigState).Returns(AnalyzerConfigState.Enabled);\n            _configProviderMock.Setup(i => i.ConfigException).Returns<Exception>(null);\n            _configProviderMock.Setup(i => i.Config).Returns(_configMock.Object);\n        }\n\n        private IEnumerable<AnalyzerMessageBase> AnalyzeProject()\n        {\n            return CreateDependencyAnalyzer().AnalyzeProject(new List<string>(), new List<string>());\n        }\n\n        private IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode()\n        {\n            var syntaxTree = SyntaxFactory.CompilationUnit().SyntaxTree;\n            var dummyCompilation = CSharpCompilation.Create(assemblyName: \"MyAssembly\", syntaxTrees: new[] {syntaxTree});\n            var semanticModel = dummyCompilation.GetSemanticModel(syntaxTree);\n\n            return CreateDependencyAnalyzer().AnalyzeSyntaxNode(SyntaxFactory.IdentifierName(\"dummy\"), semanticModel);\n        }\n\n        private IDependencyAnalyzer CreateDependencyAnalyzer()\n        {\n            return new DependencyAnalyzer(_configProviderMock.Object, _typeDependencyEnumeratorMock.Object, traceMessageHandler: null);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/DependencyRulesBuilder.cs",
    "content": "﻿using System.Collections.Generic;\nusing Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    /// <summary>\n    /// Helper class for unit testing. Enables rule config building.\n    /// </summary>\n    public class DependencyRulesBuilder : IDependencyRules\n    {\n        private readonly Dictionary<DependencyRule, TypeNameSet> _allowedDependencies;\n        private readonly HashSet<DependencyRule> _disallowedDependencies;\n        private readonly Dictionary<Domain, TypeNameSet> _visibleTypesByTargetNamespace;\n        private readonly HashSet<DependencyRule> _allowedAssemblyDependencies;\n        private readonly HashSet<DependencyRule> _disallowedAssemblyDependencies;\n\n        public DependencyRulesBuilder()\n        {\n            ChildCanDependOnParentImplicitly = ConfigDefaults.ChildCanDependOnParentImplicitly;\n            ParentCanDependOnChildImplicitly = ConfigDefaults.ParentCanDependOnChildImplicitly;\n            _allowedDependencies = new Dictionary<DependencyRule, TypeNameSet>();\n            _disallowedDependencies = new HashSet<DependencyRule>();\n            _visibleTypesByTargetNamespace = new Dictionary<Domain, TypeNameSet>();\n            _allowedAssemblyDependencies = new HashSet<DependencyRule>();\n            _disallowedAssemblyDependencies = new HashSet<DependencyRule>();\n        }\n\n        public bool ChildCanDependOnParentImplicitly { get; private set; }\n\n        public bool ParentCanDependOnChildImplicitly { get; }\n\n        public Dictionary<DependencyRule, TypeNameSet> AllowRules => _allowedDependencies;\n        public HashSet<DependencyRule> DisallowRules => _disallowedDependencies;\n        public Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace => _visibleTypesByTargetNamespace;\n        public HashSet<DependencyRule> AllowedAssemblyRules => _allowedAssemblyDependencies;\n        public HashSet<DependencyRule> DisallowedAssemblyRules => _disallowedAssemblyDependencies;\n\n        public DependencyRulesBuilder SetChildCanDependOnParentImplicitly(bool value)\n        {\n            ChildCanDependOnParentImplicitly = value;\n            return this;\n        }\n\n        public DependencyRulesBuilder AddAllowed(DomainSpecification from, DomainSpecification to, params string[] typeNames)\n        {\n            _allowedDependencies.Add(new DependencyRule(from, to), new TypeNameSet(typeNames));\n            return this;\n        }\n\n        public DependencyRulesBuilder AddAllowed(string from, string to, params string[] typeNames)\n        {\n            _allowedDependencies.Add(new DependencyRule(from, to), new TypeNameSet(typeNames));\n            return this;\n        }\n\n        public DependencyRulesBuilder AddDisallowed(string from, string to)\n        {\n            _disallowedDependencies.Add(new DependencyRule(from, to));\n            return this;\n        }\n\n        public DependencyRulesBuilder AddAllowedAssemblyDependency(string from, string to)\n        {\n            _allowedAssemblyDependencies.Add(new DependencyRule(from, to));\n            return this;\n        }\n\n        public DependencyRulesBuilder AddDisallowedAssemblyDependency(string from, string to)\n        {\n            _disallowedAssemblyDependencies.Add(new DependencyRule(from, to));\n            return this;\n        }\n\n        public DependencyRulesBuilder AddVisibleMembers(string targetNamespace, params string[] typeNames)\n        {\n            _visibleTypesByTargetNamespace.Add(new Domain(targetNamespace), new TypeNameSet(typeNames));\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/TypeDependencyValidatorExtensions.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Analysis.Implementation;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    internal static class TypeDependencyValidatorExtensions\n    {\n        private static readonly SourceSegment DummySourceSegment = new SourceSegment(0, 0, 0, 0, null, null);\n\n        public static bool IsAllowedDependency(this TypeDependencyValidator typeDependencyValidator, \n            string fromNamespace, string fromType, string toNamespace, string toType)\n        {\n            var typeDependency = new TypeDependency(fromNamespace, fromType, toNamespace, toType, DummySourceSegment);\n            return typeDependencyValidator.IsAllowedDependency(typeDependency).IsAllowed;\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Analysis/TypeDependencyValidatorTests.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Analysis\n{\n    public class TypeDependencyValidatorTests\n    {\n        [Fact]\n        public void NoRule_SameNamespaceIsAlwaysAllowed()\n        {\n            var ruleConfig = new DependencyRulesBuilder();\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"N\", \"C1\", \"N\", \"C2\").Should().BeTrue();\n        }\n\n        [Fact]\n        public void NoRule_EverythingIsDisallowed_ExceptSameNamespace()\n        {\n            var ruleConfig = new DependencyRulesBuilder();\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"N1\", \"C1\", \"N2\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void AllowRule()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"S\", \"T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C1\", \"T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T1\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void AllowRule_WithSubnamespace()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"S.*\", \"T.*\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S.S1\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T.T1\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C1\", \"T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T1\", \"C2\").Should().BeFalse();\n        }\n        \n        [Fact]\n        public void AllowRule_WithPrefixWildcard()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"*.S\", \"*.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"X.Y.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S.S1\", \"C1\", \"T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T.T1\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C1\", \"T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T1\", \"C2\").Should().BeFalse();\n        }\n        \n        [Fact]\n        public void AllowRule_WithSingleNamespacePrefix()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"?.S\", \"?.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.S\", \"C1\", \"Y.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"Y.T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"B.S\", \"C1\", \"X.Y.T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void AllowRule_WithWildcard()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"A.*.S\", \"U.*.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.V.W.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.X.S\", \"C1\", \"U.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.C.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.S.C\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.V.T.W\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"A1.A.B.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n        }\n        \n        [Fact]\n        public void AllowRule_WithMultipleWildcards()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"A.*.?.S\", \"U.*.T.?\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.T.T1\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.C.S\", \"C1\", \"U.V.T.T1\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.T.T1\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.S\", \"C1\", \"U.T.T1\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.T\", \"C2\").Should().BeFalse();\n        }\n        \n        [Fact]\n        public void AllowRule_WithAnyNamespace()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"*\", \"*\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C1\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S\", \"C1\", \"T1\", \"C2\").Should().BeTrue();\n        }\n        \n        [Fact]\n        public void AllowRule_MoreSpecificRuleWithWildcardsIsStronger()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"A.*.S\", \"U.V.T\", \"C3\")\n                .AddAllowed(\"A.?.?.S\", \"U.V.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.C.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.C.D.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void AllowRule_WildcardRuleIsStrongerThanRegexRule()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"A.*.S\", \"U.V.T\", \"C3\")\n                .AddAllowed(\"/A...S/\", \"U.V.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.V.T\", \"C3\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"A.B.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void DisallowRule_LessSpecificRuleWithWildcardsIsStronger()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddDisallowed(\"A.*.S\", \"U.V.T\")\n                .AddAllowed(\"A.?.?.S\", \"U.V.T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"A.B.C.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"A.B.C.D.S\", \"C1\", \"U.V.T\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void AllowRuleWithVisibleMembers_AffectsOnlyAllowRuleSource()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"S1\", \"T\", \"C1\", \"C2\")\n                .AddAllowed(\"S2\", \"T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C1\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C3\").Should().BeFalse();\n\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C1\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C3\").Should().BeTrue();\n        }\n\n        [Fact]\n        public void AllowRule_GlobalVisibleMembers_AffectsAllRuleSources()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"S1\", \"T\")\n                .AddAllowed(\"S2\", \"T\")\n                .AddVisibleMembers(\"T\", \"C1\", \"C2\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C1\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S1\", \"C\", \"T\", \"C3\").Should().BeFalse();\n\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C1\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C2\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"S2\", \"C\", \"T\", \"C3\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void DisallowRule()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddDisallowed(\"S\", \"T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S\", \"C\", \"T\", \"C1\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void DisallowRule_StrongerThanAllowRule()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddAllowed(\"S\", \"T\")\n                .AddDisallowed(\"S\", \"T\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"S\", \"C\", \"T\", \"C1\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void DisallowRule_ButSameNamespaceShouldBeAllowed()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddDisallowed(\"a.*\", \"a.b.*\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"a.b.c\", \"C1\", \"a.b.c\", \"C2\").Should().BeTrue();\n        }\n\n        [Fact]\n        public void DisallowRule_IsStrongerThanChildCanDependOnParentImplicitly()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .AddDisallowed(\"a.*\", \"a.b.*\")\n                .SetChildCanDependOnParentImplicitly(true);\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"a.b.c\", \"C1\", \"a.b\", \"C2\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void ChildCanDependOnParentImplicitly()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .SetChildCanDependOnParentImplicitly(true);\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"N1.N2\", \"C\", \"N1\", \"C1\").Should().BeTrue();\n            dependencyValidator.IsAllowedDependency(\"N1\", \"C\", \"N1.N2\", \"C1\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void ChildCanDependOnParentImplicitly_ButDisallowWins()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .SetChildCanDependOnParentImplicitly(true)\n                .AddDisallowed(\"N1.N2\", \"N1\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"N1.N2\", \"C\", \"N1\", \"C1\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"N1\", \"C\", \"N1.N2\", \"C1\").Should().BeFalse();\n        }\n\n        [Fact]\n        public void ChildCanDependOnParentImplicitly_ButDisallowWins_WithWildcard()\n        {\n            var ruleConfig = new DependencyRulesBuilder()\n                .SetChildCanDependOnParentImplicitly(true)\n                .AddDisallowed(\"N1.*\", \"N1\");\n\n            var dependencyValidator = CreateTypeDependencyValidator(ruleConfig);\n            dependencyValidator.IsAllowedDependency(\"N1.N2\", \"C\", \"N1\", \"C1\").Should().BeFalse();\n            dependencyValidator.IsAllowedDependency(\"N1\", \"C\", \"N1.N2\", \"C1\").Should().BeFalse();\n        }\n\n        private static TypeDependencyValidator CreateTypeDependencyValidator(IDependencyRules ruleConfig) => new TypeDependencyValidator(ruleConfig);\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/AnalyzerConfigBuilderTests.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Config.Implementation;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Config\n{\n    public class AnalyzerConfigBuilderTests\n    {\n        [Fact]\n        public void ToAnalyzerConfig_AppliesDefaults()\n        {\n            var config = new AnalyzerConfigBuilder().ToAnalyzerConfig();\n\n            config.IsEnabled.Should().Be(ConfigDefaults.IsEnabled);\n            config.ChildCanDependOnParentImplicitly.Should().Be(ConfigDefaults.ChildCanDependOnParentImplicitly);\n            config.MaxIssueCount.Should().Be(ConfigDefaults.MaxIssueCount);\n        }\n\n        [Theory]\n        [InlineData(\"/root\", \"*.cs\", \"/root/*.cs\")]\n        [InlineData(@\"C:\\folder with space\", \"*.cs\", \"C:/folder with space/*.cs\")]\n        [InlineData(@\"C:\\folder with space\", @\"**\\*.cs\", \"C:/folder with space/**/*.cs\")]\n        [InlineData(@\"C:\\folder with space\", @\"D:\\*.cs\", \"D:/*.cs\")]\n        [InlineData(@\"C:\\folder with space\", \"//a folder/b.cs\", \"//a folder/b.cs\")]\n        [InlineData(@\"C:\\folder with space\", \"/*.cs\", \"/*.cs\")]\n        public void ToAnalyzerConfig_ConvertsPathsToRooted(string pathRoot, string pathExclusionPattern, string expectedFullPath)\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddSourcePathExclusionPatterns([pathExclusionPattern])\n                .MakePathsRooted(pathRoot);\n\n            var config = configBuilder.ToAnalyzerConfig();\n\n            // Note that Path.GetFullPath normalizes the path according to the current OS so we can assert equivalence with the expected path.\n            config.SourcePathExclusionPatterns.Select(Path.GetFullPath)\n                .Should().BeEquivalentTo(Path.GetFullPath(expectedFullPath));\n        }\n\n        [Fact]\n        public void SetMethods_WithNonNullValues_OverwriteProperties()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .SetInheritanceDepth(9)\n                .SetIsEnabled(true)\n                .SetChildCanDependOnParentImplicitly(true)\n                .SetCheckAssemblyDependencies(true)\n                .SetMaxIssueCount(42);\n\n            configBuilder.InheritanceDepth.Should().Be(9);\n            configBuilder.IsEnabled.Should().Be(true);\n            configBuilder.ChildCanDependOnParentImplicitly.Should().Be(true);\n            configBuilder.CheckAssemblyDependencies.Should().Be(true);\n            configBuilder.MaxIssueCount.Should().Be(42);\n        }\n\n        [Fact]\n        public void SetMethods_WithNullValues_DoNotOverwriteProperties()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .SetInheritanceDepth(9)\n                .SetIsEnabled(true)\n                .SetChildCanDependOnParentImplicitly(true)\n                .SetCheckAssemblyDependencies(true)\n                .SetMaxIssueCount(42);\n\n            configBuilder\n                .SetInheritanceDepth(null)\n                .SetIsEnabled(null)\n                .SetChildCanDependOnParentImplicitly(null)\n                .SetCheckAssemblyDependencies(null)\n                .SetMaxIssueCount(null);\n\n            configBuilder.InheritanceDepth.Should().Be(9);\n            configBuilder.IsEnabled.Should().Be(true);\n            configBuilder.ChildCanDependOnParentImplicitly.Should().Be(true);\n            configBuilder.CheckAssemblyDependencies.Should().Be(true);\n            configBuilder.MaxIssueCount.Should().Be(42);\n        }\n\n        [Fact]\n        public void AddAllowRule_Works()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddAllowRule(new DependencyRule(\"N1\", \"N2\"))\n                .AddAllowRule(new DependencyRule(\"N3\", \"N4\"), new TypeNameSet { \"T1\", \"T2\" });\n\n            configBuilder\n                .AddAllowRule(new DependencyRule(\"N3\", \"N4\"), new TypeNameSet { \"T2\", \"T3\" })\n                .AddAllowRule(new DependencyRule(\"N5\", \"N6\"), new TypeNameSet { \"T4\" });\n\n            configBuilder.AllowRules.Should().BeEquivalentTo(\n                new Dictionary<DependencyRule, TypeNameSet>\n                {\n                    {new DependencyRule(\"N1\", \"N2\"), null},\n                    {new DependencyRule(\"N3\", \"N4\"), new TypeNameSet {\"T1\", \"T2\", \"T3\"}},\n                    {new DependencyRule(\"N5\", \"N6\"), new TypeNameSet {\"T4\"}},\n                });\n        }\n\n        [Fact]\n        public void AddDisallowRule_Works()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddDisallowRule(new DependencyRule(\"N1\", \"N2\"))\n                .AddDisallowRule(new DependencyRule(\"N3\", \"N4\"));\n\n            configBuilder\n                .AddDisallowRule(new DependencyRule(\"N3\", \"N4\"))\n                .AddDisallowRule(new DependencyRule(\"N5\", \"N6\"));\n\n            configBuilder.DisallowRules.Should().BeEquivalentTo(\n                new HashSet<DependencyRule>\n                {\n                    new DependencyRule(\"N1\", \"N2\"),\n                    new DependencyRule(\"N3\", \"N4\"),\n                    new DependencyRule(\"N5\", \"N6\"),\n                });\n        }\n\n        [Fact]\n        public void AddVisibleTypesByNamespace_Works()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddVisibleTypesByNamespace(new Domain(\"N1\"), null)\n                .AddVisibleTypesByNamespace(new Domain(\"N2\"), new TypeNameSet { \"T1\", \"T2\" });\n\n            configBuilder\n                .AddVisibleTypesByNamespace(new Domain(\"N2\"), new TypeNameSet { \"T2\", \"T3\" })\n                .AddVisibleTypesByNamespace(new Domain(\"N3\"), new TypeNameSet { \"T4\" });\n\n            configBuilder.VisibleTypesByNamespace.Should().BeEquivalentTo(\n                new Dictionary<Domain, TypeNameSet>\n                {\n                    {new Domain(\"N1\"), null},\n                    {new Domain(\"N2\"), new TypeNameSet {\"T1\", \"T2\", \"T3\"}},\n                    {new Domain(\"N3\"), new TypeNameSet {\"T4\"}},\n                });\n        }\n\n        [Fact]\n        public void Combine_EmptyWithEmpty()\n        {\n            var configBuilder1 = new AnalyzerConfigBuilder();\n            var configBuilder2 = new AnalyzerConfigBuilder();\n\n            configBuilder1.Combine(configBuilder2);\n\n            configBuilder1.IsEnabled.Should().BeNull();\n            configBuilder1.ChildCanDependOnParentImplicitly.Should().BeNull();\n            configBuilder1.AllowRules.Should().HaveCount(0);\n            configBuilder1.DisallowRules.Should().HaveCount(0);\n            configBuilder1.VisibleTypesByNamespace.Should().HaveCount(0);\n            configBuilder1.AllowedAssemblyRules.Should().HaveCount(0);\n            configBuilder1.DisallowedAssemblyRules.Should().HaveCount(0);\n            configBuilder1.MaxIssueCount.Should().BeNull();\n        }\n\n        [Fact]\n        public void AddAllowedAssemblyRule_Works()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddAllowedAssemblyRule(new DependencyRule(\"N1\", \"N2\"))\n                .AddAllowedAssemblyRule(new DependencyRule(\"N3\", \"N4\"));\n\n            configBuilder\n                .AddAllowedAssemblyRule(new DependencyRule(\"N3\", \"N4\"))\n                .AddAllowedAssemblyRule(new DependencyRule(\"N5\", \"N6\"));\n\n            configBuilder.AllowedAssemblyRules.Should().BeEquivalentTo(\n                new HashSet<DependencyRule>()\n                {\n                    new DependencyRule(\"N1\", \"N2\"),\n                    new DependencyRule(\"N3\", \"N4\"),\n                    new DependencyRule(\"N5\", \"N6\"),\n                }\n            );\n        }\n\n        [Fact]\n        public void AddDisallowedAssemblyRule_Works()\n        {\n            var configBuilder = new AnalyzerConfigBuilder()\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A1\", \"A2\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A3\", \"A4\"));\n\n            configBuilder\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A3\", \"A4\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A5\", \"A6\"));\n\n            configBuilder.DisallowedAssemblyRules.Should().BeEquivalentTo(\n                new HashSet<DependencyRule>()\n                {\n                    new DependencyRule(\"A1\", \"A2\"),\n                    new DependencyRule(\"A3\", \"A4\"),\n                    new DependencyRule(\"A5\", \"A6\"),\n                }\n            );\n        }\n\n        [Fact]\n        public void Combine_NonEmptyWithEmpty()\n        {\n            var configBuilder1 = new AnalyzerConfigBuilder()\n                .SetIsEnabled(true)\n                .SetChildCanDependOnParentImplicitly(true)\n                .AddAllowRule(new DependencyRule(\"N1\", \"N2\"), new TypeNameSet { \"T1\" })\n                .AddDisallowRule(new DependencyRule(\"N3\", \"N4\"))\n                .AddVisibleTypesByNamespace(new Domain(\"N5\"), new TypeNameSet { \"T2\" })\n                .AddAllowedAssemblyRule(new DependencyRule(\"A1\", \"A2\"))\n                .AddAllowedAssemblyRule(new DependencyRule(\"A3\", \"A4\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A5\", \"A6\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A7\", \"A8\"))\n                .SetMaxIssueCount(42);\n\n            var configBuilder2 = new AnalyzerConfigBuilder();\n\n            configBuilder1.Combine(configBuilder2);\n\n            configBuilder1.IsEnabled.Should().Be(true);\n            configBuilder1.ChildCanDependOnParentImplicitly.Should().Be(true);\n            configBuilder1.AllowRules.Should().HaveCount(1);\n            configBuilder1.DisallowRules.Should().HaveCount(1);\n            configBuilder1.VisibleTypesByNamespace.Should().HaveCount(1);\n            configBuilder1.AllowedAssemblyRules.Should().HaveCount(2);\n            configBuilder1.DisallowedAssemblyRules.Should().HaveCount(2);\n            configBuilder1.MaxIssueCount.Should().Be(42);\n        }\n\n        [Fact]\n        public void Combine_EmptyWithNonEmpty()\n        {\n            var configBuilder1 = new AnalyzerConfigBuilder();\n\n            var configBuilder2 = new AnalyzerConfigBuilder()\n                .SetIsEnabled(true)\n                .SetChildCanDependOnParentImplicitly(true)\n                .AddAllowRule(new DependencyRule(\"N1\", \"N2\"), new TypeNameSet { \"T1\" })\n                .AddDisallowRule(new DependencyRule(\"N3\", \"N4\"))\n                .AddVisibleTypesByNamespace(new Domain(\"N5\"), new TypeNameSet { \"T2\" })\n                .AddAllowedAssemblyRule(new DependencyRule(\"A1\", \"A2\"))\n                .AddAllowedAssemblyRule(new DependencyRule(\"A3\", \"A4\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A5\", \"A6\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A7\", \"A8\"))\n                .SetMaxIssueCount(42);\n\n            configBuilder1.Combine(configBuilder2);\n\n            configBuilder1.IsEnabled.Should().Be(true);\n            configBuilder1.ChildCanDependOnParentImplicitly.Should().Be(true);\n            configBuilder1.AllowRules.Should().HaveCount(1);\n            configBuilder1.DisallowRules.Should().HaveCount(1);\n            configBuilder1.VisibleTypesByNamespace.Should().HaveCount(1);\n            configBuilder1.AllowedAssemblyRules.Should().HaveCount(2);\n            configBuilder1.DisallowedAssemblyRules.Should().HaveCount(2);\n            configBuilder1.MaxIssueCount.Should().Be(42);\n        }\n\n        [Fact]\n        public void Combine_NonEmptyWithNonEmpty()\n        {\n            var configBuilder1 = new AnalyzerConfigBuilder()\n                .SetIsEnabled(false)\n                .SetChildCanDependOnParentImplicitly(false)\n                .AddAllowRule(new DependencyRule(\"N1\", \"N2\"), new TypeNameSet { \"T1\" })\n                .AddDisallowRule(new DependencyRule(\"N3\", \"N4\"))\n                .AddVisibleTypesByNamespace(new Domain(\"N5\"), new TypeNameSet { \"T2\" })\n                .AddAllowedAssemblyRule(new DependencyRule(\"A1\", \"A2\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A3\", \"A4\"))\n                .SetMaxIssueCount(43);\n\n            var configBuilder2 = new AnalyzerConfigBuilder()\n                .SetIsEnabled(true)\n                .SetChildCanDependOnParentImplicitly(true)\n                .AddAllowRule(new DependencyRule(\"N6\", \"N7\"), new TypeNameSet { \"T3\" })\n                .AddDisallowRule(new DependencyRule(\"N8\", \"N9\"))\n                .AddVisibleTypesByNamespace(new Domain(\"N10\"), new TypeNameSet { \"T4\" })\n                .AddAllowedAssemblyRule(new DependencyRule(\"A6\", \"A7\"))\n                .AddAllowedAssemblyRule(new DependencyRule(\"A8\", \"A9\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A9\", \"A9\"))\n                .AddDisallowedAssemblyRule(new DependencyRule(\"A10\", \"A10\"))\n                .SetMaxIssueCount(42);\n\n            configBuilder1.Combine(configBuilder2);\n\n            configBuilder1.IsEnabled.Should().Be(true);\n            configBuilder1.ChildCanDependOnParentImplicitly.Should().Be(true);\n            configBuilder1.AllowRules.Should().HaveCount(2);\n            configBuilder1.DisallowRules.Should().HaveCount(2);\n            configBuilder1.VisibleTypesByNamespace.Should().HaveCount(2);\n            configBuilder1.AllowedAssemblyRules.Should().HaveCount(3);\n            configBuilder1.DisallowedAssemblyRules.Should().HaveCount(3);\n            configBuilder1.MaxIssueCount.Should().Be(42);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Attributes_LowerLevelWins/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" MaxIssueCount=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Attributes_LowerLevelWins/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig MaxIssueCount=\"1\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Attributes_MissingDoesNotOverwrite/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Attributes_MissingDoesNotOverwrite/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig MaxIssueCount=\"1\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"false\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtHigherLevelButEnabledAtProjectLevel/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtHigherLevelButEnabledAtProjectLevel/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"false\" MaxIssueCount=\"1\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtProjectLevel/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"false\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigDisabledAtProjectLevel/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigEnabled/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigEnabled/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigError/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigError/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfigg>\n</NsDepCopConfigg>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ConfigError/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Excluded File 4.cs",
    "content": "﻿class ExcludedFile4\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/ExcludedFile3.cs",
    "content": "﻿class ExcludedFile3\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Level1/Excluded File 2.cs",
    "content": "﻿class ExcludedFile2a\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Level1/ExcludedFile1.cs",
    "content": "﻿class ExcludedFile1a\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" ExcludedFiles=\"ExcludedFile1.cs, Excluded File 2.cs\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig ExcludedFiles=\"ExcludedFile3.cs, Excluded File 4.cs\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/NoConfig/Level2/Level1/placeholder.txt",
    "content": "﻿"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToConfigError/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToConfigError/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToDisabled/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToDisabled/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToEnabledButChanged/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\" IsEnabled=\"true\" AutoLowerMaxIssueCount=\"false\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToEnabledButChanged/config.nsdepcop",
    "content": "﻿<NsDepCopConfig MaxIssueCount=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_EnabledToNoConfig/Level2/Level1/placeholder.txt",
    "content": "﻿"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_InheritanceDepthChanged/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_InheritanceDepthChanged/config.nsdepcop",
    "content": "﻿<NsDepCopConfig MaxIssueCount=\"42\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/RefreshConfig_NoConfigToEnabled/Level2/Level1/placeholder.txt",
    "content": "﻿"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Rules_Merged/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig InheritanceDepth=\"2\">\n    <Allowed From=\"N3\" To=\"N4\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/Rules_Merged/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1\" To=\"N2\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/UpdateMaxIssueCount_Level1ContainsMaxIssueCount/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\" InheritanceDepth=\"1\" MaxIssueCount=\"42\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/UpdateMaxIssueCount_Level1ContainsMaxIssueCount/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount/Level2/Level1/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\" InheritanceDepth=\"1\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount/Level2/config.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\" MaxIssueCount=\"42\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests.cs",
    "content": "﻿using System.IO;\nusing System.Linq;\nusing System.Threading;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Config.Implementation;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Config\n{\n    public class MultiLevelXmlFileConfigProviderTests : XmlFileConfigTestBase\n    {\n        [Fact]\n        public void Rules_Merged()\n        {\n            var folder = GetFilePathInTestClassFolder(@\"Rules_Merged/Level2/Level1\");\n            var configProvider = CreateConfigProvider(folder);\n\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.ConfigException.Should().BeNull();\n\n            var allowedRules = configProvider.Config.AllowRules;\n            allowedRules.Should().HaveCount(2);\n            allowedRules.Keys.Should().Contain(new DependencyRule(\"N1\", \"N2\"));\n            allowedRules.Keys.Should().Contain(new DependencyRule(\"N3\", \"N4\"));\n        }\n\n        [Fact]\n        public void Attributes_LowerLevelWins()\n        {\n            var folder = GetFilePathInTestClassFolder(\"Attributes_LowerLevelWins/Level2/Level1\");\n            var configProvider = CreateConfigProvider(folder);\n            configProvider.Config.MaxIssueCount.Should().Be(2);\n        }\n\n        [Fact]\n        public void Attributes_MissingDoesNotOverwrite()\n        {\n            var folder = GetFilePathInTestClassFolder(\"Attributes_MissingDoesNotOverwrite/Level2/Level1\");\n            var configProvider = CreateConfigProvider(folder);\n            configProvider.Config.MaxIssueCount.Should().Be(1);\n        }\n\n        [Fact]\n        public void ExcludedFiles_AllCorrectlyRooted()\n        {\n            var folder = GetFilePathInTestClassFolder(\"ExcludedFiles_AllCorrectlyRooted/Level2/Level1\");\n\n            var expectedExcludedFiles = new[]\n            {\n                GetFilePathInTestClassFolder(\"ExcludedFiles_AllCorrectlyRooted/Level2/Level1/ExcludedFile1.cs\"),\n                GetFilePathInTestClassFolder(\"ExcludedFiles_AllCorrectlyRooted/Level2/Level1/Excluded File 2.cs\"),\n                GetFilePathInTestClassFolder(\"ExcludedFiles_AllCorrectlyRooted/Level2/ExcludedFile3.cs\"),\n                GetFilePathInTestClassFolder(\"ExcludedFiles_AllCorrectlyRooted/Level2/Excluded File 4.cs\"),\n            };\n\n            var configProvider = CreateConfigProvider(folder);\n            configProvider.Config.SourcePathExclusionPatterns.Select(Path.GetFullPath).Should().BeEquivalentTo(expectedExcludedFiles.Select(Path.GetFullPath));\n            configProvider.Config.SourcePathExclusionPatterns.All(File.Exists).Should().BeTrue();\n        }\n\n        [Fact]\n        public void Properties_ConfigNotFound()\n        {\n            var path = GetFilePathInTestClassFolder(\"NoConfig/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigError()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigError/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.ConfigError);\n            configProvider.ConfigException.Should().NotBeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigEnabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigEnabled/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().NotBeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigDisabledAtProjectLevel_EffectiveDisabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigDisabledAtProjectLevel/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel_EffectiveDisabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigDisabledAtHigherLevelButEnabledAtProjectLevel_DisabledConfigNotCombinedToEffective()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigDisabledAtHigherLevelButEnabledAtProjectLevel/Level2/Level1\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.MaxIssueCount.Should().Be(ConfigDefaults.MaxIssueCount);\n        }\n\n        [Fact]\n        public void RefreshConfig_Unchanged()\n        {\n            var path = GetFilePathInTestClassFolder(\"ConfigEnabled/Level2/Level1\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            var savedConfig = configProvider.Config;\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.Config.Should().Be(savedConfig);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToEnabledButChanged()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToEnabledButChanged/Level2/Level1\");\n            var path2 = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToEnabledButChanged\");\n\n            SetAttribute(GetConfigFilePath(path), \"AutoLowerMaxIssueCount\", \"true\");\n            SetAttribute(GetConfigFilePath(path2), \"MaxIssueCount\", \"1\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.Config.AutoLowerMaxIssueCount.Should().Be(true);\n            configProvider.Config.MaxIssueCount.Should().Be(1);\n\n            Thread.Sleep(10);\n            SetAttribute(GetConfigFilePath(path), \"AutoLowerMaxIssueCount\", \"false\");\n            SetAttribute(GetConfigFilePath(path2), \"MaxIssueCount\", \"2\");\n\n            configProvider.RefreshConfig();\n            configProvider.Config.AutoLowerMaxIssueCount.Should().Be(false);\n            configProvider.Config.MaxIssueCount.Should().Be(2);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToDisabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToDisabled/Level2/Level1\");\n\n            SetAttribute(GetConfigFilePath(path), \"IsEnabled\", \"true\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Thread.Sleep(10);\n            SetAttribute(GetConfigFilePath(path), \"IsEnabled\", \"false\");\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToConfigError()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToConfigError/Level2/Level1\");\n\n            SetAttribute(GetConfigFilePath(path), \"IsEnabled\", \"true\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Thread.Sleep(10);\n            SetAttribute(GetConfigFilePath(path), \"IsEnabled\", \"maybe\");\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.ConfigError);\n        }\n\n        [Fact]\n        public void RefreshConfig_NoConfigToEnabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_NoConfigToEnabled/Level2/Level1\");\n\n            Delete(GetConfigFilePath(path));\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n\n            CreateConfigFile(GetConfigFilePath(path), \"true\", 2);\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToNoConfig()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToNoConfig/Level2/Level1\");\n\n            Delete(path);\n            CreateConfigFile(GetConfigFilePath(path), \"true\", 2);\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Delete(GetConfigFilePath(path));\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n        }\n\n        [Fact]\n        public void RefreshConfig_InheritanceDepthChangedFrom0To2()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_InheritanceDepthChanged/Level2/Level1\");\n\n            SetAttribute(GetConfigFilePath(path), \"InheritanceDepth\", \"0\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.InheritanceDepth.Should().Be(0);\n            configProvider.Config.MaxIssueCount.Should().Be(ConfigDefaults.MaxIssueCount);\n\n            Thread.Sleep(10);\n            SetAttribute(GetConfigFilePath(path), \"InheritanceDepth\", \"2\");\n\n            configProvider.RefreshConfig();\n            configProvider.InheritanceDepth.Should().Be(2);\n            configProvider.Config.MaxIssueCount.Should().Be(42);\n        }\n\n        [Fact]\n        public void RefreshConfig_InheritanceDepthChangedFrom2To0()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_InheritanceDepthChanged/Level2/Level1\");\n\n            SetAttribute(GetConfigFilePath(path), \"InheritanceDepth\", \"2\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.InheritanceDepth.Should().Be(2);\n            configProvider.Config.MaxIssueCount.Should().Be(42);\n\n            Thread.Sleep(10);\n            SetAttribute(GetConfigFilePath(path), \"InheritanceDepth\", \"0\");\n\n            configProvider.RefreshConfig();\n            configProvider.InheritanceDepth.Should().Be(0);\n            configProvider.Config.MaxIssueCount.Should().Be(ConfigDefaults.MaxIssueCount);\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount_SetToNewValue()\n        {\n            var path = GetFilePathInTestClassFolder(\"UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount/Level2/Level1\");\n\n            RemoveAttribute(GetConfigFilePath(path), \"MaxIssueCount\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.Config.MaxIssueCount.Should().Be(42);\n\n            Thread.Sleep(10);\n            configProvider.UpdateMaxIssueCount(142);\n            configProvider.Config.MaxIssueCount.Should().Be(142);\n\n            GetAttribute(GetConfigFilePath(path.Replace(\"/Level1\", \"\")), \"MaxIssueCount\").Should().Be(42.ToString());\n            GetAttribute(GetConfigFilePath(path), \"MaxIssueCount\").Should().Be(142.ToString());\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_Level1ContainsMaxIssueCount_SetToNewValue()\n        {\n            var path = GetFilePathInTestClassFolder(\"UpdateMaxIssueCount_Level1ContainsMaxIssueCount/Level2/Level1\");\n\n            SetAttribute(GetConfigFilePath(path), \"MaxIssueCount\", 42.ToString());\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.Config.MaxIssueCount.Should().Be(42);\n\n            Thread.Sleep(10);\n            configProvider.UpdateMaxIssueCount(142);\n            configProvider.Config.MaxIssueCount.Should().Be(142);\n\n            GetAttribute(GetConfigFilePath(path.Replace(\"/Level1\", \"\")), \"MaxIssueCount\").Should().BeNull();\n            GetAttribute(GetConfigFilePath(path), \"MaxIssueCount\").Should().Be(142.ToString());\n        }\n\n        private static string GetConfigFilePath(string path)\n        {\n            return Path.Combine(path, ProductConstants.DefaultConfigFileName);\n        }\n\n        private static MultiLevelXmlFileConfigProvider CreateConfigProvider(string folder)\n        {\n            return new MultiLevelXmlFileConfigProvider(folder, traceMessageHandler: null);\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedAssemblyRules.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <AllowedAssembly From=\"A1\" To=\"A2\" />\n    <AllowedAssembly From=\"A3\" To=\"A4\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1\" To=\"N2\">\n        <VisibleMembers OfNamespace=\"N2\">\n            <Type Name=\"T1\"/>\n        </VisibleMembers>\n    </Allowed>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedRuleForWildcardNamespaceWithVisibleMembers.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1\" To=\"*\">\n        <VisibleMembers>\n            <Type Name=\"T1\"/>\n        </VisibleMembers>\n    </Allowed>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedRuleFromAttributeMissing.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed To=\"N2\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedRuleToAttributeMissing.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/AllowedRules.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1\" To=\"N2\"/>\n    <Allowed From=\"N3\" To=\"N4\">\n        <VisibleMembers>\n            <Type Name=\"T1\"/>\n            <Type Name=\"T2\"/>\n        </VisibleMembers>\n    </Allowed>\n    <Allowed From=\"N5\" To=\"N6\">\n        <!-- Empty type name set means no restriction. -->\n        <VisibleMembers>\n        </VisibleMembers>\n    </Allowed>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/DisallowedAssemblyRules.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <DisallowedAssembly From=\"A1\" To=\"A2\"/>\n    <DisallowedAssembly From=\"A3\" To=\"A4\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/DisallowedRules.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Disallowed From=\"N1\" To=\"N2\"/>\n    <Disallowed From=\"N3\" To=\"N4\"/>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/InvalidAttributeValue.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"maybe\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/InvalidDuplicatedWildcardNamespaceString.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"N1.*.*.A\" To=\"N2\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/InvalidNamespaceString.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <Allowed From=\"..\" To=\"N2\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/NoRootAttributes.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/NsDepCopConfigElementNotFound.nsdepcop",
    "content": "﻿<NsDepCopConfigg>\n</NsDepCopConfigg>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/RootAttributes.nsdepcop",
    "content": "﻿<NsDepCopConfig\n    InheritanceDepth=\"9\"\n    IsEnabled=\"true\"\n    CodeIssueKind=\"Error\"\n    MaxIssueCount=\"42\"\n    ChildCanDependOnParentImplicitly=\"true\"\n    InfoImportance=\"Normal\"\n    MaxIssueCountSeverity=\"Error\"\n    AutoLowerMaxIssueCount=\"true\" \n    AnalyzerServiceCallRetryTimeSpans=\"100, 1000\"\n    ExcludedFiles=\"**/*.g.cs ,  TestData\\**\\*.cs\"\n    CheckAssemblyDependencies=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/VisibleMembers.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <VisibleMembers OfNamespace=\"N1\">\n        <Type Name=\"T1\"/>\n        <Type Name=\"T2\"/>\n    </VisibleMembers>\n\n    <VisibleMembers OfNamespace=\"N2\">\n        <Type Name=\"T3\"/>\n    </VisibleMembers>\n\n    <!-- Empty type name set means no restriction. -->\n    <VisibleMembers OfNamespace=\"N3\">\n    </VisibleMembers>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/VisibleMembersOfNamespaceMissing.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <VisibleMembers>\n        <Type Name=\"T1\"/>\n    </VisibleMembers>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests/VisibleMembersTypeNameAttributeMissing.nsdepcop",
    "content": "﻿<NsDepCopConfig>\n    <VisibleMembers OfNamespace=\"N1\">\n        <Type/>\n    </VisibleMembers>\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests.cs",
    "content": "﻿using System;\nusing System.Xml.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Config.Implementation;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Config\n{\n    public class XmlConfigParserTests : FileBasedTestsBase\n    {\n        [Fact]\n        public void Parse_NoRootAttributes()\n        {\n            var xDocument = LoadXml(\"NoRootAttributes.nsdepcop\");\n            var configBuilder = XmlConfigParser.Parse(xDocument);\n            configBuilder.IsEnabled.Should().BeNull();\n            configBuilder.InheritanceDepth.Should().BeNull();\n            configBuilder.MaxIssueCount.Should().BeNull();\n            configBuilder.ChildCanDependOnParentImplicitly.Should().BeNull();\n            configBuilder.AutoLowerMaxIssueCount.Should().BeNull();\n            configBuilder.SourcePathExclusionPatterns.Should().BeEmpty();\n            configBuilder.CheckAssemblyDependencies.Should().BeNull();\n        }\n\n        [Fact]\n        public void Parse_RootAttributes()\n        {\n            var xDocument = LoadXml(\"RootAttributes.nsdepcop\");\n            var configBuilder = XmlConfigParser.Parse(xDocument);\n            configBuilder.IsEnabled.Should().BeTrue();\n            configBuilder.InheritanceDepth.Should().Be(9);\n            configBuilder.MaxIssueCount.Should().Be(42);\n            configBuilder.ChildCanDependOnParentImplicitly.Should().BeTrue();\n            configBuilder.AutoLowerMaxIssueCount.Should().BeTrue();\n            configBuilder.SourcePathExclusionPatterns.Should().BeEquivalentTo(\"**/*.g.cs\", @\"TestData\\**\\*.cs\");\n            configBuilder.CheckAssemblyDependencies.Should().BeTrue();\n        }\n\n        [Fact]\n        public void Parse_AllowedRules()\n        {\n            var xDocument = LoadXml(\"AllowedRules.nsdepcop\");\n            var config = XmlConfigParser.Parse(xDocument);\n\n            var allowedRules = config.AllowRules;\n            allowedRules.Should().HaveCount(3);\n            {\n                var types = allowedRules[new DependencyRule(\"N1\", \"N2\")];\n                types.Should().BeNull();\n            }\n            {\n                var types = allowedRules[new DependencyRule(\"N3\", \"N4\")];\n                types.Should().HaveCount(2);\n                types.Should().Contain(\"T1\");\n                types.Should().Contain(\"T2\");\n            }\n            {\n                var types = allowedRules[new DependencyRule(\"N5\", \"N6\")];\n                types.Should().BeNull();\n            }\n        }\n\n        [Fact]\n        public void Parse_DisallowedRules()\n        {\n            var xDocument = LoadXml(\"DisallowedRules.nsdepcop\");\n            var config = XmlConfigParser.Parse(xDocument);\n\n            var disallowedRules = config.DisallowRules;\n            disallowedRules.Should().HaveCount(2);\n\n            disallowedRules.Should().Contain(new DependencyRule(\"N1\", \"N2\"));\n            disallowedRules.Should().Contain(new DependencyRule(\"N3\", \"N4\"));\n        }\n\n        [Fact]\n        public void Parse_VisibleMembers()\n        {\n            var xDocument = LoadXml(\"VisibleMembers.nsdepcop\");\n            var config = XmlConfigParser.Parse(xDocument);\n\n            var visibleTypesByNamespace = config.VisibleTypesByNamespace;\n            visibleTypesByNamespace.Should().HaveCount(2);\n            {\n                var types = visibleTypesByNamespace[new Domain(\"N1\")];\n                types.Should().HaveCount(2);\n                types.Should().Contain(\"T1\");\n                types.Should().Contain(\"T2\");\n            }\n            {\n                var types = visibleTypesByNamespace[new Domain(\"N2\")];\n                types.Should().HaveCount(1);\n                types.Should().Contain(\"T3\");\n            }\n        }\n\n        [Fact]\n        public void Parse_AllowedAssemblyRules()\n        {\n            var xDocument = LoadXml(\"AllowedAssemblyRules.nsdepcop\");\n            var config = XmlConfigParser.Parse(xDocument);\n\n            var allowedAssemblyRules = config.AllowedAssemblyRules;\n            allowedAssemblyRules.Should().HaveCount(2);\n\n            allowedAssemblyRules.Should().Contain(new DependencyRule(\"A1\", \"A2\"));\n            allowedAssemblyRules.Should().Contain(new DependencyRule(\"A3\", \"A4\"));\n        }\n\n        [Fact]\n        public void Parse_DisallowedAssemblyRules()\n        {\n            var xDocument = LoadXml(\"DisallowedAssemblyRules.nsdepcop\");\n            var config = XmlConfigParser.Parse(xDocument);\n\n            var disallowedAssemblyRules = config.DisallowedAssemblyRules;\n            disallowedAssemblyRules.Should().HaveCount(2);\n\n            disallowedAssemblyRules.Should().Contain(new DependencyRule(\"A1\", \"A2\"));\n            disallowedAssemblyRules.Should().Contain(new DependencyRule(\"A3\", \"A4\"));\n        }\n\n        [Fact]\n        public void Parse_AllowedRuleForWildcardNamespaceWithVisibleMembers_Throws()\n        {\n            var xDocument = LoadXml(\"AllowedRuleForWildcardNamespaceWithVisibleMembers.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*must be a single namespace*\");\n        }\n\n        [Fact]\n        public void Parse_AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute_Throws()\n        {\n            var xDocument = LoadXml(\"AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*'OfNamespace' attribute must not be defined*\");\n        }\n\n        [Fact]\n        public void Parse_VisibleMembersOfNamespaceMissing_Throws()\n        {\n            var xDocument = LoadXml(\"VisibleMembersOfNamespaceMissing.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*'OfNamespace' attribute missing*\");\n        }\n\n        [Fact]\n        public void Parse_AllowedRuleFromAttributeMissing_Throws()\n        {\n            var xDocument = LoadXml(\"AllowedRuleFromAttributeMissing.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*'From' attribute missing*\");\n        }\n\n        [Fact]\n        public void Parse_AllowedRuleToAttributeMissing_Throws()\n        {\n            var xDocument = LoadXml(\"AllowedRuleToAttributeMissing.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*'To' attribute missing*\");\n        }\n\n        [Fact]\n        public void Parse_VisibleMembersTypeNameAttributeMissing_Throws()\n        {\n            var xDocument = LoadXml(\"VisibleMembersTypeNameAttributeMissing.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*'Name' attribute missing*\");\n        }\n\n        [Fact]\n        public void Parse_NsDepCopConfigElementNotFound_Throws()\n        {\n            var xDocument = LoadXml(\"NsDepCopConfigElementNotFound.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*root element not found*\");\n        }\n\n        [Fact]\n        public void Parse_InvalidNamespaceString_Throws()\n        {\n            var xDocument = LoadXml(\"InvalidNamespaceString.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*not a valid Domain*\");\n        }\n\n        [Fact]\n        public void Parse_InvalidDuplicatedWildcardNamespaceString_Throws()\n        {\n            var xDocument = LoadXml(\"InvalidDuplicatedWildcardNamespaceString.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*not a valid WildcardDomain*\");\n        }\n\n        [Fact]\n        public void Parse_InvalidAttributeValue_Throws()\n        {\n            var xDocument = LoadXml(\"InvalidAttributeValue.nsdepcop\");\n            Action a = () => XmlConfigParser.Parse(xDocument);\n            a.Should().Throw<Exception>().WithMessage(\"*Error parsing 'IsEnabled' value*\");\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_HasMaxIssueCountAttribute_Works()\n        {\n            const int newMaxIssueCount = 101;\n            var xDocument = LoadXml(\"RootAttributes.nsdepcop\");\n            XmlConfigParser.UpdateMaxIssueCount(xDocument, newMaxIssueCount);\n            xDocument.Element(\"NsDepCopConfig\")?.Attribute(\"MaxIssueCount\")?.Value.Should().Be(newMaxIssueCount.ToString());\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_NoMaxIssueCountAttribute_Works()\n        {\n            const int newMaxIssueCount = 101;\n            var xDocument = LoadXml(\"NoRootAttributes.nsdepcop\");\n            XmlConfigParser.UpdateMaxIssueCount(xDocument, newMaxIssueCount);\n            xDocument.Element(\"NsDepCopConfig\")?.Attribute(\"MaxIssueCount\")?.Value.Should().Be(newMaxIssueCount.ToString());\n        }\n\n        private XDocument LoadXml(string filename)\n        {\n            var path = GetFilePathInTestClassFolder(filename);\n            return XDocument.Load(path);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/Disabled.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"false\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/Enabled.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/Erronous.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"maybe\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/Excluded File 2.cs",
    "content": "﻿class ExcludedFile2b\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/ExcludedFile1.cs",
    "content": "﻿class ExcludedFile1b\n{\n}"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/ExcludedFiles.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\" ExcludedFiles=\"ExcludedFile1.cs, Excluded File 2.cs\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/RefreshConfig_EnabledToConfigError.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/RefreshConfig_EnabledToDisabled.nsdepcop",
    "content": "﻿<NsDepCopConfig IsEnabled=\"true\">\n</NsDepCopConfig>"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Config.Implementation;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Config\n{\n    public class XmlFileConfigProviderTests : XmlFileConfigTestBase\n    {\n        [Fact]\n        public void Properties_ConfigNotFound()\n        {\n            var path = GetFilePathInTestClassFolder(\"NonExisting.nsdepcop\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigEnabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"Enabled.nsdepcop\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().NotBeNull();\n        }\n\n        [Fact]\n        public void Properties_ExcludedFiles_AreRooted()\n        {\n            var path = GetFilePathInTestClassFolder(\"ExcludedFiles.nsdepcop\");\n            var configProvider = CreateConfigProvider(path);\n\n            var expectedExcludedFiles = new[]\n            {\n                GetFilePathInTestClassFolder(\"ExcludedFile1.cs\"),\n                GetFilePathInTestClassFolder(\"Excluded File 2.cs\")\n            };\n\n            var exclusionPatterns = configProvider.Config.SourcePathExclusionPatterns;\n            exclusionPatterns.Select(Path.GetFullPath).Should().BeEquivalentTo(expectedExcludedFiles.Select(Path.GetFullPath));\n            exclusionPatterns.All(File.Exists).Should().BeTrue();\n        }\n\n        [Fact]\n        public void Properties_ConfigDisabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"Disabled.nsdepcop\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n            configProvider.ConfigException.Should().BeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void Properties_ConfigError()\n        {\n            var path = GetFilePathInTestClassFolder(\"Erronous.nsdepcop\");\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.ConfigError);\n            configProvider.ConfigException.Should().NotBeNull();\n            configProvider.Config.Should().BeNull();\n        }\n\n        [Fact]\n        public void RefreshConfig_Unchanged()\n        {\n            var path = GetFilePathInTestClassFolder(\"Enabled.nsdepcop\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            var savedConfig = configProvider.Config;\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n            configProvider.Config.Should().Be(savedConfig);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToDisabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToDisabled.nsdepcop\");\n\n            SetAttribute(path, \"IsEnabled\", \"true\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Thread.Sleep(10);\n            SetAttribute(path, \"IsEnabled\", \"false\");\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToConfigError()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToConfigError.nsdepcop\");\n\n            SetAttribute(path, \"IsEnabled\", \"true\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Thread.Sleep(10);\n            SetAttribute(path, \"IsEnabled\", \"maybe\");\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.ConfigError);\n        }\n\n        [Fact]\n        public void RefreshConfig_NoConfigToEnabled()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_NoConfigToEnabled.nsdepcop\");\n\n            Delete(path);\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n\n            CreateConfigFile(path, \"true\");\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n        }\n\n        [Fact]\n        public void RefreshConfig_EnabledToNoConfig()\n        {\n            var path = GetFilePathInTestClassFolder(\"RefreshConfig_EnabledToNoConfig.nsdepcop\");\n\n            Delete(path);\n            CreateConfigFile(path, \"true\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Enabled);\n\n            Delete(path);\n\n            configProvider.RefreshConfig();\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.NoConfig);\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_DisabledConfig_Throws()\n        {\n            var path = GetFilePathInTestClassFolder(\"UpdateMaxIssueCount_DisabledConfig.nsdepcop\");\n\n            Delete(path);\n            CreateConfigFile(path, \"false\");\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.ConfigState.Should().Be(AnalyzerConfigState.Disabled);\n\n            Action a = () => configProvider.UpdateMaxIssueCount(142);\n            a.Should().Throw<InvalidOperationException>().Where(i => i.Message.Contains(AnalyzerConfigState.Disabled.ToString()));\n\n            Delete(path);\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_FromNoneToNewValue()\n        {\n            var path = GetFilePathInTestClassFolder(\"UpdateMaxIssueCount_FromNoneToNewValue.nsdepcop\");\n\n            Delete(path);\n            CreateConfigFile(path, \"true\", maxIssueCount: null);\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.Config.MaxIssueCount.Should().Be(ConfigDefaults.MaxIssueCount);\n\n            configProvider.UpdateMaxIssueCount(142);\n            configProvider.Config.MaxIssueCount.Should().Be(142);\n\n            Delete(path);\n        }\n\n        [Fact]\n        public void UpdateMaxIssueCount_FromOldValueToNewValue()\n        {\n            var path = GetFilePathInTestClassFolder(\"UpdateMaxIssueCount_FromOldValueToNewValue.nsdepcop\");\n\n            Delete(path);\n            CreateConfigFile(path, \"true\", maxIssueCount: 42);\n\n            var configProvider = CreateConfigProvider(path);\n            configProvider.Config.MaxIssueCount.Should().Be(42);\n\n            configProvider.UpdateMaxIssueCount(142);\n            configProvider.Config.MaxIssueCount.Should().Be(142);\n\n            Delete(path);\n        }\n\n        private static XmlFileConfigProvider CreateConfigProvider(string path)\n        {\n            return new XmlFileConfigProvider(path, traceMessageHandler: null);\n        }\n    }\n}\n\n"
  },
  {
    "path": "source/NsDepCop.Test/Implementation/Config/XmlFileConfigTestBase.cs",
    "content": "﻿using System.Xml.Linq;\n\nnamespace Codartis.NsDepCop.Test.Implementation.Config\n{\n    public class XmlFileConfigTestBase : FileBasedTestsBase\n    {\n        protected static void CreateConfigFile(string path, string isEnabledString, int inheritanceDepth = 0, int? maxIssueCount = null)\n        {\n            var document = XDocument.Parse($\"<NsDepCopConfig InheritanceDepth='{inheritanceDepth}' IsEnabled='{isEnabledString}' {GetMaxIssueCountAttributeString(maxIssueCount)} />\");\n            document.Save(path);\n        }\n\n        private static string GetMaxIssueCountAttributeString(int? maxIssueCount)\n        {\n            return maxIssueCount == null ? string.Empty : $\" MaxIssueCount='{maxIssueCount}' \";\n        }\n\n        protected static string GetAttribute(string path, string attributeName)\n        {\n            var document = XDocument.Load(path);\n            return document.Root.Attribute(attributeName)?.Value;\n        }\n\n        protected static void SetAttribute(string path, string attributeName, string value)\n        {\n            var document = XDocument.Load(path);\n            var xAttribute = document.Root.Attribute(attributeName);\n\n            if (xAttribute == null)\n                document.Root.Add(new XAttribute(attributeName, value));\n            else\n                xAttribute.SetValue(value);\n\n            document.Save(path);\n        }\n\n        protected static void RemoveAttribute(string path, string attributeName)\n        {\n            var document = XDocument.Load(path);\n            document.Root.Attribute(attributeName)?.Remove();\n            document.Save(path);\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Interface/Config/DomainSpecificationParserTests.cs",
    "content": "﻿using System;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Interface.Config\n{\n    public class DomainSpecificationParserTests\n    {\n        [Theory]\n        [InlineData(\".\")]\n        [InlineData(\"A.B\")]\n        public void Parse_DomainSpecification(string domainString)\n        {\n            DomainSpecificationParser.Parse(domainString).Should().Be(new Domain(domainString));\n        }\n\n        [Theory]\n        [InlineData(\"*\")]\n        [InlineData(\"A.*\")]\n        [InlineData(\"A.*.B\")]\n        [InlineData(\"A.?.B\")]\n        [InlineData(\"*.B\")]\n        [InlineData(\"?.B\")]\n        [InlineData(\"A.B.?\")]\n        [InlineData(\"A.B.*\")]\n        public void Parse_WildcardDomainSpecification(string wildcardDomainString)\n        {\n            DomainSpecificationParser.Parse(wildcardDomainString).Should().Be(new WildcardDomain(wildcardDomainString));\n        }\n\n        [Theory]\n        [InlineData(\"/Unit\\\\.Test/\")]\n        [InlineData(\"/^Unit\\\\.Test$/\")]\n        public void Parse_RegexDomainSpecification(string regexDomainString)\n        {\n            DomainSpecificationParser.Parse(regexDomainString).Should().Be(new RegexDomain(regexDomainString));\n        }\n\n        [Theory]\n        [InlineData(\"..\")]\n        [InlineData(\".A\")]\n        [InlineData(\"A.\")]\n        [InlineData(\"*.*\")]\n        [InlineData(\"/foo{2,1}/\")]\n        public void Parse_Invalid(string invalidString)\n        {\n            Assert.Throws<FormatException>(() => DomainSpecificationParser.Parse(invalidString));\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Interface/Config/DomainSpecificationTests.cs",
    "content": "﻿using System.Linq;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Interface.Config\n{\n    public class DomainSpecificationTests\n    {\n        [Theory]\n        [InlineData(\"A.B\", \"D\", 0)]\n        [InlineData(\"A.B\", \"D.*\", 0)]\n        [InlineData(\"A.B\", \"A.B.C.*\", 0)]\n        [InlineData(\"A.B\", \"A\", 0)]\n        [InlineData(\"A.B\", \".\", 0)]\n        [InlineData(\"A.B\", \"A.B\", int.MaxValue)]\n        [InlineData(\"A.B\", \"A.?\", int.MaxValue - 1)]\n        [InlineData(\"A.B\", \"A.*\", int.MaxValue - 2)]\n        [InlineData(\"A.B\", \"A.B.*\", int.MaxValue - 1)]\n        [InlineData(\"A.B\", \"A.B.?\", 0)]\n        [InlineData(\"A.B\", \"/A\\\\.B/\", 1)]\n        [InlineData(\"A.B\", \"/A\\\\../\", 1)]\n        [InlineData(\"A.B\", \"/A\\\\.[A-Z]/\", 1)]\n        [InlineData(\"A.B\", \"/A\\\\.[0-9]/\", 0)]\n        [InlineData(\"A.C.D\", \"B.?.D\", 0)]\n        [InlineData(\"A.C.D\", \"*.E\", 0)]\n        [InlineData(\"A.C.D\", \"A.C.D\", int.MaxValue)]\n        [InlineData(\"A.C.D\", \"A.?.D\", int.MaxValue - 1)]\n        [InlineData(\"A.C.D\", \"A.C.?\", int.MaxValue - 1)]\n        [InlineData(\"A.C.D\", \"?.C.D\", int.MaxValue - 1)]\n        [InlineData(\"A.C.D\", \"A.?.?\", int.MaxValue - 2)]\n        [InlineData(\"A.C.D\", \"?.?.D\", int.MaxValue - 2)]\n        [InlineData(\"A.C.D\", \"?.?.?\", int.MaxValue - 3)]\n        [InlineData(\"A.C.D\", \"A.*\", int.MaxValue - 3)]\n        [InlineData(\"A.C.D\", \"*.D\", int.MaxValue - 3)]\n        [InlineData(\"A.C.D\", \"*.?.D\", int.MaxValue - 3)]\n        [InlineData(\"A.B.C.D\", \"*.?.D\", int.MaxValue - 4)]\n        [InlineData(\"A.C.D\", \"*\", int.MaxValue - 4)]\n        [InlineData(\"A.F1.B.C\", \"A.*.B\", 0)]\n        [InlineData(\"A.F1.B.C\", \"A.*.B.*\", int.MaxValue - 4)]\n        [InlineData(\"A.F1.B.C\", \"A.*.B.?\", int.MaxValue - 3)]\n        [InlineData(\"A.F1.B.C\", \"A.?.B.?\", int.MaxValue - 2)]\n        [InlineData(\"A.F1.B.C\", \"A.?.B.*\", int.MaxValue - 3)]\n        public void GetMatchRelevance_ShouldReturnTheExpectedValue(string domainString, string domainSpecificationString, int expectedMatchRelevance)\n        {\n            var domain = new Domain(domainString);\n            var domainSpecification = DomainSpecificationParser.Parse(domainSpecificationString);\n            domainSpecification.GetMatchRelevance(domain).Should().Be(expectedMatchRelevance);\n        }\n\n        /// <summary>\n        /// This test verifies that the matching rules are prioritized correctly, according to their match relevance.\n        /// </summary>\n        [Theory]\n        [InlineData(\"A.B\", \"A.B\", \"A.B.*\", \"A.?\", \"A.*\", \"/A\\\\.B/\")]\n        public void GetMatchRelevance_ShouldPrioritizeProperly(string domainString, params string[] domainSpecificationStrings)\n        {\n            var domain = new Domain(domainString);\n            var domainSpecifications = domainSpecificationStrings.Select(DomainSpecificationParser.Parse);\n            domainSpecifications.Select(i => i.GetMatchRelevance(domain)).Should().BeInDescendingOrder();\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Interface/Config/DomainTests.cs",
    "content": "﻿using System;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Interface.Config\n{\n    public class DomainTests\n    {\n        [Theory]\n        [InlineData(\"A\")]\n        [InlineData(\"A.B\")]\n        [InlineData(\".\")]\n        public void Create_Works(string domainString)\n        {\n            new Domain(domainString).ToString().Should().Be(domainString);\n        }\n\n        [Theory]\n        [InlineData(\"<global namespace>\")]\n        [InlineData(\"\")]\n        public void Create_GlobalDomainRepresentationNormalized(string globalDomainString)\n        {\n            new Domain(globalDomainString).ToString().Should().Be(\".\");\n        }\n\n        [Fact]\n        public void Create_WithNull_ThrowsArgumentNullException()\n        {\n            Assert.Throws<ArgumentNullException>(() => new Domain(null));\n        }\n\n        [Theory]\n        [InlineData(\"*\")]\n        [InlineData(\"A.*\")]\n        public void Create_AnyDomain_ThrowsFormatException(string domainString)\n        {\n            Assert.Throws<FormatException>(() => new Domain(domainString));\n        }\n\n        [Fact]\n        public void IsSubDomainOf_Works()\n        {\n            new Domain(\"A\").IsSubDomain(new Domain(\".\")).Should().BeTrue();\n            new Domain(\"A.B\").IsSubDomain(new Domain(\".\")).Should().BeTrue();\n\n            new Domain(\"A.B\").IsSubDomain(new Domain(\"A\")).Should().BeTrue();\n            new Domain(\"A.B.C\").IsSubDomain(new Domain(\"A\")).Should().BeTrue();\n\n            new Domain(\".\").IsSubDomain(new Domain(\"A\")).Should().BeFalse();\n            new Domain(\"A\").IsSubDomain(new Domain(\"A\")).Should().BeFalse();\n            new Domain(\"A\").IsSubDomain(new Domain(\"A.B\")).Should().BeFalse();\n        }\n\n        [Fact]\n        public void Equals_Works()\n        {\n            (new Domain(\"A\") == new Domain(\"A\")).Should().BeTrue();\n            (new Domain(\"A\") == new Domain(\"B\")).Should().BeFalse();\n        }\n\n        [Fact]\n        public void GlobalDomain_IsEqualToOtherInstanceOfGlobalDomain()\n        {\n            (new Domain(\".\") == Domain.GlobalDomain).Should().BeTrue();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/Interface/Config/RegexDomainTests.cs",
    "content": "using System;\nusing System.Diagnostics.CodeAnalysis;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Interface.Config;\n\npublic sealed class RegexDomainTests\n{\n    [Theory]\n    [InlineData(\"/Unit\\\\.Test/\")]\n    [InlineData(\"/^Unit\\\\.Test(\\\\.[A-Za-z_][A-Za-z0-9_]*)*$/\")]\n    public void Create_Works(string regexDomainString)\n    {\n        new RegexDomain(regexDomainString).ToString().Should().Be(regexDomainString);\n    }\n\n    [Fact]\n    public void Create_WithNull_ThrowsArgumentNullException()\n    {\n        var act = () => new RegexDomain(null);\n        act.Should().Throw<ArgumentNullException>();\n    }\n\n    [Theory]\n    [InlineData(\"\")]\n    [InlineData(\"//\")]\n    [InlineData(\"^Unit\\\\.Test(\\\\.[A-Za-z_][A-Za-z0-9_]*)*$\")]\n    [InlineData(\"/foo{2,1}/\")]\n    [InlineData(\"/(abc\\\\Kdef)/\")]\n    [InlineData(\"/((a|b|)/\")]\n    public void Create_InvalidRegexDomain_ThrowsFormatException(string regexDomainString)\n    {\n        var act = () => new RegexDomain(regexDomainString);\n        act.Should().Throw<FormatException>();\n    }\n\n    [Fact]\n    [SuppressMessage(\"ReSharper\", \"EqualExpressionComparison\")]\n    public void Equals_Works()\n    {\n        (new RegexDomain(\"/Unit\\\\.Test/\") == new RegexDomain(\"/Unit\\\\.Test/\")).Should().BeTrue();\n        (new RegexDomain(\"/Unit\\\\.Test/\") == new RegexDomain(\"/^Unit\\\\.Test$/\")).Should().BeFalse();\n    }\n\n    [Fact]\n    public void GetMatchRelevance_WhenTimeoutOccurs_ShouldReturnNoMatch_WithoutThrowingException()\n    {\n        var rule = new RegexDomain(\"/(a|aa)+$/\", regexTimeout: TimeSpan.FromTicks(1));\n        var domain = new Domain(new string('a', 10));\n        var action = () => rule.GetMatchRelevance(domain);\n        action.Should().NotThrow();\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Test/Interface/Config/WildcardDomainTests.cs",
    "content": "﻿using System;\nusing System.Diagnostics.CodeAnalysis;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.Interface.Config\n{\n    public class WildcardDomainTests\n    {\n        [Theory]\n        [InlineData(\"*\")]\n        [InlineData(\"A.*\")]\n        [InlineData(\"*.A.*\")]\n        [InlineData(\"*.A.?\")]\n        [InlineData(\"*.A.?.B\")]\n        [InlineData(\"A.?.?.B\")]\n        [InlineData(\"A.*.?.?.B\")]\n        public void Create_Works(string wildcardDomainString)\n        {\n            new WildcardDomain(wildcardDomainString).ToString().Should().Be(wildcardDomainString);\n        }\n\n        [Fact]\n        public void Create_WithNull_ThrowsArgumentNullException()\n        {\n            Assert.Throws<ArgumentNullException>(() => new WildcardDomain(null));\n        }\n\n        [Theory]\n        [InlineData(\"A\")]\n        [InlineData(\"A.B\")]\n        public void Create_NotAWildcardDomain_ThrowsFormatException(string wildcardDomainString)\n        {\n            Assert.Throws<FormatException>(() => new WildcardDomain(wildcardDomainString));\n        }\n\n        [Theory]\n        [InlineData(\"\")]\n        [InlineData(\".\")]\n        [InlineData(\"A..\")]\n        [InlineData(\"A.B.\")]\n        [InlineData(\"A.B?.C\")]\n        [InlineData(\"A*.B\")]\n        [InlineData(\"A.**.B\")]\n        [InlineData(\"A.*.*.B\")]\n        [InlineData(\".*.B\")]\n        public void Create_InvalidWildcardDomain_ThrowsFormatException(string wildcardDomainString)\n        {\n            Assert.Throws<FormatException>(() => new WildcardDomain(wildcardDomainString));\n        }\n\n        [Fact]\n        [SuppressMessage(\"ReSharper\", \"EqualExpressionComparison\")]\n        public void Equals_Works()\n        {\n            (new WildcardDomain(\"A.*\") == new WildcardDomain(\"A.*\")).Should().BeTrue();\n            (new WildcardDomain(\"A.*\") == new WildcardDomain(\"B.*\")).Should().BeFalse();\n        }\n\n        [Fact]\n        [SuppressMessage(\"ReSharper\", \"EqualExpressionComparison\")]\n        public void AnyDomain_IsEqualToOtherInstanceOfAnyDomain()\n        {\n            (new WildcardDomain(\"*\") == new WildcardDomain(\"*\")).Should().BeTrue();\n        }\n    }\n}\n"
  },
  {
    "path": "source/NsDepCop.Test/NsDepCop.Test.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <RootNamespace>Codartis.NsDepCop.Test</RootNamespace>\n    <IsPackable>false</IsPackable>\n    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n    <LangVersion>latest</LangVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Include\\CommonAssemblyInfo.cs\" Link=\"Properties\\CommonAssemblyInfo.cs\" />\n    <Compile Include=\"..\\Include\\VersionInfo.cs\" Link=\"Properties\\VersionInfo.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"FluentAssertions\" Version=\"7.0.0\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.12.0\" />\n    <PackageReference Include=\"Moq\" Version=\"4.20.72\" />\n    <PackageReference Include=\"xunit\" Version=\"2.9.2\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.8.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\NsDepCop.Analyzer\\NsDepCop.Analyzer.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\ExcludedFile1.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\Excluded File 2.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\Level1\\Excluded File 2.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\Level1\\ExcludedFile1.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\Excluded File 4.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ExcludedFiles_AllCorrectlyRooted\\Level2\\ExcludedFile3.cs\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Attributes_MissingDoesNotOverwrite\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Attributes_MissingDoesNotOverwrite\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Attributes_LowerLevelWins\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Attributes_LowerLevelWins\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtHigherLevelButEnabledAtProjectLevel\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtHigherLevelButEnabledAtProjectLevel\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\UpdateMaxIssueCount_Level1ContainsMaxIssueCount\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\UpdateMaxIssueCount_Level1ContainsMaxIssueCount\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_InheritanceDepthChanged\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_InheritanceDepthChanged\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToEnabledButChanged\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToEnabledButChanged\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToConfigError\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToConfigError\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToDisabled\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToDisabled\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigEnabled\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigEnabled\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtProjectLevel\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigDisabledAtProjectLevel\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigError\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigError\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\ConfigError\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Rules_Merged\\Level2\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\Rules_Merged\\Level2\\Level1\\config.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedAssemblyRules.nsdepcop\">\n        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\InvalidAttributeValue.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\NsDepCopConfigElementNotFound.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedRuleToAttributeMissing.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\DisallowedAssemblyRules.nsdepcop\">\n        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedRuleFromAttributeMissing.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\InvalidNamespaceString.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\NoRootAttributes.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n      <SubType>Designer</SubType>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\VisibleMembersTypeNameAttributeMissing.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\VisibleMembersOfNamespaceMissing.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedRuleForWildcardNamespaceWithVisibleMembers.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\VisibleMembers.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\DisallowedRules.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\Disabled.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\ExcludedFiles.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\RefreshConfig_EnabledToConfigError.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\RefreshConfig_EnabledToDisabled.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\Erronous.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlFileConfigProviderTests\\Enabled.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\AllowedRules.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Include=\"Implementation\\Config\\XmlConfigParserTests\\RootAttributes.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"Implementation\\Config\\XmlConfigParserTests\\InvalidDuplicatedWildcardNamespaceString.nsdepcop\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n  <ItemGroup>\n    <Content Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\NoConfig\\Level2\\Level1\\placeholder.txt\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_EnabledToNoConfig\\Level2\\Level1\\placeholder.txt\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Include=\"Implementation\\Config\\MultiLevelXmlFileConfigProviderTests\\RefreshConfig_NoConfigToEnabled\\Level2\\Level1\\placeholder.txt\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n  </ItemGroup>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.Test/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\n\n[assembly: AssemblyTitle(\"NsDepCop.Analyzer.Test\")]\n[assembly: AssemblyDescription(\"Unit tests for NsDepCop.Analyzer\")]\n"
  },
  {
    "path": "source/NsDepCop.Test/RoslynAnalyzer/AnalyzerProviderTests.cs",
    "content": "﻿using Codartis.NsDepCop.Analysis;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.RoslynAnalyzer;\nusing Moq;\nusing Xunit;\n\nnamespace Codartis.NsDepCop.Test.RoslynAnalyzer\n{\n    public class AnalyzerProviderTests\n    {\n        private readonly Mock<IDependencyAnalyzerFactory> _dependencyAnalyzerFactoryMock;\n        private readonly Mock<IAssemblyDependencyAnalyzerFactory> _assemblyDependencyAnalyzerFactoryMock;\n        private readonly Mock<IConfigProviderFactory> _configProviderFactoryMock;\n        private readonly Mock<ITypeDependencyEnumerator> _typeDependencyEnumeratorMock;\n\n        public AnalyzerProviderTests()\n        {\n            _dependencyAnalyzerFactoryMock = new Mock<IDependencyAnalyzerFactory>();\n            _assemblyDependencyAnalyzerFactoryMock = new Mock<IAssemblyDependencyAnalyzerFactory>();\n            _configProviderFactoryMock = new Mock<IConfigProviderFactory>();\n            _typeDependencyEnumeratorMock = new Mock<ITypeDependencyEnumerator>();\n        }\n\n        [Fact]\n        public void GetDependencyAnalyzer_RetrievedOnce_CallsFactory()\n        {\n            const string filePath = \"myFilePath\";\n\n            var analyzerProvider = CreateAnalyzerProvider();\n\n            analyzerProvider.GetDependencyAnalyzer(filePath);\n\n            VerifyDependencyAnalyzerFactoryCall(Times.Once());\n        }\n\n        [Fact]\n        public void GetDependencyAnalyzer_RetrievedTwice_CallsFactoryThenAnalyzerRefresh()\n        {\n            const string filePath = \"myFilePath\";\n\n            var analyzerProvider = CreateAnalyzerProvider();\n\n            var analyzerMock = new Mock<IDependencyAnalyzer>();\n            SetUpFactoryCall(analyzerMock.Object);\n\n            analyzerProvider.GetDependencyAnalyzer(filePath);\n            VerifyDependencyAnalyzerFactoryCall(Times.Once());\n            analyzerMock.Verify(i => i.RefreshConfig(), Times.Never);\n\n            analyzerProvider.GetDependencyAnalyzer(filePath);\n            VerifyDependencyAnalyzerFactoryCall(Times.Once());\n            analyzerMock.Verify(i => i.RefreshConfig(), Times.Once);\n        }\n\n        [Fact]\n        public void GetAssemblyDependencyAnalyzer_RetrievedTwice_CallsFactoryThenAnalyzerRefresh()\n        {\n            const string filePath = \"myFilePath\";\n\n            var analyzerProvider = CreateAnalyzerProvider();\n\n            var analyzerMock = new Mock<IAssemblyDependencyAnalyzer>();\n            SetUpFactoryCall(analyzerMock.Object);\n\n            analyzerProvider.GetAssemblyDependencyAnalyzer(filePath);\n            VerifyAssemblyDependencyAnalyzerFactoryCall(Times.Once());\n            analyzerMock.Verify(i => i.RefreshConfig(), Times.Never);\n\n            analyzerProvider.GetAssemblyDependencyAnalyzer(filePath);\n            VerifyAssemblyDependencyAnalyzerFactoryCall(Times.Once());\n            analyzerMock.Verify(i => i.RefreshConfig(), Times.Once);\n        }\n\n        private void SetUpFactoryCall(IDependencyAnalyzer analyzer)\n        {\n            _dependencyAnalyzerFactoryMock\n                .Setup(i => i.Create(It.IsAny<IUpdateableConfigProvider>(), _typeDependencyEnumeratorMock.Object))\n                .Returns(analyzer);\n        }\n\n        private void VerifyDependencyAnalyzerFactoryCall(Times times)\n        {\n            _dependencyAnalyzerFactoryMock\n                .Verify(i => i.Create(It.IsAny<IUpdateableConfigProvider>(), _typeDependencyEnumeratorMock.Object), times);\n        }\n\n        private void VerifyAssemblyDependencyAnalyzerFactoryCall(Times times)\n        {\n            _assemblyDependencyAnalyzerFactoryMock.Verify(i => i.Create(It.IsAny<IUpdateableConfigProvider>()), times);\n        }\n\n        private void SetUpFactoryCall(IAssemblyDependencyAnalyzer analyzer)\n        {\n            _assemblyDependencyAnalyzerFactoryMock\n                .Setup(i => i.Create(It.IsAny<IUpdateableConfigProvider>()))\n                .Returns(analyzer);\n        }\n\n        private IAnalyzerProvider CreateAnalyzerProvider()\n        {\n            return new AnalyzerProvider(\n                _dependencyAnalyzerFactoryMock.Object,\n                _assemblyDependencyAnalyzerFactoryMock.Object,\n                _configProviderFactoryMock.Object,\n                _typeDependencyEnumeratorMock.Object\n            );\n        }\n    }\n}"
  },
  {
    "path": "source/NsDepCop.Vsix/NsDepCop.Vsix.csproj",
    "content": "﻿<Project>\n  <Import Sdk=\"Microsoft.NET.Sdk\" Project=\"Sdk.props\" />\n\n  <PropertyGroup>\n    <TargetFramework>net472</TargetFramework>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <GeneratePkgDefFile>false</GeneratePkgDefFile>\n    <IncludeAssemblyInVSIXContainer>false</IncludeAssemblyInVSIXContainer>\n    <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer>\n    <IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment>\n    <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory>\n    <CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>\n    <VSSDKTargetPlatformRegRootSuffix>Roslyn</VSSDKTargetPlatformRegRootSuffix>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.VSSDK.BuildTools\" Version=\"17.12.2069\" PrivateAssets=\"all\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\NsDepCop.Analyzer\\NsDepCop.Analyzer.csproj\" />\n  </ItemGroup>\n\n  <PropertyGroup>\n    <StartAction>Program</StartAction>\n    <StartProgram>$(DevEnvDir)devenv.exe</StartProgram>\n    <StartArguments>\n      c:\\temp\\simpleapp\\simpleapp.sln /rootsuffix $(VSSDKTargetPlatformRegRootSuffix) /log c:\\temp\\activitylog.xml\n    </StartArguments>\n  </PropertyGroup>\n\n  <Import Sdk=\"Microsoft.NET.Sdk\" Project=\"Sdk.targets\" />\n\n  <Import Project=\"$(VSToolsPath)\\VSSDK\\Microsoft.VsSDK.targets\" Condition=\"Exists('$(VSToolsPath)\\VSSDK\\Microsoft.VsSDK.targets')\" />\n\n  <ItemGroup>\n    <!-- https://github.com/dotnet/sdk/issues/433 -->\n    <ProjectReference Update=\"@(ProjectReference)\" AdditionalProperties=\"TargetFramework=netstandard2.0\" />\n\n    <!-- https://github.com/Microsoft/extendvs/issues/57 -->\n    <ProjectReference Update=\"@(ProjectReference)\" Name=\"%(Filename)\" />\n  </ItemGroup>\n\n  <!-- Workaround to include NuGet DLLs into the VSIX. -->\n  <Target Name=\"IncludeNuGetPackageReferences\" AfterTargets=\"GetVsixSourceItems\">\n    <ItemGroup>\n      <VSIXSourceItem Include=\"@(ReferenceCopyLocalPaths)\" Condition=\"'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'DotNet.Glob'\" />\n    </ItemGroup>\n  </Target>\n\n</Project>"
  },
  {
    "path": "source/NsDepCop.Vsix/readme.txt",
    "content": "﻿If the VSIX project launches the experimental Visual Studio instance successfully, but the breakpoints are not hit, \nthen turn off \"Run code analysis in separate process\" in the Options of the experimental VS instance.\nSee: https://github.com/dotnet/roslyn-sdk/issues/515#issuecomment-1223731899\n\nAlso, if the project that is used for testing, has a package reference to the NsDepCop nuget, it might be necessary to remove it,\nto force the analyzer to run from the VSIX package.\n"
  },
  {
    "path": "source/NsDepCop.Vsix/source.extension.vsixmanifest",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PackageManifest Version=\"2.0.0\" xmlns=\"http://schemas.microsoft.com/developer/vsx-schema/2011\" xmlns:d=\"http://schemas.microsoft.com/developer/vsx-schema-design/2011\">\n  <Metadata>\n    <Identity Id=\"NsDepCop.A2AB1A0B-EEF2-45BB-BEED-C54689C769CA\" Version=\"2.0\" Language=\"en-US\" Publisher=\"Codartis\"/>\n    <DisplayName>NsDepCop - Code dependency checker tool for C#</DisplayName>\n    <Description xml:space=\"preserve\">Static code analysis tool for enforcing namespace-based type dependency rules in C# projects.</Description>\n  </Metadata>\n  <Installation>\n    <InstallationTarget Id=\"Microsoft.VisualStudio.Pro\" Version=\"[15.0,)\" />\n    <InstallationTarget Id=\"Microsoft.VisualStudio.Community\" Version=\"[15.0,)\" />\n    <InstallationTarget Id=\"Microsoft.VisualStudio.Enterprise\" Version=\"[15.0,)\" />\n  </Installation>\n  <Dependencies>\n    <Dependency Id=\"Microsoft.Framework.NDP\" DisplayName=\"Microsoft .NET Framework\" d:Source=\"Manual\" Version=\"[4.7.2,)\" />\n  </Dependencies>\n  <Assets>\n    <Asset Type=\"Microsoft.VisualStudio.MefComponent\" d:Source=\"Project\" d:ProjectName=\"NsDepCop.Analyzer\" Path=\"|NsDepCop.Analyzer|\"/>\n    <Asset Type=\"Microsoft.VisualStudio.Analyzer\" d:Source=\"Project\" d:ProjectName=\"NsDepCop.Analyzer\" Path=\"|NsDepCop.Analyzer|\"/>\n  </Assets>\n  <Prerequisites>\n    <Prerequisite Id=\"Microsoft.VisualStudio.Component.CoreEditor\" Version=\"[15.0,)\" DisplayName=\"Visual Studio core editor\" />\n    <Prerequisite Id=\"Microsoft.VisualStudio.Component.Roslyn.LanguageServices\" Version=\"[15.0,)\" DisplayName=\"Roslyn Language Services\" />\n  </Prerequisites>\n</PackageManifest>"
  },
  {
    "path": "source/NsDepCop.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.4.33403.182\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{AB1A4FF5-D372-416A-9986-6C3548F78B3B}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t.editorconfig = .editorconfig\r\n\t\t..\\appveyor.yml = ..\\appveyor.yml\r\n\t\t..\\CHANGELOG.md = ..\\CHANGELOG.md\r\n\t\tconfig.nsdepcop = config.nsdepcop\r\n\t\t..\\Contribute.md = ..\\Contribute.md\r\n\t\tDirectory.Build.targets = Directory.Build.targets\r\n\t\t..\\LICENSE = ..\\LICENSE\r\n\t\t..\\README.md = ..\\README.md\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Include\", \"Include\", \"{71A874EB-DA8D-4F27-8D68-335B7EF77671}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\tinclude\\CommonAssemblyInfo.cs = include\\CommonAssemblyInfo.cs\r\n\t\tinclude\\VersionInfo.cs = include\\VersionInfo.cs\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"doc\", \"doc\", \"{EFA91D33-558D-4191-8786-8A6A8CFA7CD3}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t..\\doc\\DependencyControl.md = ..\\doc\\DependencyControl.md\r\n\t\t..\\doc\\Diagnostics.md = ..\\doc\\Diagnostics.md\r\n\t\t..\\doc\\Help.md = ..\\doc\\Help.md\r\n\t\t..\\doc\\Troubleshooting.md = ..\\doc\\Troubleshooting.md\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"NsDepCop.Analyzer\", \"NsDepCop.Analyzer\\NsDepCop.Analyzer.csproj\", \"{BC26589E-79B0-4F55-B64D-DB11534D3476}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"NsDepCop.Test\", \"NsDepCop.Test\\NsDepCop.Test.csproj\", \"{96044EE5-D220-4CED-A687-35AED0115A35}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"NsDepCop.NuGet\", \"NsDepCop.NuGet\\NsDepCop.NuGet.csproj\", \"{0FB37BF6-7E56-4974-829D-917AB6207257}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"NsDepCop.SourceTest\", \"NsDepCop.SourceTest\\NsDepCop.SourceTest.csproj\", \"{F6554236-1D67-4343-816A-F145F7750526}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"NsDepCop.Vsix\", \"NsDepCop.Vsix\\NsDepCop.Vsix.csproj\", \"{17A44684-B673-42F8-982F-01ABEA3D5BBE}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"NsDepCop.ConfigSchema\", \"NsDepCop.ConfigSchema\", \"{44F96B9A-C418-43A2-8138-CC64E3FEAF08}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\tNsDepCop.ConfigSchema\\NsDepCopCatalog.xml = NsDepCop.ConfigSchema\\NsDepCopCatalog.xml\r\n\t\tNsDepCop.ConfigSchema\\NsDepCopConfig.xsd = NsDepCop.ConfigSchema\\NsDepCopConfig.xsd\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"NsDepCop.Benchmarks\", \"NsDepCop.Benchmarks\\NsDepCop.Benchmarks.csproj\", \"{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tDebug|Mixed Platforms = Debug|Mixed Platforms\r\n\t\tDebug|x86 = Debug|x86\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\t\tRelease|Mixed Platforms = Release|Mixed Platforms\r\n\t\tRelease|x86 = Release|x86\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{BC26589E-79B0-4F55-B64D-DB11534D3476}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{96044EE5-D220-4CED-A687-35AED0115A35}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Debug|x86.Build.0 = Debug|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{0FB37BF6-7E56-4974-829D-917AB6207257}.Release|x86.Build.0 = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Debug|x86.Build.0 = Debug|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{F6554236-1D67-4343-816A-F145F7750526}.Release|x86.Build.0 = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Debug|x86.Build.0 = Debug|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{17A44684-B673-42F8-982F-01ABEA3D5BBE}.Release|x86.Build.0 = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|x86.ActiveCfg = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Debug|x86.Build.0 = Debug|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|Mixed Platforms.Build.0 = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|x86.ActiveCfg = Release|Any CPU\r\n\t\t{3E9D9807-52F9-4853-A4B5-6AC30AD88D25}.Release|x86.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 = {EBB04CE1-A8C8-417E-95FF-EF622AD8EAFE}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "source/NsDepCop.sln.DotSettings",
    "content": "﻿<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namespace:System;assembly=mscorlib\" xmlns:ss=\"urn:shemas-jetbrains-com:settings-storage-xaml\" xmlns:wpf=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">\n\t<s:String x:Key=\"/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue\">NEVER</s:String>\n\t<s:Int64 x:Key=\"/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue\">160</s:Int64>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Codartis/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=NSDEPCOP/@EntryIndexedValue\">True</s:Boolean></wpf:ResourceDictionary>"
  },
  {
    "path": "source/config.nsdepcop",
    "content": "﻿<NsDepCopConfig ChildCanDependOnParentImplicitly=\"true\" CheckAssemblyDependencies=\"true\">\n    <Allowed From=\"*\" To=\"System.*\" />\n\n\t<AllowedAssembly From=\"*\" To=\"mscorlib\" />\n\t<AllowedAssembly From=\"*\" To=\"netstandard\" />\n    <AllowedAssembly From=\"*\" To=\"System.*\" />\n</NsDepCopConfig>"
  },
  {
    "path": "source/include/CommonAssemblyInfo.cs",
    "content": "﻿using System.Reflection;\r\n\r\n[assembly: AssemblyCompany(\"Codartis\")]\r\n[assembly: AssemblyProduct(\"NsDepCop\")]\r\n[assembly: AssemblyCopyright(\"Copyright © 2013-2025 Ferenc Vizkeleti\")]\r\n"
  }
]