Showing preview only (555K chars total). Download the full file or copy to clipboard to get everything.
Repository: realvizu/NsDepCop
Branch: master
Commit: 155a9b5b7411
Files: 297
Total size: 468.7 KB
Directory structure:
gitextract_m8768ds6/
├── .gitignore
├── CHANGELOG.md
├── CLAUDE.md
├── Contribute.md
├── LICENSE
├── README.md
├── appveyor.yml
├── doc/
│ ├── DependencyControl.md
│ ├── Diagnostics.md
│ ├── Help.md
│ └── Troubleshooting.md
├── images/
│ ├── docs/
│ │ ├── Figures.vsdx
│ │ └── NsDepCop_Example_w600.xcf
│ └── icons/
│ ├── NsDepCop_128.xcf
│ ├── NsDepCop_128_flat.xcf
│ ├── NsDepCop_256.xcf
│ ├── NsDepCop_40.xcf
│ ├── NsDepCop_48.xcf
│ ├── NsDepCop_ItemTemplate_40.xcf
│ ├── SetupBackground.xcf
│ └── SetupTopBanner.xcf
└── source/
├── .editorconfig
├── Directory.Build.targets
├── NsDepCop.Analyzer/
│ ├── Analysis/
│ │ ├── AssemblyDependency.cs
│ │ ├── Factory/
│ │ │ ├── AssemblyDependencyAnalyzerFactory.cs
│ │ │ └── DependencyAnalyzerFactory.cs
│ │ ├── IAssemblyDependencyAnalyzer.cs
│ │ ├── IAssemblyDependencyAnalyzerFactory.cs
│ │ ├── IDependencyAnalyzer.cs
│ │ ├── IDependencyAnalyzerFactory.cs
│ │ ├── ITypeDependencyEnumerator.cs
│ │ ├── Implementation/
│ │ │ ├── AssemblyDependencyAnalyzer.cs
│ │ │ ├── AssemblyDependencyValidator.cs
│ │ │ ├── CachingTypeDependencyValidator.cs
│ │ │ ├── DependencyAnalyzer.cs
│ │ │ ├── DependencyStatus.cs
│ │ │ ├── IAssemblyDependencyValidator.cs
│ │ │ ├── ITypeDependencyValidator.cs
│ │ │ ├── IllegalTypeDependency.cs
│ │ │ └── TypeDependencyValidator.cs
│ │ ├── Messages/
│ │ │ ├── AnalyzerMessageBase.cs
│ │ │ ├── ConfigDisabledMessage.cs
│ │ │ ├── ConfigErrorMessage.cs
│ │ │ ├── IllegalAssemblyDependencyMessage.cs
│ │ │ ├── IllegalDependencyMessage.cs
│ │ │ ├── NoConfigFileMessage.cs
│ │ │ └── ToolDisabledMessage.cs
│ │ ├── SourceSegment.cs
│ │ └── TypeDependency.cs
│ ├── Config/
│ │ ├── AnalyzerConfigState.cs
│ │ ├── ConfigDefaults.cs
│ │ ├── DependencyRule.cs
│ │ ├── Domain.cs
│ │ ├── DomainSpecification.cs
│ │ ├── DomainSpecificationParser.cs
│ │ ├── Factory/
│ │ │ └── ConfigProviderFactory.cs
│ │ ├── IAnalyzerConfig.cs
│ │ ├── IConfigProvider.cs
│ │ ├── IConfigProviderFactory.cs
│ │ ├── IDependencyRules.cs
│ │ ├── IUpdateableConfigProvider.cs
│ │ ├── Implementation/
│ │ │ ├── AnalyzerConfig.cs
│ │ │ ├── AnalyzerConfigBuilder.cs
│ │ │ ├── ConfigLoadResult.cs
│ │ │ ├── ConfigProviderBase.cs
│ │ │ ├── FileConfigProviderBase.cs
│ │ │ ├── MultiLevelXmlFileConfigProvider.cs
│ │ │ ├── RuleConfigToStringsFormatter.cs
│ │ │ ├── XmlConfigParser.cs
│ │ │ └── XmlFileConfigProvider.cs
│ │ ├── RegexCompilationMode.cs
│ │ ├── RegexDomain.cs
│ │ ├── RegexUsageMode.cs
│ │ ├── TypeNameSet.cs
│ │ └── WildcardDomain.cs
│ ├── GlobalSettings.cs
│ ├── NsDepCop.Analyzer.csproj
│ ├── ParserAdapter/
│ │ └── Roslyn/
│ │ ├── ISyntaxNodeAnalyzer.cs
│ │ ├── SyntaxNodeAnalyzer.cs
│ │ ├── SyntaxNodeExtensions.cs
│ │ ├── TypeDependencyEnumerator.cs
│ │ └── TypeDependencyEnumeratorSyntaxVisitor.cs
│ ├── ProductConstants.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── RoslynAnalyzer/
│ │ ├── AnalyzerProvider.cs
│ │ ├── DiagnosticDefinitions.cs
│ │ ├── IAnalyzerProvider.cs
│ │ └── NsDepCopAnalyzer.cs
│ ├── Util/
│ │ ├── ConcurrentDictionaryExtensions.cs
│ │ ├── DictionaryExtensions.cs
│ │ ├── EnumerableExtensions.cs
│ │ ├── ICacheStatistics.cs
│ │ ├── IDateTimeProvider.cs
│ │ ├── IDiagnosticSupport.cs
│ │ ├── IndentHelper.cs
│ │ ├── LinqExtensions.cs
│ │ ├── MathHelper.cs
│ │ └── MessageHandler.cs
│ └── config.nsdepcop
├── NsDepCop.Benchmarks/
│ ├── NsDepCop.Benchmarks.RuleTypesBenchmarks-report-github.md
│ ├── NsDepCop.Benchmarks.csproj
│ ├── Program.cs
│ ├── RuleTypesBenchmarks.cs
│ └── readme.txt
├── NsDepCop.ConfigSchema/
│ ├── NsDepCopCatalog.xml
│ └── NsDepCopConfig.xsd
├── NsDepCop.NuGet/
│ ├── NsDepCop.NuGet.csproj
│ └── tools/
│ ├── install.ps1
│ └── uninstall.ps1
├── NsDepCop.SourceTest/
│ ├── AnalyzerFeatureTests.cs
│ ├── AnalyzerFeature_AllowedDependency/
│ │ ├── AnalyzerFeature_AllowedDependency.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ChildCanDependOnParentImplicitly/
│ │ ├── AnalyzerFeature_ChildCanDependOnParentImplicitly.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_DisallowedDependency/
│ │ ├── AnalyzerFeature_DisallowedDependency.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ExcludedFiles/
│ │ ├── AnalyzerFeature_ExcludedFiles.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ExcludedFiles_WithWildcard/
│ │ ├── AnalyzerFeature_ExcludedFiles_WithWildcard.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ParentCanDependOnChildImplicitly/
│ │ ├── AnalyzerFeature_ParentCanDependOnChildImplicitly.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/
│ │ ├── AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_SameNamespaceAlwaysAllowed/
│ │ ├── AnalyzerFeature_SameNamespaceAlwaysAllowed.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_VisibleMembersOfAllowedRule/
│ │ ├── AnalyzerFeature_VisibleMembersOfAllowedRule.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_VisibleMembersOfNamespace/
│ │ ├── AnalyzerFeature_VisibleMembersOfNamespace.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_WithTopLevelStatement/
│ │ ├── AnalyzerFeature_WithTopLevelStatement.cs
│ │ └── config.nsdepcop
│ ├── Cs6Tests.cs
│ ├── Cs6_AliasQualifiedName/
│ │ ├── Cs6_AliasQualifiedName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ArrayType/
│ │ ├── Cs6_ArrayType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Attributes/
│ │ ├── Cs6_Attributes.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Delegates/
│ │ ├── Cs6_Delegates.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ElementAccess/
│ │ ├── Cs6_ElementAccess.cs
│ │ └── config.nsdepcop
│ ├── Cs6_EveryUserDefinedTypeKind/
│ │ ├── Cs6_EveryUserDefinedTypeKind.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ExtensionMethodInvocation/
│ │ ├── Cs6_ExtensionMethodInvocation.cs
│ │ └── config.nsdepcop
│ ├── Cs6_GenericName/
│ │ ├── Cs6_GenericName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_GenericTypeArgument/
│ │ ├── Cs6_GenericTypeArgument.cs
│ │ └── config.nsdepcop
│ ├── Cs6_InvocationExpression/
│ │ ├── Cs6_InvocationExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_InvocationWithTypeArg/
│ │ ├── Cs6_InvocationWithTypeArg.cs
│ │ └── config.nsdepcop
│ ├── Cs6_MemberAccessExpression/
│ │ ├── Cs6_MemberAccessExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_NestedType/
│ │ ├── Cs6_NestedType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_NullableType/
│ │ ├── Cs6_NullableType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ObjectCreationExpression/
│ │ ├── Cs6_ObjectCreationExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_PointerType/
│ │ ├── Cs6_PointerType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_QualifiedName/
│ │ ├── Cs6_QualifiedName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_StaticImport/
│ │ ├── Cs6_StaticImport.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Var/
│ │ ├── Cs6_Var.cs
│ │ └── config.nsdepcop
│ ├── Cs6_VarWithConstructedGenericType/
│ │ ├── Cs6_VarWithConstructedGenericType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_VeryComplexType/
│ │ ├── Cs6_VeryComplexType.cs
│ │ └── config.nsdepcop
│ ├── Cs7Tests.cs
│ ├── Cs7_1_DefaultLiteral/
│ │ ├── Cs7_1_DefaultLiteral.cs
│ │ └── config.nsdepcop
│ ├── Cs7_1_InferredTupleNames/
│ │ ├── Cs7_1_InferredTupleNames.cs
│ │ └── config.nsdepcop
│ ├── Cs7_1_Tests.cs
│ ├── Cs7_2_NonTrailingNamedArguments/
│ │ ├── Cs7_2_NonTrailingNamedArguments.cs
│ │ └── config.nsdepcop
│ ├── Cs7_2_Tests.cs
│ ├── Cs7_3_AttributeOnPropertyBackingField/
│ │ ├── Cs7_3_AttributeOnPropertyBackingField.cs
│ │ └── config.nsdepcop
│ ├── Cs7_3_Tests.cs
│ ├── Cs7_Deconstruction/
│ │ ├── Cs7_Deconstruction.cs
│ │ └── config.nsdepcop
│ ├── Cs7_IsExpressionWithPattern/
│ │ ├── Cs7_IsExpressionWithPattern.cs
│ │ └── config.nsdepcop
│ ├── Cs7_LocalFunction/
│ │ ├── Cs7_LocalFunction.cs
│ │ └── config.nsdepcop
│ ├── Cs7_Out/
│ │ ├── Cs7_Out.cs
│ │ └── config.nsdepcop
│ ├── Cs7_SwitchWithPattern/
│ │ ├── Cs7_SwitchWithPattern.cs
│ │ └── config.nsdepcop
│ ├── Cs7_ThrowExpression/
│ │ ├── Cs7_ThrowExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs7_Tuples/
│ │ ├── Cs7_Tuples.cs
│ │ └── config.nsdepcop
│ ├── FileBasedTestsBase.cs
│ ├── NsDepCop.SourceTest.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── SourceLineSegment.cs
│ └── SourceTestSpecification.cs
├── NsDepCop.Test/
│ ├── FileBasedTestsBase.cs
│ ├── Implementation/
│ │ ├── Analysis/
│ │ │ ├── AssemblyDependencyAnalyzerTests.cs
│ │ │ ├── CachingTypeDependencyValidatorTests.cs
│ │ │ ├── DependencyAnalyzerTests.cs
│ │ │ ├── DependencyRulesBuilder.cs
│ │ │ ├── TypeDependencyValidatorExtensions.cs
│ │ │ └── TypeDependencyValidatorTests.cs
│ │ └── Config/
│ │ ├── AnalyzerConfigBuilderTests.cs
│ │ ├── MultiLevelXmlFileConfigProviderTests/
│ │ │ ├── Attributes_LowerLevelWins/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── Attributes_MissingDoesNotOverwrite/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtHigherLevelButEnabledAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigEnabled/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigError/
│ │ │ │ ├── Level2/
│ │ │ │ │ ├── Level1/
│ │ │ │ │ │ └── config.nsdepcop
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ExcludedFiles_AllCorrectlyRooted/
│ │ │ │ └── Level2/
│ │ │ │ ├── Excluded File 4.cs
│ │ │ │ ├── ExcludedFile3.cs
│ │ │ │ ├── Level1/
│ │ │ │ │ ├── Excluded File 2.cs
│ │ │ │ │ ├── ExcludedFile1.cs
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── NoConfig/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── RefreshConfig_EnabledToConfigError/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToDisabled/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToEnabledButChanged/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToNoConfig/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── RefreshConfig_InheritanceDepthChanged/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_NoConfigToEnabled/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── Rules_Merged/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── UpdateMaxIssueCount_Level1ContainsMaxIssueCount/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ └── UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount/
│ │ │ └── Level2/
│ │ │ ├── Level1/
│ │ │ │ └── config.nsdepcop
│ │ │ └── config.nsdepcop
│ │ ├── MultiLevelXmlFileConfigProviderTests.cs
│ │ ├── XmlConfigParserTests/
│ │ │ ├── AllowedAssemblyRules.nsdepcop
│ │ │ ├── AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute.nsdepcop
│ │ │ ├── AllowedRuleForWildcardNamespaceWithVisibleMembers.nsdepcop
│ │ │ ├── AllowedRuleFromAttributeMissing.nsdepcop
│ │ │ ├── AllowedRuleToAttributeMissing.nsdepcop
│ │ │ ├── AllowedRules.nsdepcop
│ │ │ ├── DisallowedAssemblyRules.nsdepcop
│ │ │ ├── DisallowedRules.nsdepcop
│ │ │ ├── InvalidAttributeValue.nsdepcop
│ │ │ ├── InvalidDuplicatedWildcardNamespaceString.nsdepcop
│ │ │ ├── InvalidNamespaceString.nsdepcop
│ │ │ ├── NoRootAttributes.nsdepcop
│ │ │ ├── NsDepCopConfigElementNotFound.nsdepcop
│ │ │ ├── RootAttributes.nsdepcop
│ │ │ ├── VisibleMembers.nsdepcop
│ │ │ ├── VisibleMembersOfNamespaceMissing.nsdepcop
│ │ │ └── VisibleMembersTypeNameAttributeMissing.nsdepcop
│ │ ├── XmlConfigParserTests.cs
│ │ ├── XmlFileConfigProviderTests/
│ │ │ ├── Disabled.nsdepcop
│ │ │ ├── Enabled.nsdepcop
│ │ │ ├── Erronous.nsdepcop
│ │ │ ├── Excluded File 2.cs
│ │ │ ├── ExcludedFile1.cs
│ │ │ ├── ExcludedFiles.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToConfigError.nsdepcop
│ │ │ └── RefreshConfig_EnabledToDisabled.nsdepcop
│ │ ├── XmlFileConfigProviderTests.cs
│ │ └── XmlFileConfigTestBase.cs
│ ├── Interface/
│ │ └── Config/
│ │ ├── DomainSpecificationParserTests.cs
│ │ ├── DomainSpecificationTests.cs
│ │ ├── DomainTests.cs
│ │ ├── RegexDomainTests.cs
│ │ └── WildcardDomainTests.cs
│ ├── NsDepCop.Test.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ └── RoslynAnalyzer/
│ └── AnalyzerProviderTests.cs
├── NsDepCop.Vsix/
│ ├── NsDepCop.Vsix.csproj
│ ├── readme.txt
│ └── source.extension.vsixmanifest
├── NsDepCop.sln
├── NsDepCop.sln.DotSettings
├── config.nsdepcop
└── include/
├── CommonAssemblyInfo.cs
└── VersionInfo.cs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studo 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.[Cc]ache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
/source/out
*.local.*
================================================
FILE: CHANGELOG.md
================================================
# NsDepCop Change Log
## v2.7.0
(12/2025)
- [x] Perf: Avoids unnecessary rebuilds when only a solution-level config.nsdepcop file is used (no project-level files).
## v2.6.0
(04/2025)
- [x] New: Regex patterns for assemblies and namespaces.
## v2.5.0
(01/2025)
- [x] New: Added assembly dependency checking.
## v2.4.0
(09/2024)
- [x] New: Analyzing top level statements.
## v2.3.0
(07/2023)
- [x] Changed: Added the allowed type names to the diagnostic message (if VisibleMembers are specified).
## v2.2.0
(09/2022)
- [x] New: Wildcard patterns for namespaces.
## v2.1.0
(07/2022)
- [x] New: ParentCanDependOnChildImplicitly config attribute.
## v2.0.1
(03/2022)
- [x] Fix: #60 - Statically imported type dependency not detected.
## v2.0.0
(06/2021)
The big change in this version is that the implementation changed from MSBuild task + Visual Studio Extension to a standard Roslyn analyzer.
- [x] NsDepCop must be added to a project as a NuGet package.
- [x] Appears in Solution Explorer: project / Dependencies / Analyzers / NsDepCop.Analyzer
- [x] Issue severities can be configured that same way as other analyzers (use Visual Studio or .editorconfig files).
- [x] Works both at build time and inside Visual Studio editor.
- [x] Requires Visual Studio 2019 (16.10.0 or later).
- [x] Supports .NET Core / .NET 5 / etc. projects too.
- [x] Uses Roslyn 3.9.0.
Stuff that was removed:
- [x] No need for the NsDepCop Visual Studio Extension any more.
- [x] No need for the out-of-process service host any more.
- [x] Dropped support for VS 2015/2017. For those, use NsDepCop v1.11.0.
- [x] Config attributes no longer supported (ignored): CodeIssueKind, MaxIssueCountSeverity, InfoImportance, AnalyzerServiceCallRetryTimeSpans.
Other info:
- [x] AutoLowerMaxIssueCount feature is temporarily not supported.
## v1.11.0
(04/2020)
- [x] New: Disable/force NsDepCop with MSBuild property.
## v1.10.1
(02/2020)
- [x] Fix: #51 - RemotingException when using different NsDepCop NuGet and VSIX version.
## v1.10.0
(04/2019)
- [x] New: Support Visual Studio 2019
## v1.9.0
(03/2019)
- [x] New: Support incremental build - don't run the tool if there was no change in the source/config files.
- [x] New: Global turn off switch - DisableNsDepCop environment variable.
- [x] New: Excluding files from analysis - ExcludedFiles attribute in config.nsdepcop.
## v1.8.2
(01/2019)
- [x] Fix: #43 (for real this time) - RemotingException when path contains space.
## v1.8.1
(12/2018)
- [x] Fix: #43 - RemotingException when path contains space.
## v1.8.0
(07/2018)
- [x] Enhancements in launching the out-of-process service host (configurable retry intervals, allow access for any user).
- [x] MaxIssueCountSeverity - enables breaking the build when a threshold number of dependency violations has been reached.
- [x] AutoLowerMaxIssueCount - automatically lower MaxIssueCount to encourage cleaning up dependency problems and prohibit introducing new ones.
- [x] Supports C# up to 7.3.
- [x] The Visual Studio Extension (VSIX) requires 15.7.4 or higher.
## v1.7.1
(07/2017)
- [x] Performance enhancement when run by MSBuild.
- [x] The analyzer keeps running in its own process to avoid repeated creation cost. Shuts down with parent process.
## v1.7.0
(07/2017)
- [x] New: C# 7 support.
- [x] New: Visual Studio 2017 support.
- [x] Removed: MSI installer.
- [x] Config XML schema support is now available as a Visual Studio Extension (only for VS2017).
- [x] Global MSBuild-integration is discontinued. Please use per-project MSBuild integration via the NuGet package.
## v1.6.1
(04/2017)
- [x] Fix: Type without a name caused exception in analyzer.
## v1.6.0
(03/2017)
- [x] New: NuGet package.
- [x] Enables per-project MSBuild integration.
- [x] Enables zero install on build machine.
- [x] New: Multi-level config file.
- [x] Use the InheritanceDepth config attribute to specify the number of parent folder levels to merge config files from.
- [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.
- [x] Changed: MSI installer modified.
- [x] Option (default on): config.nsdepcop XML schema support updated.
- [x] Option (default off): Machine-wide MSBuild integration. Not recommended any more, use the NuGet (per-project) distribution instead.
- [x] Removed option: Visual Studio 2015 integration. Use the VSIX package directly instead.
- [x] Fixed:
- [x] Types in enum and delegate declarations were not analyzed.
- [x] Constructed generic, array and pointer types are now analyzed recursively.
- [x] Source and metadata file load errors are now handled gracefully.
- [x] Changed: Roslyn version updated to 1.3.2.
- [x] Changed: Removed NRefactory as a parser choice.
### Upgrading
* To upgrade please uninstall the previous version first.
* Your existing config.nsdepcop files will be preserved.
* Then install the new version.
* Recommended: change to per-project MSBuild integration with NuGet. See [README.md](README.md) for details.
* 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.
## v1.5
(06/2016)
- [x] Supports Visual Studio 2015 only.
- [x] New: Use the VisibleMembers element to fine-tune the allowed dependencies at the type level.
- [x] New: Added config.nsdepcop XML schema support to Visual Studio so it can validate config syntax and provide IntelliSense.
- [x] Fixed: adding an nsdepcop.config file to a project now works for all C# projects (incl. portable lib).
- [x] Changed: Roslyn version updated to 1.2.2.
## v1.4
(08/2015)
- [x] Supports Visual Studio 2015 only.
- [x] New: Info messages' level can be configured to suppress/enable them in the MSBuild output.
- [x] New: ChildCanDependOnParentImplicitly config attribute.
- [x] Fixed:
- [x] MSBuild return code was success even if an error was detected.
- [x] Extension method declaring type was not checked.
- [x] Changed: Roslyn version updated to 1.0.
- [x] Icons (tadaaa! :)
## v1.3
(01/2015)
- [x] Supports Visual Studio 2013 only.
- [x] New: Disallowed rules.
## v1.2
(08/2014)
- [x] Supports Visual Studio 2013 only.
- [x] Requires the Roslyn End User Preview of April 2014.
## v1.1
(07/2013)
- [x] Supports Visual Studio 2012 only.
- [x] Requires Roslyn September 2012 CTP.
- [x] New: Added NRefactory as the default parser for the MSBuild task.
## v1.0
(03/2013)
- [x] Supports Visual Studio 2012 only.
- [x] Requires Roslyn September 2012 CTP.
================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
NsDepCop 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.
## Build and Test Commands
Solution-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:
```bash
# Build the analyzer (restores and builds dependencies automatically)
dotnet build source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj
# Run unit tests
dotnet test source/NsDepCop.Test/NsDepCop.Test.csproj
# Run source-based integration tests
dotnet test source/NsDepCop.SourceTest/NsDepCop.SourceTest.csproj
# Run a single test by name
dotnet test source/NsDepCop.Test/NsDepCop.Test.csproj --filter "FullyQualifiedName~TestMethodName"
```
**Prerequisites:** Visual Studio 2022 with **Visual Studio extension development** workload (includes the .NET SDK).
## Solution Structure
All source code lives under `source/`. The solution is `source/NsDepCop.sln`.
| Project | Target | Purpose |
|---|---|---|
| `NsDepCop.Analyzer` | netstandard2.0 | Core analyzer — the main product code |
| `NsDepCop.Test` | net8.0 | Unit tests (xUnit, FluentAssertions, Moq) |
| `NsDepCop.SourceTest` | net8.0 | Integration tests — verifies analyzer against C# source files |
| `NsDepCop.NuGet` | netstandard2.0 | NuGet package packaging |
| `NsDepCop.Benchmarks` | — | Performance benchmarks |
| `NsDepCop.Vsix` | — | Visual Studio Extension wrapper |
## Architecture
### Analyzer Core (`NsDepCop.Analyzer`)
Root namespace: `Codartis.NsDepCop`. Internal module dependencies are enforced by `config.nsdepcop` in the project itself.
- **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).
- **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.
- **Analysis/** — Dependency validation logic. `DependencyAnalyzer` orchestrates type-level and assembly-level validation. `TypeDependencyValidator` checks namespace rules; `AssemblyDependencyValidator` checks assembly rules.
- **ParserAdapter/Roslyn/** — Extracts type dependencies from Roslyn syntax trees.
- **Util/** — Shared helpers.
### Dependency flow between modules
```
RoslynAnalyzer → Config (interfaces only), Analysis (interfaces only), ParserAdapter
ParserAdapter → Analysis
Analysis → Config
Config.Factory → Config.Implementation
```
The `RoslynAnalyzer` layer is explicitly **disallowed** from depending on `*.Implementation` namespaces.
### Test Structure
**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`.
**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).
### Self-referencing / Dogfooding
The 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.
## Key Conventions
- `TreatWarningsAsErrors` is enabled on all projects
- Root namespace is `Codartis.NsDepCop` (with project-specific suffixes like `.Test`)
- `config.nsdepcop` is the XML configuration file format — both the product config and test fixtures
- CI runs on AppVeyor (Visual Studio 2022 image), Release configuration
- Version is managed in `appveyor.yml` and patched into `source/Include/VersionInfo.cs`
## Diagnostics
Diagnostic 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`.
================================================
FILE: Contribute.md
================================================
## How to build the source
1. Prerequisites
* Visual Studio 2019 or later (16.10.0 or later, any edition)
* With workload: **Visual Studio extension development**
1. [Download or clone the source](https://github.com/realvizu/NsDepCop)
1. Open "source\NsDepCop.sln"
1. Build the solution.
## How to debug the tool in Visual Studio
1. Set **NsDepCop.Vsix** as the StartUp project.
1. In the project file modify the **StartArguments** tag to point to a valid solution file and log path.
1. Run the solution.
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================
# NsDepCop - Namespace and Assembly Dependency Checker Tool for C# #
NsDepCop is a static code analysis tool that enforces namespace and assembly dependency rules in C# projects.
* It runs as part of the build process and reports any dependency problems.
* No more unplanned or unnoticed dependencies in your system.
What is this [**dependency control**](doc/DependencyControl.md) anyway? And [**why should you automate it**](https://www.plainionist.net/Dependency-Governance-DotNet/)?
## Getting Started
1. Add the [**NsDepCop NuGet package**](https://nuget.org/packages/NsDepCop) to your C# projects: [](https://nuget.org/packages/NsDepCop)
1. Add a text file named **'config.nsdepcop'** to your project, then edit it to define your [**dependency rules**](doc/Help.md#dependency-rules).
1. Dependency violations will be underlined in the code editor and reported at build time just like compiler errors/warnings.
See the [**Help**](doc/Help.md) for details.
Or check out this step-by-step [**tutorial video**](https://www.youtube.com/watch?v=rkU7Hx20Dc0) by [plainionist](https://github.com/plainionist).
## Versions
* See the [**Change Log**](CHANGELOG.md) for version history.
## Feedback
* Use the [**Issue Tracker**](https://github.com/realvizu/NsDepCop/issues) to submit bugs and feature requests.
* Use the [**Discussions forum**](https://github.com/realvizu/NsDepCop/discussions) for questions.
## More Info
* [Diagnostics Reference](doc/Diagnostics.md)
* [Configuring XML schema support for config.nsdepcop files](doc/Help.md#config-xml-schema-support-in-visual-studio)
* [Troubleshooting](doc/Troubleshooting.md)
* [How to contribute?](Contribute.md)
## Thanks to
* [Roslyn](https://github.com/dotnet/roslyn) for the amazing parser API.
* [DotNet.Glob](https://github.com/dazinator/DotNet.Glob) for the globbing library.
## License
* [GPL-2.0](LICENSE)
## Other Tools
* Check out my other project: [Codartis Diagram Tool](https://codartis.com/), a code visualization tool for C#.
================================================
FILE: appveyor.yml
================================================
image: Visual Studio 2022
environment:
shortversion: '2.7.0'
informationalversion: '2.7.0'
version: '$(shortversion).{build}'
configuration: Release
install:
- ps: (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/realvizu/Tools/master/Build/buildtools.ps1") | Invoke-Expression
assembly_info:
patch: true
file: source\include\VersionInfo.cs
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '$(informationalversion)'
dotnet_csproj:
patch: true
file: source\NsDepCop.NuGet\NsDepCop.NuGet.csproj
package_version: '$(informationalversion)'
before_build:
- cmd: nuget restore -Verbosity quiet source\NsDepCop.sln
build:
project: source\NsDepCop.sln
verbosity: minimal
test:
assemblies: '**\*Test*.dll'
artifacts:
- path: 'source\NsDepCop.NuGet\bin\$(configuration)\NsDepCop*.nupkg'
================================================
FILE: doc/DependencyControl.md
================================================
# Dependency Control
## Why Care About Code Dependencies?
The number one enemy of a developer is complexity.
Among the many sources of complexity, lets focus now on the structure of the codebase and its dependencies.
* To reduce complexity, the primary strategy is to decompose the code into smaller units (e.g., modules) and limit dependencies between them.
* A codebase with well-defined modules and clear dependency rules is easier to understand, modify, and reuse.
* However, without a dependency control tool acting as a safeguard, even a well-structured codebase can eventually degrade into a tangled mess.
## How to Control Code Dependencies?
Dependency control tools allow you to define rules for permitted and prohibited dependencies and alert you to any violations.
These tools can operate at various levels and on different input formats:
* Physical Level: Projects, libraries, and assemblies.
* Logical Level: Namespaces and types.
* Input Formats: Source code, compiled binaries, or intermediary representations.
**This tool performs the following dependency checks:**
* Namespace dependencies in the C# source code.
* Assembly dependencies in the C# projects.
It also supports some fine-tuning at the type level (see details below).
## What Is a Namespace Dependency?
Namespace **A** depends on Namespace **B** if any type declared in Namespace **A** uses any type declared in Namespace **B**.
In the example below **Namespace A depends on Namespace B** because type A1 uses types B1, B2, B3, B4 and B5.
```csharp
namespace A
{
using B;
class A1 : B1
{
B2 field1;
B3 Property1 { get; set; }
B4 MyMethod(B5 p) { ... }
}
}
namespace B
{
interface B1 {}
class B2 {}
struct B3 {}
enum B4 {}
delegate void B5();
}
```
Note 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.
## Recommended approach
* **Define** the high-level structure of your system as a hierarchy of logical modules or packages.
* It's better to do this upfront to avoid extensive refactoring later.
* This tool won't assist with the initial design; use a modeling tool or even pen and paper for this step.
* **Implement** these logical modules/packages using C# namespaces.
* Ensure a one-to-one correspondence between logical units and namespaces.
* [**Describe**](Help.md#dependency-rules) allowed namespace dependencies in config.nsdepcop files.
* Use one config file per C# project.
* Common dependency rules can be placed in a ["master" config file](Help.md#config-inheritance).
* **Fix** illegal dependencies reported by the tool.
* This may require rethinking or redesigning parts of your architecture.
* Avoid circular dependencies.
## Why Namespace Dependencies Instead of Type Dependencies?
Enforcing dependency rules at the type level can lead to verbose and fragile dependency descriptions.
Namespaces 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.
## Why Does This Tool Support Some Type-Level Dependency Control?
In 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.
================================================
FILE: doc/Diagnostics.md
================================================
# NsDepCop Diagnostics Reference
### NSDEPCOP01
Title|Illegal namespace reference.
:-|:-
Default Severity|Warning
Explanation|The designated type cannot reference the other type because their namespaces cannot depend on each other according to the current rules.
To Do|Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this namespace dependency.
### NSDEPCOP02
Title|Too many dependency issues, analysis was stopped.
:-|:-
Default Severity|Warning
Explanation|The number of dependency issues in this compilation has exceeded the configured maximum value.
To Do|Correct the reported issues and run the build again or set the MaxIssueCount attribute in your 'config.nsdepcop' file to a higher number.
### NSDEPCOP03
Title|No config file found, analysis skipped.
:-|:-
Default Severity|Info
Explanation|This analyzer requires that you add a file called 'config.nsdepcop' to your project with build action 'C# analyzer additional file'.
To Do|None, this is just an informational message.
### NSDEPCOP04
Title|Analysis is disabled in the config file.
:-|:-
Default Severity|Info
Explanation|The IsEnabled attribute was set to false in this project's 'config.nsdepcop' file, so the analyzer skips this project.
To Do|None, this is just an informational message.
### NSDEPCOP05
Title|Error loading config.
:-|:-
Default Severity|Error
Explanation|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.
To 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.
### NSDEPCOP06
Title|Analysis is disabled with environment variable.
:-|:-
Default Severity|Info
Explanation|If the 'DisableNsDepCop' environment variable is set to 'True' or '1' then all analysis is skipped.
To Do|None, this is just an informational message.
### NSDEPCOP07
Title|Illegal assembly reference.
:-|:-
Default Severity|Warning
Explanation|The designated assembly cannot reference the other assembly because their dependency is prohibited according to the current rules.
To Do|Change the dependency rules in the 'config.nsdepcop' file or change your design to avoid this assembly dependency.
================================================
FILE: doc/Help.md
================================================
# NsDepCop Help
* [Supported project types](#supported-project-types)
* [Dependency rules](#dependency-rules)
* [Config inheritance](#config-inheritance)
* [Dealing with a high number of dependency issues](#dealing-with-a-high-number-of-dependency-issues)
* [Disabling with an environment variable](#disabling-with-an-environment-variable)
* [Config XML schema](#config-xml-schema)
* [Config XML schema support in Visual Studio](#config-xml-schema-support-in-visual-studio)
* [v1.x only topics](#v1.x-only-topics)
## Supported project types
* Projects with a **csproj** project file are supported.
* .Net Core and .Net 5+ projects are supported in v2.0 or above.
* Projects with an **xproj** project file are not supported.
## Dependency rules
* Allowed and disallowed namespace and assembly dependencies are described with dependency rules in config files.
* 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).
* 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)).
* The config file can inherit other config files from parent folders, see [**config inheritance**](#config-inheritance).
* 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).
* Rules can specify namespaces in the following ways.
Namespace specification type | Example
-- | --
Exact| System.IO
Wildcard | System.Collections.* <br> MyProduct.?.StorageModel
Regex | /MyProduct(\.[\w]+)*\.StorageModel[\w]/
> Notice that Regex patterns must be enclosed in forward slashes ('/').
### Rule notation
Notation | Meaning
-- | --
. (a single dot) | The global namespace.
\* (a single star) | Any namespace.
MyNamespace.\* | MyNamespace and any sub-namespaces.
MyNamespace.?| All direct sub-namespaces of MyNamespace
\*.MyNamespace | Any namespace named MyNamespace
?.MyNamespace | Any namespace named MyNamespace which has exactly one parent namespace.
MyNamespace.*.MyOtherNamespace| Any namespace called MyOtherNamespace which has an ancestor named MyNamespace
MyNamespace.?.MyOtherNamespace| Any namespace called MyOtherNamespace which has a grandparent named MyNamespace
/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.
### Example One
```xml
<NsDepCopConfig IsEnabled="true" ChildCanDependOnParentImplicitly="true">
<Allowed From="*" To="System.*" />
<Allowed From="NsDepCop.*" To="Microsoft.CodeAnalysis.*" />
<Allowed From="NsDepCop.ParserAdapter.Roslyn" To="NsDepCop.Analysis" />
</NsDepCopConfig>
```
Meaning:
* **Any** namespace can reference the **System** namespace and any of its sub-namespaces.
* The **NsDepCop** namespace and all of its sub-namespaces can reference the **Microsoft.CodeAnalysis** namespace and any of its sub-namespaces.
* The **NsDepCop.ParserAdapter.Roslyn** namespace can reference the **NsDepCop.Analysis** namespace (but not its sub-namespaces).
### Example Two
```xml
<NsDepCopConfig IsEnabled="true" CheckAssemblyDependencies="true">
<AllowedAssembly From="*" To="*" />
<DisallowedAssembly From="*.Repository" To="*.Service" />
</NsDepCopConfig>
```
Meaning:
* **Any** assembly can reference each other with the following exception.
* The **Repository** layer cannot reference the **Service** layer.
Tip: When using the allowlisting approach for assemblies, don't forget the include the following rules:
```xml
<NsDepCopConfig IsEnabled="true" CheckAssemblyDependencies="true">
<AllowedAssembly From="*" To="mscorlib" />
<AllowedAssembly From="*" To="netstandard" />
<AllowedAssembly From="*" To="System.*" />
</NsDepCopConfig>
```
### Config attributes
You can set the following attributes on the root element. (Bold marks the the **default** value.)
Attribute | Values | Description
--- | --- | ---
**IsEnabled** | **true**, false | If set to false then analysis is not performed for the project.
**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.)
**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**.
**MaxIssueCount** | int (>0), default: **100** | Analysis stops when reaching this number of dependency issues.
**AutoLowerMaxIssueCount** | true, **false** | If set to true then each successful build yielding fewer issues than MaxIssueCount sets MaxIssueCount to the current number of issues.
**InheritanceDepth** | int (>=0), default: **0** | Sets the number of parent folder levels to inherit config from. 0 means no inheritance.
**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`
**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.
### Allowlisting
* The **`<Allowed From="N1" To="N2"/>`** config element defines that **N1** namespace can depend on **N2** namespace.
* If a dependency does not match any of the allowed rules then it's considered disallowed.
Examples:
Example | Meaning
-|-
`<Allowed From="MyNamespace" To="System" />` | **MyNamespace** can depend on **System**
`<Allowed From="MyNamespace" To="System.*" />` | **MyNamespace** can depend on **System and any sub-namespace**
`<Allowed From="MyNamespace" To="*" />` | **MyNamespace** can depend on **any namespace**
`<Allowed From="MyNamespace" To="." />` | **MyNamespace** can depend on the **global namespace**
`<Allowed From="MyNamespace" To="System.*.Serialization.*" />` | **MyNamespace** can depend on all **Serialization** namespaces in **System** and their sub-namespaces
### Denylisting
* The **`<Disallowed From="N1" To="N2"/>`** config element defines that **N1** namespace **must not** depend on **N2** namespace.
* To implement the denylisting behavior, you also have to define an "allow all" rule, otherwise no dependency will be allowed.
* Only those dependencies are allowed that has a matching "Allowed" rule and no match with any of the "Disallowed" rules.
* You can specify any number of "Allowed" and "Disallowed" rules in any order.
* If both an "Allowed" and a "Disallowed" rule are matched then "Disallowed" is the "stronger".
Example:
```xml
<NsDepCopConfig>
<Allowed From="*" To="*" />
<Disallowed From="MyFrontEnd.*" To="MyDataAccess.*" />
</NsDepCopConfig>
```
Meaning:
* Every dependency is allowed but MyFrontEnd (and its sub-namespace) must not depend on MyDataAccess (and its sub-namespaces).
### Behavior of the wildcards '*' and '?'
If any `Disallowed` rule matches, no `Allowed` rule is considered.
If multiple `Allowed` rules match the same namespace, the one with best matching `From` rule is selected.
The 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:
* Replacing a `?` has a cost of 1.
* Replacing a `*` has a cost of 1 and additionaly a cost of 1 per sub-namespace that replaces the `*`.
Example: 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.
### Namespace surface
* The *surface* of a namespace consists of the types that are visible to some other namespace.
* The **`<VisibleMembers>`** config element defines the surface of a namespace.
* In the following example **GameLogic** can use only **Vector2** and **Vector3** types of the **UnityEngine** namespace.
```xml
<Allowed From="GameLogic" To="UnityEngine">
<VisibleMembers>
<Type Name="Vector2" />
<Type Name="Vector3" />
</VisibleMembers>
</Allowed>
```
* 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**.
* You can define different surfaces for different other namespaces.
* 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.
```xml
<VisibleMembers OfNamespace="UnityEngine">
<Type Name="Vector2" />
<Type Name="Vector3" />
</VisibleMembers>
```
* Notice that when defining a "global" surface the `<VisibleMembers>` element is not embedded in an `<Allowed>` element but you must specify the **OfNamespace** attribute.
### Allowing all child namespaces to depend on their parents
You can specify the **ChildCanDependOnParentImplicitly** attribute on the NsDepCopConfig element.
* True means that all child namespaces can depend on any of their parent namespaces without requiring an explicit Allowed rule.
* True is in line with how C# type resolution works: it searches parent namespaces without requiring an explicit using statement.
* False means that all dependencies between children and their parents must be explicitly allowed with a rule.
* False is the default for backward compatibility.
Example:
```xml
<NsDepCopConfig ChildCanDependOnParentImplicitly="true">
<!-- The following rule is not necessary because the ChildCanDependOnParentImplicitly="true" attribute implies it. -->
<Allowed From="MyNamespace.SubNamespace" To="MyNamespace" />
</NsDepCopConfig>
```
### Allowing all parent namespaces to depend on their children
You can specify the **ParentCanDependOnChildImplicitly** attribute on the NsDepCopConfig element.
However, 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.
## Config inheritance
From v1.6 NsDepCop supports config inheritance, aka multi-level config.
* The goal is to achieve "DRY" configs, that is, **avoid redundant info** in config.nsdepcop files.
* 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.
* The "master" config file must also be named config.nsdepcop.
* 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.
* 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.
Example:
```xml
config.nsdepcop file in "C:\MySolution":
<NsDepCopConfig ChildCanDependOnParentImplicitly="true">
<Allowed From="*" To="System.*" />
<Allowed From="*" To="MoreLinq" />
<Allowed From="*" To="NsDepCop.Core.Util" />
</NsDepCopConfig>
config.nsdepcop file in "C:\MySolution\MyProject":
<NsDepCopConfig InheritanceDepth="1">
<Allowed From="NsDepCop.MsBuildTask" To="NsDepCop.Core.Interface.*" />
<Allowed From="NsDepCop.MsBuildTask" To="NsDepCop.Core.Factory" />
<Allowed From="NsDepCop.MsBuildTask" To="Microsoft.Build.*" />
</NsDepCopConfig>
```
More info:
* If there is a conflict between the project-level and the inherited settings then the project-level settings "wins".
* The `IsEnabled` attribute has different meaning in the project-level config and in inherited configs.
* If `IsEnabled="false"` in a project-level config then the project don't get analyzed.
* If `IsEnabled="false"` in an inherited config then its content doesn't get inherited.
* 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.
* There must always be a config.nsdepcop file in the project folder if you want to analyze that project.
Even 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.
E.g.: `<NsDepCopConfig InheritanceDepth="3"/>`
## Dealing with a high number of dependency issues
If 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.
* Prevent the introduction of more dependency issues. Set the current number of issues as the maximum and make it an error to create more.
```xml
<NsDepCopConfig MaxIssueCount="<the current number of issues>">
```
* Encourage developers to gradually fix the dependency issues by automatically lowering the max issue count whenever possible. Turn on AutoLowerMaxIssueCount.
```xml
<NsDepCopConfig AutoLowerMaxIssueCount="true" MaxIssueCount="<the current number of issues>">
```
> Please note that when NsDepCop modifies the nsdepcop.config files their formatting will be reset (because of the XML deserialization/serialization roundtrip).
## Disabling with an environment variable
To disable the tool **globally**, set the **DisableNsDepCop** environment variable to **true** or **1**.
`setx DisableNsDepCop 1`
It will affect both MSBuild integration (NuGet package) and Visual Studio integration (VSIX package).
Note that it won't affect processes that are already running, only the newly started ones.
## Config XML schema
See the XSD schema of config.nsdepcop [here](../source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd).
## Config XML schema support in Visual Studio
Add NsDepCop config XML schema to the Visual Studio schema cache to get validation and IntelliSense when editing NsDepCop config files.
* Copy the following files into the Visual Studio schema cache folder, located at <VsInstallDir>/Xml/Schemas (eg. C:\Program Files\Microsoft Visual Studio\2022\Community\Xml\Schemas):
* [NsDepCopCatalog.xml](../source/NsDepCop.ConfigSchema/NsDepCopCatalog.xml)
* [NsDepCopConfig.xsd](../source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd)
## v1.x only topics
The following topics apply only to v1.x versions.
### Config attributes deprecated in v2.0
Attribute | Values | Description
--- | --- | ---
**CodeIssueKind** | Info, **Warning**, Error | Dependency violations are reported at this severity level.
**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.
**MaxIssueCountSeverity** | Info, **Warning**, Error | This is the severity of the issue of reaching MaxIssueCount.
**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.
### Controlling verbosity
* Besides emitting dependency violation issues, the tool can emit diagnostic and info messages too.
* **Info messages** tell you when was the tool started and finished.
* **Diagnostic messages** help you debug config problems by dumping config contents and dependency validation result cache change events.
* 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.
* 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]
* Set it to **detailed** or higher to see NsDepCop **diagnostic messages**.
* Set it to **normal** or higher to see NsDepCop **info messages**.
Advanced settings:
* You can also modify the importance level of NsDepCop info messages by setting the `InfoImportance` attribute in config.nsdepcop to Low, Normal or High.
* 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.
* The following table shows which InfoImportance levels are shown at certain MSBuild verbosity levels.
| MSBuild verbosity level| Low InfoImportance | Normal InfoImportance | High InfoImportance |
| - | - | - | - |
| q[uiet] | - | - | - |
| m[inimal] | - | - | yes |
| n[ormal] | - | yes | yes |
| d[etailed] | yes | yes | yes |
| diag[nostic] | yes | yes | yes |
E.g.: if you want NsDepCop info messages to show up at minimal MSBuild verbosity then set `InfoImportance` to High.
### Disabling to tool with MSBuild property
To disable the tool in MSBuild, set the **DisableNsDepCop** property to **true**.
```xml
<PropertyGroup>
<DisableNsDepCop>true</DisableNsDepCop>
</PropertyGroup>
```
### Overriding the disabled state with MSBuild property
To force executing the tool in MSBuild, set the **ForceNsDepCop** property to **true**.
`msbuild MySolution.sln -t:NsDepCop_Analyze -p:ForceNsDepCop=true`
### Running NsDepCop only as an explicit command
If NsDepCop slows down the build too much then you can disable it as part of the build and run it explicitly before checking in.
* 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:
```xml
<Project>
<PropertyGroup>
<DisableNsDepCop>true</DisableNsDepCop>
</PropertyGroup>
</Project>
```
* Create a cmd file that runs only NsDepCop. Run it before every check-in.
`msbuild MySolution.sln -t:NsDepCop_Analyze -p:ForceNsDepCop=true`
### NsDepCop ServiceHost
NsDepCop NuGet package **v1.7.1** have introduced the NsDepCop ServiceHost to improve build performance.
* It runs in the background as a standalone process, communicates via named pipes and serves requests coming from NsDepCopTask instances running inside MSBuild processes.
* It is started automatically when needed by an NsDepCopTask and quits automatically when the MSBuild process that started it exits.
* By running continuously it avoids the repeated startup times which is significant.
You can control the lifetime of NsDepCop ServiceHost by controlling the lifetime of the MSBuild processes by modifying the **MSBUILDDISABLENODEREUSE** environment variable.
* 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.
* 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.**
================================================
FILE: doc/Troubleshooting.md
================================================
# NsDepCop Troubleshooting
* [Exception: Unable to communicate with NsDepCop service](#item5)
* [NsDepCop NuGet package is not adding config.nsdepcop file to the project](#item4)
* [Anonymous types raise false alarms](#item3)
<a name="item5"></a>
## Exception: Unable to communicate with NsDepCop service
> Applies only to versions before v2.0.
This 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.
To fix it:
* Update to v1.10.1 or later.
* 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).
* E.g. this config waits 100ms, then 1sec, then 10sec:
```xml
<NsDepCopConfig AnalyzerServiceCallRetryTimeSpans="100,1000,10000">
```
<a name="item4"></a>
## NsDepCop NuGet package is not adding config.nsdepcop file to the project
> Applies only to versions before v2.0.
If the project uses the **PackageReference** package manager format then content files are not added to the project.
Workaround:
* **Add** a file called **config.nsdepcop** and fill it in using the examples in [Help](Help.md).
* Install the NsDepCop Visual Studio Extension [](https://marketplace.visualstudio.com/items?itemName=FerencVizkeleti.NsDepCopVS2017-CodedependencycheckerforC) and then:
* Right-click on project >> Add >> New Item... >> NsDepCop Config File
<a name="item3"></a>
## Anonymous types raise false alarms
> Applies only to versions before v1.6.
For 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.
To avoid alarms caused by anonymous types you have to add a rule that you allow referencing the global namespace:
```xml
<Allowed From="YourNamespace" To="." />
```
Or to be more lax:
```xml
<Allowed From="*" To="." />
```
================================================
FILE: source/.editorconfig
================================================
root = true
[*.cs]
# Default severity for analyzer diagnostics with category 'MicrosoftCodeAnalysisReleaseTracking'
dotnet_analyzer_diagnostic.category-MicrosoftCodeAnalysisReleaseTracking.severity = none
# NSDEPCOP01: Illegal namespace reference.
dotnet_diagnostic.NSDEPCOP01.severity = error
================================================
FILE: source/Directory.Build.targets
================================================
<Project>
<!--Begin: Avoid cycle error when package builds itself-->
<Choose>
<When Condition="$(AvoidCycleErrorOnSelfReference) == 'true'">
<PropertyGroup>
<PackageId Condition="'$(PackageId)' == ''">$(MSBuildProjectName)</PackageId>
<PackageIdTemp>$(PackageId)</PackageIdTemp>
<PackageId>$(PackageId)_temp</PackageId>
</PropertyGroup>
</When>
</Choose>
<Target Name="_UpdatePackageId" BeforeTargets="$(PackDependsOn)"
Condition="$(AvoidCycleErrorOnSelfReference) == 'true'">
<PropertyGroup>
<PackageId>$(PackageIdTemp)</PackageId>
</PropertyGroup>
</Target>
<!--End: Avoid cycle error when package builds itself-->
</Project>
================================================
FILE: source/NsDepCop.Analyzer/Analysis/AssemblyDependency.cs
================================================
using System;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis
{
[Serializable]
public struct AssemblyDependency
{
public static AssemblyDependency Empty;
public AssemblyIdentity FromAssembly { get; }
public AssemblyIdentity ToAssembly { get; }
public AssemblyDependency(AssemblyIdentity fromAssembly, AssemblyIdentity toAssembly)
{
FromAssembly = fromAssembly ?? throw new ArgumentNullException(nameof(fromAssembly));
ToAssembly = toAssembly ?? throw new ArgumentNullException(nameof(toAssembly));
}
public override string ToString() => $"{FromAssembly?.Name}->{ToAssembly?.Name}";
public bool Equals(AssemblyDependency other)
{
return string.Equals(FromAssembly?.Name, other.FromAssembly?.Name)
&& string.Equals(ToAssembly?.Name, other.ToAssembly?.Name);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is AssemblyDependency && Equals((AssemblyDependency)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (FromAssembly != null ? FromAssembly.Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ToAssembly != null ? ToAssembly.Name.GetHashCode() : 0);
return hashCode;
}
}
public static bool operator ==(AssemblyDependency left, AssemblyDependency right)
{
return left.Equals(right);
}
public static bool operator !=(AssemblyDependency left, AssemblyDependency right)
{
return !left.Equals(right);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Factory/AssemblyDependencyAnalyzerFactory.cs
================================================
using Codartis.NsDepCop.Analysis.Implementation;
using Codartis.NsDepCop.Config;
namespace Codartis.NsDepCop.Analysis.Factory
{
public sealed class AssemblyDependencyAnalyzerFactory : IAssemblyDependencyAnalyzerFactory
{
public IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider configProvider)
{
return new AssemblyDependencyAnalyzer(configProvider);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Factory/DependencyAnalyzerFactory.cs
================================================
using Codartis.NsDepCop.Analysis.Implementation;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Analysis.Factory
{
/// <summary>
/// Creates dependency analyzer objects.
/// </summary>
public sealed class DependencyAnalyzerFactory : IDependencyAnalyzerFactory
{
private readonly MessageHandler _traceMessageHandler;
public DependencyAnalyzerFactory(MessageHandler traceMessageHandler)
{
_traceMessageHandler = traceMessageHandler;
}
public IDependencyAnalyzer Create(IUpdateableConfigProvider configProvider, ITypeDependencyEnumerator typeDependencyEnumerator)
{
return new DependencyAnalyzer(configProvider, typeDependencyEnumerator, _traceMessageHandler);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzer.cs
================================================
using System;
using System.Collections.Generic;
using Codartis.NsDepCop.Analysis.Messages;
using Codartis.NsDepCop.Config;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Performs assembly dependency analysis on a project.
/// </summary>
public interface IAssemblyDependencyAnalyzer
{
IEnumerable<AnalyzerMessageBase> AnalyzeProject(AssemblyIdentity sourceAssembly, IReadOnlyList<AssemblyIdentity> referencedAssemblies);
/// <summary>
/// Re-reads the config.
/// </summary>
void RefreshConfig();
/// <summary>
/// Gets the current config state.
/// </summary>
AnalyzerConfigState ConfigState { get; }
/// <summary>
/// Gets the config exception or null if there was no exception.
/// </summary>
Exception ConfigException { get; }
/// <summary>
/// Gets the current analyzer config or null if there was an error.
/// </summary>
IAnalyzerConfig Config { get; }
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzerFactory.cs
================================================
using Codartis.NsDepCop.Config;
namespace Codartis.NsDepCop.Analysis
{
public interface IAssemblyDependencyAnalyzerFactory
{
IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider configProvider);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzer.cs
================================================
using System;
using System.Collections.Generic;
using Codartis.NsDepCop.Analysis.Messages;
using Codartis.NsDepCop.Config;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Performs dependency analysis on a project or a syntax node.
/// </summary>
public interface IDependencyAnalyzer
{
/// <summary>
/// Analyzes a project (source files and referenced assemblies).
/// </summary>
/// <param name="sourceFilePaths">A collection of the full path of source files.</param>
/// <param name="referencedAssemblyPaths">A collection of the full path of referenced assemblies.</param>
/// <returns>Issue and info messages, including illegal dependency issues.</returns>
IEnumerable<AnalyzerMessageBase> AnalyzeProject(IEnumerable<string> sourceFilePaths, IEnumerable<string> referencedAssemblyPaths);
/// <summary>
/// Analyzes a syntax node.
/// </summary>
/// <param name="syntaxNode">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the project being analyzed.</param>
/// <returns>Issue and info messages, including illegal dependency issues.</returns>
IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode syntaxNode, SemanticModel semanticModel);
/// <summary>
/// Re-reads the config.
/// </summary>
void RefreshConfig();
/// <summary>
/// Gets the current config state.
/// </summary>
AnalyzerConfigState ConfigState { get; }
/// <summary>
/// Gets the config exception or null if there was no exception.
/// </summary>
Exception ConfigException { get; }
/// <summary>
/// Gets the current analyzer config or null if there was an error.
/// </summary>
IAnalyzerConfig Config { get; }
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzerFactory.cs
================================================
using Codartis.NsDepCop.Config;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Creates dependency analyzer objects.
/// </summary>
public interface IDependencyAnalyzerFactory
{
IDependencyAnalyzer Create(IUpdateableConfigProvider configProvider, ITypeDependencyEnumerator typeDependencyEnumerator);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/ITypeDependencyEnumerator.cs
================================================
using System.Collections.Generic;
using DotNet.Globbing;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Enumerates type dependencies for a project or a syntax node.
/// </summary>
public interface ITypeDependencyEnumerator
{
/// <summary>
/// Enumerates type dependencies for a project (source files and referenced assemblies).
/// </summary>
/// <param name="sourceFilePaths">A collection of the full path of source files.</param>
/// <param name="referencedAssemblyPaths">A collection of the full path of referenced assemblies.</param>
/// <param name="sourcePathExclusionGlobs">A collection of file path patterns (globs) for excluding source files from analysis.</param>
/// <returns>A collection of type dependencies.</returns>
IEnumerable<TypeDependency> GetTypeDependencies(
IEnumerable<string> sourceFilePaths,
IEnumerable<string> referencedAssemblyPaths,
IEnumerable<Glob> sourcePathExclusionGlobs);
/// <summary>
/// Enumerates type dependencies for a syntax node.
/// </summary>
/// <param name="syntaxNode">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the project being analyzed.</param>
/// <param name="sourcePathExclusionGlobs">A collection of file path patterns (globs) for excluding source files from analysis.</param>
/// <returns>A collection of type dependencies.</returns>
IEnumerable<TypeDependency> GetTypeDependencies(
SyntaxNode syntaxNode,
SemanticModel semanticModel,
IEnumerable<Glob> sourcePathExclusionGlobs);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyAnalyzer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using Codartis.NsDepCop.Analysis.Messages;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis.Implementation
{
public sealed class AssemblyDependencyAnalyzer : IAssemblyDependencyAnalyzer
{
private readonly IUpdateableConfigProvider _configProvider;
private readonly object _configRefreshLock = new();
private IAssemblyDependencyValidator _assemblyDependencyValidator;
private IAnalyzerConfig _config;
public AssemblyDependencyAnalyzer(
IUpdateableConfigProvider configProvider)
{
_configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));
UpdateConfig();
}
public AnalyzerConfigState ConfigState
{
get
{
lock (_configRefreshLock)
{
return _configProvider.ConfigState;
}
}
}
public Exception ConfigException
{
get
{
lock (_configRefreshLock)
{
return _configProvider.ConfigException;
}
}
}
public IAnalyzerConfig Config
{
get
{
lock (_configRefreshLock)
{
return _configProvider.Config;
}
}
}
public IEnumerable<AnalyzerMessageBase> AnalyzeProject(
AssemblyIdentity sourceAssembly,
IReadOnlyList<AssemblyIdentity> referencedAssemblies)
{
if (sourceAssembly == null) throw new ArgumentNullException(nameof(sourceAssembly));
if (referencedAssemblies == null) throw new ArgumentNullException(nameof(referencedAssemblies));
if (GlobalSettings.IsToolDisabled())
return [new ToolDisabledMessage()];
lock (_configRefreshLock)
{
var assemblyDependencyEnumerable = GetAssemblyDependencies(sourceAssembly, referencedAssemblies);
var illegalAssemblyDependencyEnumerable = GetIllegalAssemblyDependencies(assemblyDependencyEnumerable);
return AnalyzeCore(illegalAssemblyDependencyEnumerable);
}
}
private IEnumerable<AssemblyDependency> GetAssemblyDependencies(AssemblyIdentity sourceAssembly, IReadOnlyList<AssemblyIdentity> referencedAssemblies)
{
foreach (AssemblyIdentity referencedAssembly in referencedAssemblies)
{
yield return new AssemblyDependency(sourceAssembly, referencedAssembly);
}
}
public void RefreshConfig()
{
lock (_configRefreshLock)
{
_configProvider.RefreshConfig();
UpdateConfig();
}
}
private void UpdateConfig()
{
var oldConfig = _config;
_config = _configProvider.Config;
if (oldConfig == _config)
return;
_assemblyDependencyValidator = CreateTypeDependencyValidator();
}
private AssemblyDependencyValidator CreateTypeDependencyValidator()
{
return _configProvider.ConfigState == AnalyzerConfigState.Enabled
? new AssemblyDependencyValidator(_configProvider.Config)
: null;
}
private IEnumerable<AnalyzerMessageBase> AnalyzeCore(IEnumerable<AssemblyDependency> illegalTypeDependencyEnumerable)
{
return _configProvider.ConfigState switch
{
AnalyzerConfigState.NoConfig => new NoConfigFileMessage().ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.Disabled => new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.ConfigError => new ConfigErrorMessage(_configProvider.ConfigException).ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.Enabled => _configProvider.Config.CheckAssemblyDependencies
? PerformAnalysis(illegalTypeDependencyEnumerable)
: new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),
_ => throw new Exception($"Unexpected ConfigState: {_configProvider.ConfigState}")
};
}
private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(IEnumerable<AssemblyDependency> illegalTypeDependencyEnumerator)
{
return illegalTypeDependencyEnumerator.Select(element => new IllegalAssemblyDependencyMessage(element));
}
private IEnumerable<AssemblyDependency> GetIllegalAssemblyDependencies(IEnumerable<AssemblyDependency> assemblyDependencyEnumerator)
{
foreach (AssemblyDependency assemblyDependency in assemblyDependencyEnumerator)
{
DependencyStatus dependencyStatus = _assemblyDependencyValidator.IsDependencyAllowed(assemblyDependency);
if (!dependencyStatus.IsAllowed)
{
yield return assemblyDependency;
}
}
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyValidator.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Analysis.Implementation
{
public sealed class AssemblyDependencyValidator : IAssemblyDependencyValidator
{
private readonly HashSet<DependencyRule> _allowRules;
private readonly HashSet<DependencyRule> _disallowRules;
public AssemblyDependencyValidator(IDependencyRules dependencyRules)
{
if (dependencyRules is null) throw new ArgumentNullException(nameof(dependencyRules));
_allowRules = dependencyRules.AllowedAssemblyRules;
_disallowRules = dependencyRules.DisallowedAssemblyRules;
}
public DependencyStatus IsDependencyAllowed(AssemblyDependency assemblyDependency)
{
if (assemblyDependency == AssemblyDependency.Empty)
{
throw new ArgumentException("The parameter is empty.", nameof(assemblyDependency));
}
// These assembly names are coming from a compiler so we don't have to validate them.
var fromAssembly = new Domain(assemblyDependency.FromAssembly.Name, validate: false);
var toAssembly = new Domain(assemblyDependency.ToAssembly.Name, validate: false);
var disallowRule = GetDisallowRule(fromAssembly, toAssembly);
if (disallowRule is not null)
return DependencyStatus.Disallowed;
var allowRule = GetMostSpecificAllowRule(fromAssembly, toAssembly);
if (allowRule is null)
return DependencyStatus.Disallowed;
return DependencyStatus.Allowed;
}
private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)
{
return _allowRules
.Where(element => element.From.Matches(from) && element.To.Matches(to))
.MaxByOrDefault(element => element.From.GetMatchRelevance(from));
}
private DependencyRule GetDisallowRule(Domain from, Domain to)
{
return _disallowRules.FirstOrDefault(element => element.From.Matches(from) && element.To.Matches(to));
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/CachingTypeDependencyValidator.cs
================================================
using System.Collections.Concurrent;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Analysis.Implementation
{
/// <summary>
/// Validates type dependencies to a set of allowed/disallowed rules and caches the results.
/// </summary>
public class CachingTypeDependencyValidator : TypeDependencyValidator, ICacheStatisticsProvider
{
private readonly MessageHandler _traceMessageHandler;
private readonly ConcurrentDictionary<TypeDependency, DependencyStatus> _dependencyValidationCache;
public int HitCount { get; private set; }
public int MissCount { get; private set; }
public CachingTypeDependencyValidator(IDependencyRules dependencyRules, MessageHandler traceMessageHandler)
: base(dependencyRules)
{
_traceMessageHandler = traceMessageHandler;
_dependencyValidationCache = new ConcurrentDictionary<TypeDependency, DependencyStatus>();
}
public double EfficiencyPercent => MathHelper.CalculatePercent(HitCount, HitCount + MissCount);
public override DependencyStatus IsAllowedDependency(TypeDependency typeDependency)
{
if (typeDependency.FromNamespaceName == typeDependency.ToNamespaceName)
return DependencyStatus.Allowed;
var isAllowedDependency = _dependencyValidationCache.GetOrAdd(typeDependency, base.IsAllowedDependency, out var added);
if (added)
{
MissCount++;
LogTraceMessage($"Dependency {typeDependency} added to cache as {isAllowedDependency}.");
}
else
{
HitCount++;
}
return isAllowedDependency;
}
private void LogTraceMessage(string message) => _traceMessageHandler?.Invoke(message);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/DependencyAnalyzer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using Codartis.NsDepCop.Analysis.Messages;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
using DotNet.Globbing;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.Analysis.Implementation
{
/// <summary>
/// Abstract base class for dependency analyzers.
/// </summary>
public sealed class DependencyAnalyzer : IDependencyAnalyzer
{
private readonly IUpdateableConfigProvider _configProvider;
private readonly MessageHandler _traceMessageHandler;
private readonly ITypeDependencyEnumerator _typeDependencyEnumerator;
private readonly object _configRefreshLock = new();
private CachingTypeDependencyValidator _typeDependencyValidator;
private IAnalyzerConfig _config;
private Glob[] _sourcePathExclusionGlobs;
public DependencyAnalyzer(
IUpdateableConfigProvider configProvider,
ITypeDependencyEnumerator typeDependencyEnumerator,
MessageHandler traceMessageHandler)
{
_configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));
_traceMessageHandler = traceMessageHandler;
_typeDependencyEnumerator = typeDependencyEnumerator ?? throw new ArgumentNullException(nameof(typeDependencyEnumerator));
UpdateConfig();
}
public AnalyzerConfigState ConfigState
{
get
{
lock (_configRefreshLock)
{
return _configProvider.ConfigState;
}
}
}
public Exception ConfigException
{
get
{
lock (_configRefreshLock)
{
return _configProvider.ConfigException;
}
}
}
public IAnalyzerConfig Config
{
get
{
lock (_configRefreshLock)
{
return _configProvider.Config;
}
}
}
public IEnumerable<AnalyzerMessageBase> AnalyzeProject(
IEnumerable<string> sourceFilePaths,
IEnumerable<string> referencedAssemblyPaths)
{
if (sourceFilePaths == null) throw new ArgumentNullException(nameof(sourceFilePaths));
if (referencedAssemblyPaths == null) throw new ArgumentNullException(nameof(referencedAssemblyPaths));
if (GlobalSettings.IsToolDisabled())
return new[] {new ToolDisabledMessage()};
lock (_configRefreshLock)
{
return AnalyzeCore(
() => GetIllegalTypeDependencies(
() => _typeDependencyEnumerator.GetTypeDependencies(sourceFilePaths, referencedAssemblyPaths, _sourcePathExclusionGlobs))
);
}
}
public IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode syntaxNode, SemanticModel semanticModel)
{
if (syntaxNode == null) throw new ArgumentNullException(nameof(syntaxNode));
if (semanticModel == null) throw new ArgumentNullException(nameof(semanticModel));
lock (_configRefreshLock)
{
return AnalyzeCore(
() => GetIllegalTypeDependencies(
() => _typeDependencyEnumerator.GetTypeDependencies(syntaxNode, semanticModel, _sourcePathExclusionGlobs))
);
}
}
public void RefreshConfig()
{
lock (_configRefreshLock)
{
_configProvider.RefreshConfig();
UpdateConfig();
}
}
private void UpdateConfig()
{
var oldConfig = _config;
_config = _configProvider.Config;
if (oldConfig == _config)
return;
_typeDependencyValidator = CreateTypeDependencyValidator();
_sourcePathExclusionGlobs = _config.SourcePathExclusionPatterns.Select(Glob.Parse).ToArray();
}
private CachingTypeDependencyValidator CreateTypeDependencyValidator()
{
return _configProvider.ConfigState == AnalyzerConfigState.Enabled
? new CachingTypeDependencyValidator(_configProvider.Config, _traceMessageHandler)
: null;
}
private IEnumerable<AnalyzerMessageBase> AnalyzeCore(Func<IEnumerable<IllegalTypeDependency>> illegalTypeDependencyEnumerator)
{
return _configProvider.ConfigState switch
{
AnalyzerConfigState.NoConfig => new NoConfigFileMessage().ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.Disabled => new ConfigDisabledMessage().ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.ConfigError => new ConfigErrorMessage(_configProvider.ConfigException).ToEnumerable<AnalyzerMessageBase>(),
AnalyzerConfigState.Enabled => PerformAnalysis(illegalTypeDependencyEnumerator),
_ => throw new Exception($"Unexpected ConfigState: {_configProvider.ConfigState}")
};
}
private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(Func<IEnumerable<IllegalTypeDependency>> illegalTypeDependencyEnumerator)
{
return illegalTypeDependencyEnumerator().Select(i => new IllegalDependencyMessage(i.TypeDependency, i.AllowedMembers));
// TODO: AutoLowerMaxIssueCount logic should be moved to NsDepCopAnalyzer to act at the end of a compilation.
// This method is called multiple times during a compilation so we don't know the final issue count here
//var finalIssueCount = GetInterlocked(ref issueCount);
//if (config.AutoLowerMaxIssueCount && finalIssueCount < maxIssueCount)
// ConfigProvider.UpdateMaxIssueCount(finalIssueCount);
}
private IEnumerable<IllegalTypeDependency> GetIllegalTypeDependencies(Func<IEnumerable<TypeDependency>> typeDependencyEnumerator)
{
var allDependencies = typeDependencyEnumerator()
.Select(dep => (Dependency: dep, Status: _typeDependencyValidator.IsAllowedDependency(dep)));
var excessIllegalDependencies = allDependencies
.Where(i => !i.Status.IsAllowed)
.Take(_config.MaxIssueCount + 1);
foreach (var illegalDependency in excessIllegalDependencies)
{
yield return new IllegalTypeDependency(illegalDependency.Dependency, illegalDependency.Status.AllowedTypeNames);
}
_traceMessageHandler?.Invoke(GetCacheStatisticsMessage(_typeDependencyValidator));
}
private static string GetCacheStatisticsMessage(ICacheStatisticsProvider i) =>
$"Cache hits: {i.HitCount}, misses: {i.MissCount}, efficiency (hits/all): {i.EfficiencyPercent:P}";
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/DependencyStatus.cs
================================================
using System;
namespace Codartis.NsDepCop.Analysis.Implementation
{
public class DependencyStatus
{
private DependencyStatus()
{
}
public bool IsAllowed { get; private set; }
public string[] AllowedTypeNames { get; private set; } = Array.Empty<string>();
public static readonly DependencyStatus Allowed = new() { IsAllowed = true };
public static readonly DependencyStatus Disallowed = new() { IsAllowed = false };
public static DependencyStatus DisallowedUseOfMember(string[] allowedTypeNames) =>
new() { IsAllowed = false, AllowedTypeNames = allowedTypeNames };
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/IAssemblyDependencyValidator.cs
================================================
namespace Codartis.NsDepCop.Analysis.Implementation
{
public interface IAssemblyDependencyValidator
{
DependencyStatus IsDependencyAllowed(AssemblyDependency assemblyDependency);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/ITypeDependencyValidator.cs
================================================
namespace Codartis.NsDepCop.Analysis.Implementation
{
/// <summary>
/// Determines whether a type-to-type dependency is allowed or not.
/// </summary>
internal interface ITypeDependencyValidator
{
/// <summary>
/// Decides whether a dependency is allowed based on the rule configuration.
/// </summary>
/// <param name="typeDependency">A dependency of two types.</param>
/// <returns>True if the dependency is allowed, false otherwise.</returns>
DependencyStatus IsAllowedDependency(TypeDependency typeDependency);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/IllegalTypeDependency.cs
================================================
namespace Codartis.NsDepCop.Analysis.Implementation
{
public class IllegalTypeDependency
{
public TypeDependency TypeDependency { get; }
public string[] AllowedMembers { get; }
public IllegalTypeDependency(TypeDependency typeDependency, string[] allowedMembers)
{
TypeDependency = typeDependency;
AllowedMembers = allowedMembers;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/TypeDependencyValidator.cs
================================================
using System.Collections.Generic;
using System.Linq;
using Codartis.NsDepCop.Config;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Analysis.Implementation
{
/// <summary>
/// Determines whether a given type-to-type dependency is allowed.
/// </summary>
public class TypeDependencyValidator : ITypeDependencyValidator
{
private readonly Dictionary<DependencyRule, TypeNameSet> _allowRules;
private readonly HashSet<DependencyRule> _disallowRules;
private readonly Dictionary<Domain, TypeNameSet> _visibleTypesPerNamespaces;
private readonly bool _childCanDependOnParentImplicitly;
private readonly bool _parentCanDependOnChildImplicitly;
public TypeDependencyValidator(IDependencyRules dependencyRules)
{
_allowRules = dependencyRules.AllowRules;
_disallowRules = dependencyRules.DisallowRules;
_visibleTypesPerNamespaces = dependencyRules.VisibleTypesByNamespace;
_childCanDependOnParentImplicitly = dependencyRules.ChildCanDependOnParentImplicitly;
_parentCanDependOnChildImplicitly = dependencyRules.ParentCanDependOnChildImplicitly;
}
/// <summary>
/// Decides whether a dependency is allowed based on the rule configuration.
/// </summary>
/// <param name="typeDependency">A dependency of two types.</param>
/// <returns>True if the dependency is allowed, false otherwise.</returns>
public virtual DependencyStatus IsAllowedDependency(TypeDependency typeDependency)
{
// Inside a namespace all dependencies are allowed.
if (typeDependency.FromNamespaceName == typeDependency.ToNamespaceName)
return DependencyStatus.Allowed;
// These namespace names are coming from a compiler so we don't have to validate them.
var fromNamespace = new Domain(typeDependency.FromNamespaceName, validate: false);
var toNamespace = new Domain(typeDependency.ToNamespaceName, validate: false);
var disallowRule = GetDisallowRule(fromNamespace, toNamespace);
if (disallowRule != null)
return DependencyStatus.Disallowed;
if (IsAllowedBecauseChildCanDependOnParent(fromNamespace, toNamespace))
return DependencyStatus.Allowed;
if (IsAllowedBecauseParentCanDependOnChild(fromNamespace, toNamespace))
return DependencyStatus.Allowed;
var allowRule = GetMostSpecificAllowRule(fromNamespace, toNamespace);
if (allowRule == null)
return DependencyStatus.Disallowed;
TypeNameSet visibleMembers = GetVisibleMembers(allowRule, toNamespace);
if (visibleMembers == null || visibleMembers.Count == 0)
return DependencyStatus.Allowed;
bool isUsingVisibleMember = visibleMembers.Contains(typeDependency.ToTypeName);
return isUsingVisibleMember
? DependencyStatus.Allowed
: DependencyStatus.DisallowedUseOfMember(visibleMembers.ToArray());
}
private bool IsAllowedBecauseChildCanDependOnParent(Domain fromNamespace, Domain toNamespace)
{
return _childCanDependOnParentImplicitly && fromNamespace.IsSubDomain(toNamespace);
}
private bool IsAllowedBecauseParentCanDependOnChild(Domain fromNamespace, Domain toNamespace)
{
return _parentCanDependOnChildImplicitly && toNamespace.IsSubDomain(fromNamespace);
}
private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)
{
return _allowRules.Keys
.Where(i => i.From.Matches(from) && i.To.Matches(to))
.MaxByOrDefault(i => i.From.GetMatchRelevance(from));
}
private DependencyRule GetDisallowRule(Domain from, Domain to)
{
return _disallowRules
.FirstOrDefault(i => i.From.Matches(from) && i.To.Matches(to));
}
private TypeNameSet GetVisibleMembers(DependencyRule allowRule, Domain targetNamespace)
{
TypeNameSet allowedTypeNameSet;
if (_allowRules.TryGetValue(allowRule, out allowedTypeNameSet) &&
allowedTypeNameSet != null &&
allowedTypeNameSet.Any())
return allowedTypeNameSet;
if (_visibleTypesPerNamespaces.TryGetValue(targetNamespace, out allowedTypeNameSet))
return allowedTypeNameSet;
return null;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/AnalyzerMessageBase.cs
================================================
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// Abstract base class for messages returned by the dependency analyzer.
/// </summary>
public abstract class AnalyzerMessageBase
{
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ConfigDisabledMessage.cs
================================================
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// A message indicating that analysis was disabled in the config file.
/// </summary>
public sealed class ConfigDisabledMessage : AnalyzerMessageBase
{
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ConfigErrorMessage.cs
================================================
using System;
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// A message that describes a config exception.
/// </summary>
public sealed class ConfigErrorMessage : AnalyzerMessageBase
{
public Exception Exception { get; }
public ConfigErrorMessage(Exception exception)
{
Exception = exception;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/IllegalAssemblyDependencyMessage.cs
================================================
namespace Codartis.NsDepCop.Analysis.Messages
{
public sealed class IllegalAssemblyDependencyMessage : AnalyzerMessageBase
{
public AssemblyDependency IllegalAssemblyDependency { get; }
public IllegalAssemblyDependencyMessage(AssemblyDependency illegalAssemblyDependency)
{
IllegalAssemblyDependency = illegalAssemblyDependency;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/IllegalDependencyMessage.cs
================================================
using System;
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// A message containing an illegal type dependency.
/// </summary>
public sealed class IllegalDependencyMessage : AnalyzerMessageBase
{
public TypeDependency IllegalDependency { get; }
public string[] AllowedMemberNames { get; } = Array.Empty<string>();
public IllegalDependencyMessage(TypeDependency illegalDependency, string[] allowedMemberNames)
{
IllegalDependency = illegalDependency;
AllowedMemberNames = allowedMemberNames;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/NoConfigFileMessage.cs
================================================
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// A message indicating that no config file was found for a project or location.
/// </summary>
public sealed class NoConfigFileMessage : AnalyzerMessageBase
{
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ToolDisabledMessage.cs
================================================
namespace Codartis.NsDepCop.Analysis.Messages
{
/// <summary>
/// A message indicating that analysis was disabled with environment variable.
/// </summary>
public sealed class ToolDisabledMessage : AnalyzerMessageBase
{
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/SourceSegment.cs
================================================
using System;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Describes a certain segment of a source file. Immutable.
/// </summary>
[Serializable]
public struct SourceSegment
{
/// <summary>
/// The line number of the segment's start (1-based).
/// </summary>
public int StartLine { get; }
/// <summary>
/// The column number of the segment's start (1-based).
/// </summary>
public int StartColumn { get; }
/// <summary>
/// The line number of the segment's end (1-based).
/// </summary>
public int EndLine { get; }
/// <summary>
/// The column number of the segment's end (1-based).
/// </summary>
public int EndColumn { get; }
/// <summary>
/// The text of the segment.
/// </summary>
public string Text { get; }
/// <summary>
/// The full path of the source file.
/// </summary>
public string Path { get; }
public SourceSegment(int startLine, int startColumn, int endLine, int endColumn, string text, string path)
{
StartLine = startLine;
StartColumn = startColumn;
EndLine = endLine;
EndColumn = endColumn;
Text = text;
Path = path;
}
public override string ToString() => $"{Path} ({StartLine},{StartColumn},{EndLine},{EndColumn})";
}
}
================================================
FILE: source/NsDepCop.Analyzer/Analysis/TypeDependency.cs
================================================
using System;
namespace Codartis.NsDepCop.Analysis
{
/// <summary>
/// Describes a dependency between two types at a source segment.
/// Immutable.
/// </summary>
[Serializable]
public struct TypeDependency
{
/// <summary>
/// The namespace of the referencing type.
/// </summary>
public string FromNamespaceName { get; }
/// <summary>
/// The name of the referencing type.
/// </summary>
public string FromTypeName { get; }
/// <summary>
/// The namespace of the referenced type.
/// </summary>
public string ToNamespaceName { get; }
/// <summary>
/// The name of the referenced type.
/// </summary>
public string ToTypeName { get; }
/// <summary>
/// The source segment where the dependency was found.
/// </summary>
public SourceSegment SourceSegment { get; }
public TypeDependency(string fromNamespaceName, string fromTypeName, string toNamespaceName, string toTypeName, SourceSegment sourceSegment)
{
if (string.IsNullOrWhiteSpace(fromTypeName))
throw new ArgumentException("Should not be null or whitespace.", nameof(fromTypeName));
if (string.IsNullOrWhiteSpace(toTypeName))
throw new ArgumentException("Should not be null or whitespace.", nameof(toTypeName));
FromNamespaceName = fromNamespaceName ?? throw new ArgumentNullException(nameof(fromNamespaceName));
FromTypeName = fromTypeName;
ToNamespaceName = toNamespaceName ?? throw new ArgumentNullException(nameof(toNamespaceName));
ToTypeName = toTypeName;
SourceSegment = sourceSegment;
}
// TODO: should print source segment too
public override string ToString() => $"{FromNamespaceName}.{FromTypeName}->{ToNamespaceName}.{ToTypeName}";
// TODO: should consider source segment too
public bool Equals(TypeDependency other)
{
return string.Equals(FromNamespaceName, other.FromNamespaceName)
&& string.Equals(FromTypeName, other.FromTypeName)
&& string.Equals(ToNamespaceName, other.ToNamespaceName)
&& string.Equals(ToTypeName, other.ToTypeName);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is TypeDependency && Equals((TypeDependency) obj);
}
// TODO: should consider source segment too
public override int GetHashCode()
{
unchecked
{
var hashCode = (FromNamespaceName != null ? FromNamespaceName.GetHashCode() : 0);
hashCode = (hashCode*397) ^ (FromTypeName != null ? FromTypeName.GetHashCode() : 0);
hashCode = (hashCode*397) ^ (ToNamespaceName != null ? ToNamespaceName.GetHashCode() : 0);
hashCode = (hashCode*397) ^ (ToTypeName != null ? ToTypeName.GetHashCode() : 0);
return hashCode;
}
}
public static bool operator ==(TypeDependency left, TypeDependency right)
{
return left.Equals(right);
}
public static bool operator !=(TypeDependency left, TypeDependency right)
{
return !left.Equals(right);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/AnalyzerConfigState.cs
================================================
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Enumerates the possible states of an analyzer's config.
/// </summary>
public enum AnalyzerConfigState
{
Enabled,
Disabled,
NoConfig,
ConfigError
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/ConfigDefaults.cs
================================================
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Defines the default values of the config properties.
/// </summary>
public static class ConfigDefaults
{
public const int InheritanceDepth = 0;
public const bool IsEnabled = true;
public const bool CheckAssemblyDependencies = false;
public const int MaxIssueCount = 100;
public const bool AutoLowerMaxIssueCount = false;
public const bool ChildCanDependOnParentImplicitly = false;
public const bool ParentCanDependOnChildImplicitly = false;
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/DependencyRule.cs
================================================
using System;
using System.Text;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Represents a dependency rule between two domain specifications. Immutable.
/// </summary>
/// <remarks>
/// The 'From' domain specification depends on the 'To' domain specification.
/// A domain specification can represent more than just a single domain (eg. a subtree of namespaces).
/// </remarks>
[Serializable]
public class DependencyRule
{
/// <summary>
/// The dependency points from this domain to the other.
/// </summary>
public DomainSpecification From { get; }
/// <summary>
/// The dependency points into this domain.
/// </summary>
public DomainSpecification To { get; }
/// <summary>
/// Initializes a new instance.
/// </summary>
/// <param name="from">The source of the dependency.</param>
/// <param name="to">The target of the dependency.</param>
public DependencyRule(DomainSpecification from, DomainSpecification to)
{
From = from ?? throw new ArgumentNullException(nameof(from));
To = to ?? throw new ArgumentNullException(nameof(to));
}
/// <summary>
/// Initializes a new instance by converting the string parameters to NamespaceSpecification objects.
/// </summary>
/// <param name="from">A namespace specification in string format. The source of the dependency.</param>
/// <param name="to">A namespace specification in string format. The target of the dependency.</param>
public DependencyRule(string from, string to)
: this(DomainSpecificationParser.Parse(from), DomainSpecificationParser.Parse(to))
{ }
/// <summary>
/// Returns the string representation of a namespace dependency.
/// </summary>
/// <returns>The string representation of a namespace dependency.</returns>
public override string ToString()
{
var builder = new StringBuilder();
builder.Append(From);
builder.Append("->");
builder.Append(To);
return builder.ToString();
}
public bool Equals(DependencyRule other)
{
return Equals(From, other.From) && Equals(To, other.To);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((DependencyRule)obj);
}
public override int GetHashCode()
{
unchecked
{
return ((From != null ? From.GetHashCode() : 0) * 397) ^ (To != null ? To.GetHashCode() : 0);
}
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Domain.cs
================================================
using System;
using System.Linq;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Represents a domain, eg. 'A.B'. Immutable.
/// </summary>
/// <remarks>
/// The global domain is also a domain and it's represented by '.' (a dot)
/// </remarks>
[Serializable]
public sealed class Domain : DomainSpecification
{
public const string RootDomainMarker = ".";
/// <summary>
/// Represents the global domain.
/// </summary>
public static readonly Domain GlobalDomain = new Domain(RootDomainMarker);
/// <summary>
/// Creates a new instance from a string representation.
/// </summary>
/// <param name="domainAsString">The string representation of a domain.</param>
/// <param name="validate">True means validate the input string.</param>
public Domain(string domainAsString, bool validate = true)
: base(Normalize(domainAsString), validate, IsValid)
{
}
public override int GetMatchRelevance(Domain domain)
{
return this == domain
? int.MaxValue
: 0;
}
/// <summary>
/// Determines whether this domain is a sub-domain of the given other one.
/// </summary>
/// <param name="parentCandidate">The domain to test whether it's a parent of the current domain.</param>
/// <returns>True if this domain is a sub-domain of the given one, false otherwise.</returns>
public bool IsSubDomain(Domain parentCandidate)
{
if (this == GlobalDomain)
return false;
if (parentCandidate == GlobalDomain)
return true;
var parentPrefix = parentCandidate.Value + DomainPartSeparator;
return Value.StartsWith(parentPrefix);
}
/// <summary>
/// Validates that the given string represents a valid domain specification.
/// </summary>
/// <param name="domainAsString">A domain specification in string format.</param>
/// <returns>True if the given string represents a valid domain specification.</returns>
public static bool IsValid(string domainAsString)
{
if (domainAsString == RootDomainMarker)
return true;
if (domainAsString.Any(c => c == WildcardDomain.AnyDomainMarker[0] || c == WildcardDomain.SingleDomainMarker[0]))
return false;
var pieces = domainAsString.Split(new[] { DomainPartSeparator }, StringSplitOptions.None);
return pieces.All(i => !string.IsNullOrWhiteSpace(i));
}
/// <summary>
/// Converts the input string into a standard representation (removes ambiguities).
/// </summary>
/// <param name="domainAsString">A domain specification in string format.</param>
/// <returns>The standard representation of the given domain specification string.</returns>
private static string Normalize(string domainAsString)
{
// Global domain representations:
// Roslyn: "<global namespace>"
// NRefactory: "" (empty string)
// NsDepCop: "." (dot)
if (domainAsString == "" ||
domainAsString == "<global namespace>")
domainAsString = RootDomainMarker;
return domainAsString;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/DomainSpecification.cs
================================================
using System;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Represents a domain or a domain pattern. Immutable.
/// </summary>
[Serializable]
public abstract class DomainSpecification
{
public const char DomainPartSeparator = '.';
/// <summary>
/// The domain specification stored as a string.
/// </summary>
protected readonly string Value;
/// <summary>
/// Initializes a new instance. Also validates the input format if needed.
/// </summary>
/// <param name="value">The string representation of the domain specification.</param>
/// <param name="validate">True means validate the input string.</param>
/// <param name="validator">A delegate that validates the input string.</param>
protected DomainSpecification(string value, bool validate, Func<string, bool> validator)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (validate &&
validator != null &&
!validator.Invoke(value))
throw new FormatException($"'{value}' is not a valid {GetType().Name}.");
Value = value;
}
/// <summary>
/// Returns a number indicating how well this domain specification matches a concrete domain.
/// </summary>
/// <param name="domain">A domain.</param>
/// <returns>Zero means no match. Higher value means more relevant match.</returns>
public abstract int GetMatchRelevance(Domain domain);
/// <summary>
/// Returns a value indicating whether this domain specification matches a given domain.
/// </summary>
/// <param name="domain">A domain.</param>
/// <returns>True if this domain specification matches the given domain.</returns>
public bool Matches(Domain domain) => GetMatchRelevance(domain) > 0;
public override string ToString() => Value;
public bool Equals(DomainSpecification other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return String.Equals(Value, other.Value);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((DomainSpecification)obj);
}
public override int GetHashCode()
{
return (Value != null ? Value.GetHashCode() : 0);
}
public static bool operator ==(DomainSpecification left, DomainSpecification right)
{
return Equals(left, right);
}
public static bool operator !=(DomainSpecification left, DomainSpecification right)
{
return !Equals(left, right);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/DomainSpecificationParser.cs
================================================
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Converts a string to a domain specification.
/// </summary>
public static class DomainSpecificationParser
{
/// <summary>
/// Creates a domain specification from a string representation.
/// </summary>
/// <param name="domainSpecificationAsString">A domain specification in string format.</param>
/// <returns>The domain specification created from the given string.</returns>
/// <remarks>
/// Throws an exception if the string cannot be parsed.
/// </remarks>
public static DomainSpecification Parse(string domainSpecificationAsString)
{
if (domainSpecificationAsString.StartsWith(RegexDomain.Delimiter) && domainSpecificationAsString.EndsWith(RegexDomain.Delimiter))
return new RegexDomain(domainSpecificationAsString);
if (domainSpecificationAsString.Contains(WildcardDomain.SingleDomainMarker) || domainSpecificationAsString.Contains(WildcardDomain.AnyDomainMarker))
return new WildcardDomain(domainSpecificationAsString);
return new Domain(domainSpecificationAsString);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Factory/ConfigProviderFactory.cs
================================================
using Codartis.NsDepCop.Config.Implementation;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Factory
{
/// <summary>
/// Creates config provider objects.
/// </summary>
public class ConfigProviderFactory : IConfigProviderFactory
{
private readonly MessageHandler _traceMessageHandler;
public ConfigProviderFactory(MessageHandler traceMessageHandler)
{
_traceMessageHandler = traceMessageHandler;
}
public IUpdateableConfigProvider CreateFromXmlConfigFile(string configFilePath)
{
return new XmlFileConfigProvider(configFilePath, _traceMessageHandler);
}
public IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(string folderPath)
{
return new MultiLevelXmlFileConfigProvider(folderPath, _traceMessageHandler);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/IAnalyzerConfig.cs
================================================
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// The configuration for an analyzer.
/// </summary>
public interface IAnalyzerConfig : IDependencyRules, IDiagnosticSupport
{
/// <summary>
/// Gets a value indicating whether analysis is enabled.
/// </summary>
bool IsEnabled { get; }
/// <summary>
/// Gets the max number of issues reported.
/// </summary>
int MaxIssueCount { get; }
/// <summary>
/// Gets a value indicating whether MaxIssueCount is automatically updated whenever a lower count is achieved.
/// </summary>
bool AutoLowerMaxIssueCount { get; }
/// <summary>
/// Gets an array of file path exclusions patterns. Source files that match any of these patterns won't be analyzed.
/// </summary>
/// <remarks>
/// Uses https://github.com/dazinator/DotNet.Glob patterns.
/// </remarks>
string[] SourcePathExclusionPatterns { get; }
/// <summary>
/// Gets a value indicating whether the assembly dependencies check should be performed.
/// </summary>
bool CheckAssemblyDependencies { get; }
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/IConfigProvider.cs
================================================
using System;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Provides config info and config state from some kind of repository.
/// </summary>
public interface IConfigProvider
{
/// <summary>
/// Gets the config used by the analyzers.
/// </summary>
IAnalyzerConfig Config { get; }
/// <summary>
/// Gets the state of the analyzer's config.
/// </summary>
AnalyzerConfigState ConfigState { get; }
/// <summary>
/// Gets the config exception or null if there was no exception.
/// </summary>
Exception ConfigException { get; }
/// <summary>
/// Gets the config location as a string.
/// </summary>
string ConfigLocation { get; }
/// <summary>
/// Reloads the config from its repository.
/// </summary>
void RefreshConfig();
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/IConfigProviderFactory.cs
================================================
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Creates config provider objects.
/// </summary>
public interface IConfigProviderFactory
{
/// <summary>
/// Creates a config provider for an xml config file.
/// </summary>
/// <param name="configFilePath">The full path of an xml config file.</param>
/// <returns>A config provider.</returns>
IUpdateableConfigProvider CreateFromXmlConfigFile(string configFilePath);
/// <summary>
/// Creates a multi level config provider for the xml config files found in the specified folder and its parents.
/// </summary>
/// <param name="folderPath">The full path of the folder where the search for config files begins.</param>
/// <returns>A config provider.</returns>
IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(string folderPath);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/IDependencyRules.cs
================================================
using System.Collections.Generic;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Describes dependency rules.
/// </summary>
public interface IDependencyRules
{
/// <summary>
/// True means that all child namespaces can depend on any of their parent namespaces without an explicit Allowed rule.
/// True is in line with how C# type resolution works: it searches parent namespaces without an explicit using statement.
/// False means that all dependencies must be explicitly allowed with a rule.
/// False is the default for backward compatibility.
/// </summary>
bool ChildCanDependOnParentImplicitly { get; }
bool ParentCanDependOnChildImplicitly { get; }
/// <summary>
/// Dictionary of allowed dependency rules. The key is a namespace dependency rule,
/// the value is a set of type names defined in the target namespace and visible for the source namespace(s).
/// </summary>
Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }
/// <summary>
/// The set of disallowed dependency rules.
/// </summary>
HashSet<DependencyRule> DisallowRules { get; }
/// <summary>
/// Dictionary of visible types by target namespace. The key is the name of a namespace,
/// the value is a set of type names defined in the namespace and visible outside of the namespace.
/// </summary>
Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }
HashSet<DependencyRule> AllowedAssemblyRules { get; }
HashSet<DependencyRule> DisallowedAssemblyRules { get; }
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/IUpdateableConfigProvider.cs
================================================
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Provides config info and config state. Some config data can also be updated.
/// </summary>
public interface IUpdateableConfigProvider: IConfigProvider
{
/// <summary>
/// Updates the MaxIssueCount config parameter to the given value and persists the changes.
/// </summary>
/// <param name="newValue">The new value for MaxIssueCount.</param>
void UpdateMaxIssueCount(int newValue);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfig.cs
================================================
using System;
using System.Collections.Generic;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Describes the config for a dependency analyzer. Immutable.
/// </summary>
[Serializable]
internal class AnalyzerConfig : IAnalyzerConfig
{
public bool IsEnabled { get; }
public string[] SourcePathExclusionPatterns { get; }
public bool CheckAssemblyDependencies { get; }
public bool ChildCanDependOnParentImplicitly { get; }
public bool ParentCanDependOnChildImplicitly { get; }
public Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }
public HashSet<DependencyRule> DisallowRules { get; }
public Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }
public HashSet<DependencyRule> AllowedAssemblyRules { get; }
public HashSet<DependencyRule> DisallowedAssemblyRules { get; }
public int MaxIssueCount { get; }
public bool AutoLowerMaxIssueCount { get; }
public AnalyzerConfig(
bool isEnabled,
string[] sourcePathExclusionPatterns,
bool checkAssemblyDependencies,
bool childCanDependOnParentImplicitly,
bool parentCanDependOnChildImplicitly,
Dictionary<DependencyRule, TypeNameSet> allowRules,
HashSet<DependencyRule> disallowRules,
Dictionary<Domain, TypeNameSet> visibleTypesByNamespace,
HashSet<DependencyRule> allowedAssemblyRules,
HashSet<DependencyRule> disallowedAssemblyRules,
int maxIssueCount,
bool autoLowerMaxIssueCount)
{
IsEnabled = isEnabled;
SourcePathExclusionPatterns = sourcePathExclusionPatterns;
CheckAssemblyDependencies = checkAssemblyDependencies;
ChildCanDependOnParentImplicitly = childCanDependOnParentImplicitly;
ParentCanDependOnChildImplicitly = parentCanDependOnChildImplicitly;
AllowRules = allowRules;
DisallowRules = disallowRules;
VisibleTypesByNamespace = visibleTypesByNamespace;
AllowedAssemblyRules = allowedAssemblyRules;
DisallowedAssemblyRules = disallowedAssemblyRules;
MaxIssueCount = maxIssueCount;
AutoLowerMaxIssueCount = autoLowerMaxIssueCount;
}
public IEnumerable<string> ToStrings()
{
yield return $"IsEnabled={IsEnabled}";
yield return $"SourcePathExclusionPatterns={string.Join(",", SourcePathExclusionPatterns)}";
yield return $"ChildCanDependOnParentImplicitly={ChildCanDependOnParentImplicitly}";
foreach (var s in AllowRules.ToStrings()) yield return s;
foreach (var s in DisallowRules.ToStrings()) yield return s;
foreach (var s in AllowedAssemblyRules.ToStrings()) yield return s;
foreach (var s in DisallowedAssemblyRules.ToStrings()) yield return s;
foreach (var s in VisibleTypesByNamespace.ToStrings()) yield return s;
yield return $"MaxIssueCount={MaxIssueCount}";
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfigBuilder.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Builds analyzer config objects.
/// </summary>
public class AnalyzerConfigBuilder
{
public int? InheritanceDepth { get; private set; }
public bool? IsEnabled { get; private set; }
public List<string> SourcePathExclusionPatterns { get; private set; }
public bool? CheckAssemblyDependencies { get; private set; }
public bool? ChildCanDependOnParentImplicitly { get; private set; }
public bool? ParentCanDependOnChildImplicitly { get; private set; }
public Dictionary<DependencyRule, TypeNameSet> AllowRules { get; }
public HashSet<DependencyRule> DisallowRules { get; }
public Dictionary<Domain, TypeNameSet> VisibleTypesByNamespace { get; }
public HashSet<DependencyRule> AllowedAssemblyRules { get; }
public HashSet<DependencyRule> DisallowedAssemblyRules { get; }
public int? MaxIssueCount { get; private set; }
public bool? AutoLowerMaxIssueCount { get; private set; }
public AnalyzerConfigBuilder()
{
SourcePathExclusionPatterns = new List<string>();
AllowRules = new Dictionary<DependencyRule, TypeNameSet>();
DisallowRules = new HashSet<DependencyRule>();
VisibleTypesByNamespace = new Dictionary<Domain, TypeNameSet>();
AllowedAssemblyRules = new HashSet<DependencyRule>();
DisallowedAssemblyRules = new HashSet<DependencyRule>();
}
public IAnalyzerConfig ToAnalyzerConfig()
{
return new AnalyzerConfig(
IsEnabled ?? ConfigDefaults.IsEnabled,
SourcePathExclusionPatterns.ToArray(),
CheckAssemblyDependencies ?? ConfigDefaults.CheckAssemblyDependencies,
ChildCanDependOnParentImplicitly ?? ConfigDefaults.ChildCanDependOnParentImplicitly,
ParentCanDependOnChildImplicitly ?? ConfigDefaults.ParentCanDependOnChildImplicitly,
AllowRules,
DisallowRules,
VisibleTypesByNamespace,
AllowedAssemblyRules,
DisallowedAssemblyRules,
MaxIssueCount ?? ConfigDefaults.MaxIssueCount,
AutoLowerMaxIssueCount ?? ConfigDefaults.AutoLowerMaxIssueCount
);
}
public AnalyzerConfigBuilder Combine(AnalyzerConfigBuilder analyzerConfigBuilder)
{
// Note that InheritanceDepth is not combined.
SetIsEnabled(analyzerConfigBuilder.IsEnabled);
AddSourcePathExclusionPatterns(analyzerConfigBuilder.SourcePathExclusionPatterns);
SetCheckAssemblyDependencies(analyzerConfigBuilder.CheckAssemblyDependencies);
SetChildCanDependOnParentImplicitly(analyzerConfigBuilder.ChildCanDependOnParentImplicitly);
SetParentCanDependOnChildImplicitly(analyzerConfigBuilder.ParentCanDependOnChildImplicitly);
AddAllowRules(analyzerConfigBuilder.AllowRules);
AddDisallowRules(analyzerConfigBuilder.DisallowRules);
AddVisibleTypesByNamespace(analyzerConfigBuilder.VisibleTypesByNamespace);
AddAllowedAssemblyRules(analyzerConfigBuilder.AllowedAssemblyRules);
AddDisallowedAssemblyRules(analyzerConfigBuilder.DisallowedAssemblyRules);
SetMaxIssueCount(analyzerConfigBuilder.MaxIssueCount);
SetAutoLowerMaxIssueCount(analyzerConfigBuilder.AutoLowerMaxIssueCount);
return this;
}
public AnalyzerConfigBuilder SetInheritanceDepth(int? inheritanceDepth)
{
if (inheritanceDepth.HasValue)
InheritanceDepth = inheritanceDepth;
return this;
}
public AnalyzerConfigBuilder SetIsEnabled(bool? isEnabled)
{
if (isEnabled.HasValue)
IsEnabled = isEnabled;
return this;
}
public AnalyzerConfigBuilder AddSourcePathExclusionPatterns(IEnumerable<string> sourcePathExclusionPatterns)
{
if (sourcePathExclusionPatterns != null)
SourcePathExclusionPatterns.AddRange(sourcePathExclusionPatterns);
return this;
}
public AnalyzerConfigBuilder SetCheckAssemblyDependencies(bool? checkAssemblyDependencies)
{
if (checkAssemblyDependencies.HasValue)
CheckAssemblyDependencies = checkAssemblyDependencies;
return this;
}
public AnalyzerConfigBuilder MakePathsRooted(string rootPath)
{
if (!Path.IsPathRooted(rootPath))
throw new ArgumentException($"Rooted path expected: {rootPath}");
SourcePathExclusionPatterns = SourcePathExclusionPatterns.Select(i => ToRootedPath(rootPath, i)).ToList();
return this;
}
public AnalyzerConfigBuilder SetChildCanDependOnParentImplicitly(bool? childCanDependOnParentImplicitly)
{
if (childCanDependOnParentImplicitly.HasValue)
ChildCanDependOnParentImplicitly = childCanDependOnParentImplicitly;
return this;
}
public AnalyzerConfigBuilder SetParentCanDependOnChildImplicitly(bool? parentCanDependOnChildImplicitly)
{
if (parentCanDependOnChildImplicitly.HasValue)
ParentCanDependOnChildImplicitly = parentCanDependOnChildImplicitly;
return this;
}
public AnalyzerConfigBuilder AddAllowRule(DependencyRule dependencyRule, TypeNameSet typeNameSet = null)
{
AllowRules.AddOrUnion<DependencyRule, TypeNameSet, string>(dependencyRule, typeNameSet);
return this;
}
private AnalyzerConfigBuilder AddAllowRules(IEnumerable<KeyValuePair<DependencyRule, TypeNameSet>> allowRules)
{
foreach (var keyValuePair in allowRules)
AddAllowRule(keyValuePair.Key, keyValuePair.Value);
return this;
}
public AnalyzerConfigBuilder AddDisallowRule(DependencyRule dependencyRule)
{
DisallowRules.Add(dependencyRule);
return this;
}
private AnalyzerConfigBuilder AddDisallowRules(IEnumerable<DependencyRule> disallowRules)
{
foreach (var dependencyRule in disallowRules)
AddDisallowRule(dependencyRule);
return this;
}
public AnalyzerConfigBuilder AddAllowedAssemblyRule(DependencyRule assemblyDependencyRule)
{
AllowedAssemblyRules.Add(assemblyDependencyRule);
return this;
}
private AnalyzerConfigBuilder AddAllowedAssemblyRules(IEnumerable<DependencyRule> assemblyDependencyRules)
{
foreach (var assemblyDependencyRule in assemblyDependencyRules)
AddAllowedAssemblyRule(assemblyDependencyRule);
return this;
}
public AnalyzerConfigBuilder AddDisallowedAssemblyRule(DependencyRule assemblyDependencyRule)
{
DisallowedAssemblyRules.Add(assemblyDependencyRule);
return this;
}
private AnalyzerConfigBuilder AddDisallowedAssemblyRules(IEnumerable<DependencyRule> assemblyDependencyRules)
{
foreach (var assemblyDependencyRule in assemblyDependencyRules)
AddDisallowedAssemblyRule(assemblyDependencyRule);
return this;
}
public AnalyzerConfigBuilder AddVisibleTypesByNamespace(Domain domain, TypeNameSet typeNameSet)
{
VisibleTypesByNamespace.AddOrUnion<Domain, TypeNameSet, string>(domain, typeNameSet);
return this;
}
private AnalyzerConfigBuilder AddVisibleTypesByNamespace(IEnumerable<KeyValuePair<Domain, TypeNameSet>> visibleTypesByNamespace)
{
foreach (var keyValuePair in visibleTypesByNamespace)
AddVisibleTypesByNamespace(keyValuePair.Key, keyValuePair.Value);
return this;
}
public AnalyzerConfigBuilder SetMaxIssueCount(int? maxIssueCount)
{
if (maxIssueCount.HasValue)
MaxIssueCount = maxIssueCount;
return this;
}
public AnalyzerConfigBuilder SetAutoLowerMaxIssueCount(bool? autoLowerMaxIssueCount)
{
if (autoLowerMaxIssueCount.HasValue)
AutoLowerMaxIssueCount = autoLowerMaxIssueCount;
return this;
}
public IEnumerable<string> ToStrings()
{
if (InheritanceDepth.HasValue) yield return $"InheritanceDepth={InheritanceDepth}";
if (IsEnabled.HasValue) yield return $"IsEnabled={IsEnabled}";
if (SourcePathExclusionPatterns != null) yield return $"SourcePathExclusionPatterns={string.Join(";", SourcePathExclusionPatterns)}";
if (CheckAssemblyDependencies.HasValue) yield return $"CheckAssemblyDependencies={CheckAssemblyDependencies}";
if (ChildCanDependOnParentImplicitly.HasValue) yield return $"ChildCanDependOnParentImplicitly={ChildCanDependOnParentImplicitly}";
if (ParentCanDependOnChildImplicitly.HasValue) yield return $"ParentCanDependOnChildImplicitly={ParentCanDependOnChildImplicitly}";
if (AllowRules.Any())
foreach (var s in AllowRules.ToStrings())
yield return s;
if (DisallowRules.Any())
foreach (var s in DisallowRules.ToStrings())
yield return s;
if (AllowedAssemblyRules.Any())
foreach (var s in AllowedAssemblyRules.ToStrings())
yield return s;
if (DisallowedAssemblyRules.Any())
foreach (var s in DisallowedAssemblyRules.ToStrings())
yield return s;
if (VisibleTypesByNamespace.Any())
foreach (var s in VisibleTypesByNamespace.ToStrings())
yield return s;
if (MaxIssueCount.HasValue) yield return $"MaxIssueCount={MaxIssueCount}";
}
private static string ToRootedPath(string rootPath, string path)
{
if (rootPath == null || Path.IsPathRooted(path))
return path;
return Path.Combine(rootPath, path);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/ConfigLoadResult.cs
================================================
using System;
using System.Collections.Generic;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Describes the result of a config load operation.
/// </summary>
public readonly struct ConfigLoadResult
{
public AnalyzerConfigState ConfigState { get; }
public AnalyzerConfigBuilder ConfigBuilder { get; }
public IAnalyzerConfig Config { get; }
public Exception ConfigException { get; }
private ConfigLoadResult(AnalyzerConfigState configState, AnalyzerConfigBuilder configBuilder,
IAnalyzerConfig config, Exception configException)
{
ConfigState = configState;
ConfigBuilder = configBuilder;
Config = config;
ConfigException = configException;
}
public static ConfigLoadResult CreateWithError(Exception configException)
{
if (configException == null)
throw new ArgumentNullException(nameof(configException));
return new ConfigLoadResult(AnalyzerConfigState.ConfigError, null, null, configException);
}
public static ConfigLoadResult CreateWithNoConfig()
{
return new ConfigLoadResult(AnalyzerConfigState.NoConfig, null, null, null);
}
public static ConfigLoadResult CreateWithConfig(AnalyzerConfigBuilder configBuilder)
{
if (configBuilder == null)
throw new ArgumentNullException(nameof(configBuilder));
var config = configBuilder.ToAnalyzerConfig();
return config.IsEnabled
? new ConfigLoadResult(AnalyzerConfigState.Enabled, configBuilder, config, null)
: new ConfigLoadResult(AnalyzerConfigState.Disabled, null, null, null);
}
public IEnumerable<string> ToStrings()
{
yield return $"ConfigState={ConfigState}";
if (ConfigException != null) yield return $"ConfigException={ConfigException}";
if (Config != null) foreach (var s in Config.ToStrings()) yield return s;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/ConfigProviderBase.cs
================================================
using System;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Abstract base class for config provider implementations.
/// </summary>
/// <remarks>
/// Uses locking to ensure that no property can be read while refreshing the config.
/// </remarks>
public abstract class ConfigProviderBase : IUpdateableConfigProvider
{
private bool _isInitialized;
private ConfigLoadResult _configLoadResult;
/// <summary>
/// This lock ensures that no property can be read while loading or saving the config.
/// </summary>
protected readonly object SaveLoadLockObject = new();
protected MessageHandler TraceMessageHandler { get; }
protected ConfigProviderBase(MessageHandler traceMessageHandler)
{
TraceMessageHandler = traceMessageHandler;
}
public abstract string ConfigLocation { get; }
public IAnalyzerConfig Config
{
get
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
return _configLoadResult.Config;
}
}
}
public AnalyzerConfigBuilder ConfigBuilder
{
get
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
return _configLoadResult.ConfigBuilder;
}
}
}
public AnalyzerConfigState ConfigState
{
get
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
return _configLoadResult.ConfigState;
}
}
}
public Exception ConfigException
{
get
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
return _configLoadResult.ConfigException;
}
}
}
public void RefreshConfig()
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
_configLoadResult = RefreshConfigCore();
}
}
public void UpdateMaxIssueCount(int newValue)
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
if (_configLoadResult.ConfigState != AnalyzerConfigState.Enabled)
throw new InvalidOperationException($"Cannot {nameof(UpdateMaxIssueCount)} in {_configLoadResult.ConfigState} state.");
_configLoadResult = UpdateMaxIssueCountCore(newValue);
}
}
protected abstract ConfigLoadResult LoadConfigCore();
protected abstract ConfigLoadResult RefreshConfigCore();
protected abstract ConfigLoadResult UpdateMaxIssueCountCore(int newValue);
protected void EnsureInitialized()
{
lock (SaveLoadLockObject)
{
if (_isInitialized)
return;
_isInitialized = true;
_configLoadResult = LoadConfigCore();
}
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/FileConfigProviderBase.cs
================================================
using System;
using System.IO;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Abstract base class for file based config implementations.
/// Reloads only if the file changed.
/// </summary>
/// <remarks>
/// Base class ensures that all operations are executed in an atomic way so no extra locking needed.
/// </remarks>
public abstract class FileConfigProviderBase : ConfigProviderBase
{
private bool _configFileExists;
private DateTime _configLastLoadUtc;
private ConfigLoadResult _lastConfigLoadResult;
protected string ConfigFilePath { get; }
protected FileConfigProviderBase(string configFilePath, MessageHandler traceMessageHandler)
: base(traceMessageHandler)
{
ConfigFilePath = configFilePath;
}
public override string ConfigLocation => ConfigFilePath;
public int InheritanceDepth => ConfigBuilder?.InheritanceDepth ?? ConfigDefaults.InheritanceDepth;
public bool HasConfigFileChanged()
{
return ConfigFileCreatedOrDeleted()
|| ConfigFileModifiedSinceLastLoad();
}
protected override ConfigLoadResult LoadConfigCore()
{
_lastConfigLoadResult = LoadConfigFromFile();
return _lastConfigLoadResult;
}
protected override ConfigLoadResult RefreshConfigCore()
{
if (!HasConfigFileChanged())
return _lastConfigLoadResult;
LogTraceMessage($"Refreshing config {this}.");
return LoadConfigCore();
}
private ConfigLoadResult LoadConfigFromFile()
{
try
{
_configFileExists = File.Exists(ConfigFilePath);
if (!_configFileExists)
return ConfigLoadResult.CreateWithNoConfig();
_configLastLoadUtc = DateTime.UtcNow;
var configBuilder = CreateConfigBuilderFromFile(ConfigFilePath)
.MakePathsRooted(Path.GetDirectoryName(ConfigFilePath));
return ConfigLoadResult.CreateWithConfig(configBuilder);
}
catch (Exception e)
{
LogTraceMessage($"BuildConfig exception: {e}");
return ConfigLoadResult.CreateWithError(e);
}
}
protected abstract AnalyzerConfigBuilder CreateConfigBuilderFromFile(string configFilePath);
private bool ConfigFileCreatedOrDeleted()
{
return _configFileExists != File.Exists(ConfigFilePath);
}
private bool ConfigFileModifiedSinceLastLoad()
{
return File.Exists(ConfigFilePath)
&& _configLastLoadUtc < File.GetLastWriteTimeUtc(ConfigFilePath);
}
private void LogTraceMessage(string message) => TraceMessageHandler?.Invoke(message);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/MultiLevelXmlFileConfigProvider.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Traverses the source tree and reads one or multiple config files to create a composite config.
/// Starts from the specified folder and traverses the folder tree upwards till the root or the max inheritance level is reached.
/// </summary>
/// <remarks>
/// Base class ensures that all operations are executed in an atomic way so no extra locking needed.
/// </remarks>
public sealed class MultiLevelXmlFileConfigProvider : ConfigProviderBase
{
private ConfigLoadResult _lastConfigLoadResult;
private int _lastInheritanceDepth;
/// <summary>
/// The collection of all file config providers that must be composed to a single config.
/// </summary>
/// <remarks>
/// The list is sorted from the project folder's config to increasingly farther configs in the folder tree.
/// The configs must be combined in reverse order (from the farthest to the closest).
/// </remarks>
private List<XmlFileConfigProvider> _fileConfigProviders;
private string ProjectFolder { get; }
public MultiLevelXmlFileConfigProvider(string projectFolder, MessageHandler traceMessageHandler)
: base(traceMessageHandler)
{
ProjectFolder = projectFolder;
}
public override string ConfigLocation => ProjectFolder;
public int InheritanceDepth
{
get
{
lock (SaveLoadLockObject)
{
EnsureInitialized();
return _fileConfigProviders.First().InheritanceDepth;
}
}
}
public override string ToString() => $"MultiLevelXmlConfig:'{ProjectFolder}'";
protected override ConfigLoadResult LoadConfigCore()
{
LogTraceMessage($"Loading config {this}");
var projectLevelConfigProvider = new XmlFileConfigProvider(GetConfigFilePath(ProjectFolder), TraceMessageHandler);
_fileConfigProviders = CreateFileConfigProviderList(projectLevelConfigProvider, ProjectFolder);
return CombineFileConfigProvidersAndSaveResult();
}
protected override ConfigLoadResult RefreshConfigCore()
{
if (!AnyChildConfigChanged())
return _lastConfigLoadResult;
LogTraceMessage($"Refreshing config {this}.");
var projectLevelConfigProvider = _fileConfigProviders[0];
projectLevelConfigProvider.RefreshConfig();
if (InheritanceDepth != _lastInheritanceDepth)
{
_fileConfigProviders = CreateFileConfigProviderList(projectLevelConfigProvider, ProjectFolder);
}
else
{
foreach (var configProvider in _fileConfigProviders.Skip(1))
configProvider.RefreshConfig();
}
return CombineFileConfigProvidersAndSaveResult();
}
protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)
{
_fileConfigProviders.First().UpdateMaxIssueCount(newValue);
return CombineFileConfigProvidersAndSaveResult();
}
private ConfigLoadResult CombineFileConfigProvidersAndSaveResult()
{
_lastInheritanceDepth = InheritanceDepth;
_lastConfigLoadResult = CombineFileConfigProviders();
LogTraceMessage(IndentHelper.Indent("Effective config:", 1).Concat(IndentHelper.Indent(_lastConfigLoadResult.ToStrings(), 2)));
return _lastConfigLoadResult;
}
private ConfigLoadResult CombineFileConfigProviders()
{
var configBuilder = CreateAnalyzerConfigBuilder();
var anyConfigFound = false;
foreach (var childConfigProvider in Enumerable.Reverse(_fileConfigProviders))
{
var childConfigState = childConfigProvider.ConfigState;
LogTraceMessage(IndentHelper.Indent($"Combining {childConfigProvider}, state={childConfigState}", 1));
switch (childConfigState)
{
case AnalyzerConfigState.NoConfig:
break;
case AnalyzerConfigState.Disabled:
anyConfigFound = true;
configBuilder.SetIsEnabled(false);
break;
case AnalyzerConfigState.Enabled:
anyConfigFound = true;
var childConfigBuilder = childConfigProvider.ConfigBuilder;
configBuilder.Combine(childConfigBuilder);
LogTraceMessage(IndentHelper.Indent(childConfigBuilder.ToStrings(), 2));
break;
case AnalyzerConfigState.ConfigError:
return ConfigLoadResult.CreateWithError(childConfigProvider.ConfigException);
default:
throw new ArgumentOutOfRangeException(nameof(childConfigState), childConfigState, "Unexpected value.");
}
}
return anyConfigFound
? ConfigLoadResult.CreateWithConfig(configBuilder)
: ConfigLoadResult.CreateWithNoConfig();
}
private static AnalyzerConfigBuilder CreateAnalyzerConfigBuilder() => new();
private bool AnyChildConfigChanged() => _fileConfigProviders.Any(i => i.HasConfigFileChanged());
private List<XmlFileConfigProvider> CreateFileConfigProviderList(XmlFileConfigProvider firstConfigProvider, string startFolderPath)
{
var fileConfigProviders = new List<XmlFileConfigProvider> { firstConfigProvider };
LogTraceMessage(IndentHelper.Indent($"InheritanceDepth={firstConfigProvider.InheritanceDepth}", 1));
var currentFolder = startFolderPath;
for (var i = 0; i < firstConfigProvider.InheritanceDepth; i++)
{
currentFolder = Directory.GetParent(currentFolder)?.FullName;
if (string.IsNullOrWhiteSpace(currentFolder))
break;
var higherLevelConfigProvider = new XmlFileConfigProvider(GetConfigFilePath(currentFolder), TraceMessageHandler);
fileConfigProviders.Add(higherLevelConfigProvider);
}
return fileConfigProviders;
}
private static string GetConfigFilePath(string folderPath) => Path.Combine(folderPath, ProductConstants.DefaultConfigFileName);
private void LogTraceMessage(IEnumerable<string> messages)
{
foreach (var message in messages)
LogTraceMessage(message);
}
private void LogTraceMessage(string message) => TraceMessageHandler?.Invoke(message);
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/RuleConfigToStringsFormatter.cs
================================================
using System.Collections.Generic;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Static helper class for formatting rule config data into strings.
/// </summary>
public static class RuleConfigToStringsFormatter
{
public static IEnumerable<string> ToStrings(this IDictionary<DependencyRule, TypeNameSet> allowRules)
{
yield return $"AllowRules={allowRules.Count}";
foreach (var allowRule in allowRules)
yield return $" {allowRule.Key}, {allowRule.Value?.ToString() ?? "{}"}";
}
public static IEnumerable<string> ToStrings(this ISet<DependencyRule> disallowRules)
{
yield return $"DisallowRules={disallowRules.Count}";
foreach (var disallowRule in disallowRules)
yield return $" {disallowRule}";
}
public static IEnumerable<string> ToStrings(this IDictionary<Domain, TypeNameSet> visibleTypesByNamespaces)
{
yield return $"VisibleTypesByNamespace={visibleTypesByNamespaces.Count}";
foreach (var visibleTypesByNamespace in visibleTypesByNamespaces)
yield return $" {visibleTypesByNamespace.Key}, {visibleTypesByNamespace.Value?.ToString() ?? "{}"}";
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/XmlConfigParser.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Parses a config provided in XML format.
/// </summary>
public static class XmlConfigParser
{
private const string RootElementName = "NsDepCopConfig";
private const string InheritanceDepthAttributeName = "InheritanceDepth";
private const string IsEnabledAttributeName = "IsEnabled";
private const string MaxIssueCountAttributeName = "MaxIssueCount";
private const string AutoLowerMaxIssueCountAttributeName = "AutoLowerMaxIssueCount";
private const string ImplicitParentDependencyAttributeName = "ChildCanDependOnParentImplicitly";
private const string ImplicitChildDependencyAttributeName = "ParentCanDependOnChildImplicitly";
private const string SourcePathExclusionPatternsAttributeName = "ExcludedFiles";
private const string CheckAssemblyDependenciesAttributeName = "CheckAssemblyDependencies";
private const string AllowedElementName = "Allowed";
private const string DisallowedElementName = "Disallowed";
private const string AllowedAssemblyElementName = "AllowedAssembly";
private const string DisallowedAssemblyElementName = "DisallowedAssembly";
private const string VisibleMembersElementName = "VisibleMembers";
private const string TypeElementName = "Type";
private const string OfNamespaceAttributeName = "OfNamespace";
private const string FromAttributeName = "From";
private const string ToAttributeName = "To";
private const string TypeNameAttributeName = "Name";
public static AnalyzerConfigBuilder Parse(XDocument configXml)
{
var configBuilder = new AnalyzerConfigBuilder();
var rootElement = GetRootElement(configXml);
ParseRootNodeAttributes(rootElement, configBuilder);
ParseChildElements(rootElement, configBuilder);
return configBuilder;
}
public static void UpdateMaxIssueCount(XDocument configXml, int newValue)
{
var rootElement = GetRootElement(configXml);
AddOrUpdateAttribute(rootElement, MaxIssueCountAttributeName, newValue.ToString());
}
private static XElement GetRootElement(XDocument configXml)
{
var rootElement = configXml.Element(RootElementName);
if (rootElement == null)
throw new Exception($"'{RootElementName}' root element not found.");
return rootElement;
}
private static void ParseRootNodeAttributes(XElement rootElement, AnalyzerConfigBuilder configBuilder)
{
configBuilder.SetIsEnabled(ParseValueType<bool>(rootElement, IsEnabledAttributeName, bool.TryParse));
configBuilder.SetInheritanceDepth(ParseValueType<int>(rootElement, InheritanceDepthAttributeName, int.TryParse));
configBuilder.AddSourcePathExclusionPatterns(ParseStringList(rootElement, SourcePathExclusionPatternsAttributeName, ','));
configBuilder.SetCheckAssemblyDependencies(ParseValueType<bool>(rootElement, CheckAssemblyDependenciesAttributeName, bool.TryParse));
configBuilder.SetChildCanDependOnParentImplicitly(ParseValueType<bool>(rootElement, ImplicitParentDependencyAttributeName, bool.TryParse));
configBuilder.SetParentCanDependOnChildImplicitly(ParseValueType<bool>(rootElement, ImplicitChildDependencyAttributeName, bool.TryParse));
configBuilder.SetMaxIssueCount(ParseValueType<int>(rootElement, MaxIssueCountAttributeName, int.TryParse));
configBuilder.SetAutoLowerMaxIssueCount(ParseValueType<bool>(rootElement, AutoLowerMaxIssueCountAttributeName, bool.TryParse));
}
private static IEnumerable<string> ParseStringList(XElement element, string attributeName, char separatorChar)
{
var attribute = element.Attribute(attributeName);
var parts = Split(attribute?.Value, separatorChar);
return parts?.ToList();
}
private static IEnumerable<string> Split(string s, char separatorChar)
{
return s?.Split(new[] { separatorChar }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim());
}
private static void ParseChildElements(XElement rootElement, AnalyzerConfigBuilder configBuilder)
{
foreach (var xElement in rootElement.Elements())
{
switch (xElement.Name.ToString())
{
case AllowedElementName:
ParseAllowedElement(xElement, configBuilder);
break;
case DisallowedElementName:
ParseDisallowedElement(xElement, configBuilder);
break;
case AllowedAssemblyElementName:
ParseAllowedAssemblyElement(xElement, configBuilder);
break;
case DisallowedAssemblyElementName:
ParseDisallowedAssemblyElement(xElement, configBuilder);
break;
case VisibleMembersElementName:
ParseVisibleMembersElement(xElement, configBuilder);
break;
default:
Trace.WriteLine($"Unexpected element '{xElement.Name}' ignored.");
break;
}
}
}
private static void ParseAllowedElement(XElement element, AnalyzerConfigBuilder configBuilder)
{
var allowedDependencyRule = ParseDependencyRule(element);
var visibleTypeNames = ParseVisibleMembersInsideAllowedRule(element, allowedDependencyRule);
if (visibleTypeNames.IsNullOrEmpty())
visibleTypeNames = null;
configBuilder.AddAllowRule(allowedDependencyRule, visibleTypeNames);
}
private static void ParseDisallowedElement(XElement element, AnalyzerConfigBuilder configBuilder)
{
var disallowedDependencyRule = ParseDependencyRule(element);
configBuilder.AddDisallowRule(disallowedDependencyRule);
}
private static void ParseAllowedAssemblyElement(XElement element, AnalyzerConfigBuilder configBuilder)
{
var allowedAssemblyDependencyRule = ParseAssemblyDependencyRule(element);
configBuilder.AddAllowedAssemblyRule(allowedAssemblyDependencyRule);
}
private static void ParseDisallowedAssemblyElement(XElement element, AnalyzerConfigBuilder configBuilder)
{
var disallowedAssemblyDependencyRule = ParseAssemblyDependencyRule(element);
configBuilder.AddDisallowedAssemblyRule(disallowedAssemblyDependencyRule);
}
private static TypeNameSet ParseVisibleMembersInsideAllowedRule(XElement element, DependencyRule allowedRule)
{
var visibleMembersChild = element.Element(VisibleMembersElementName);
if (visibleMembersChild == null)
return null;
if (allowedRule.To is not Domain)
throw new Exception($"{GetLineInfo(element)}The target namespace '{allowedRule.To}' must be a single namespace.");
if (visibleMembersChild.Attribute(OfNamespaceAttributeName) != null)
throw new Exception(
$"{GetLineInfo(element)}If {VisibleMembersElementName} is embedded in a dependency specification then '{OfNamespaceAttributeName}' attribute must not be defined.");
return ParseTypeNameSet(visibleMembersChild, TypeElementName);
}
private static void ParseVisibleMembersElement(XElement element, AnalyzerConfigBuilder configBuilder)
{
var targetNamespaceName = GetAttributeValue(element, OfNamespaceAttributeName);
if (targetNamespaceName == null)
throw new Exception($"{GetLineInfo(element)}'{OfNamespaceAttributeName}' attribute missing.");
var targetNamespace = TryAndReportError(element, () => new Domain(targetNamespaceName.Trim()));
var visibleTypeNames = ParseTypeNameSet(element, TypeElementName);
if (!visibleTypeNames.Any())
return;
configBuilder.AddVisibleTypesByNamespace(targetNamespace, visibleTypeNames);
}
private static DependencyRule ParseDependencyRule(XElement element)
{
var fromValue = GetAttributeValue(element, FromAttributeName);
if (fromValue == null)
throw new Exception($"{GetLineInfo(element)}'{FromAttributeName}' attribute missing.");
var toValue = GetAttributeValue(element, ToAttributeName);
if (toValue == null)
throw new Exception($"{GetLineInfo(element)}'{ToAttributeName}' attribute missing.");
var from = TryAndReportError(element, () => DomainSpecificationParser.Parse(fromValue.Trim()));
var to = TryAndReportError(element, () => DomainSpecificationParser.Parse(toValue.Trim()));
return new DependencyRule(from, to);
}
private static DependencyRule ParseAssemblyDependencyRule(XElement element)
{
var fromValue = GetAttributeValue(element, FromAttributeName);
if (fromValue == null)
throw new Exception($"{GetLineInfo(element)}'{FromAttributeName}' attribute missing.");
var toValue = GetAttributeValue(element, ToAttributeName);
if (toValue == null)
throw new Exception($"{GetLineInfo(element)}'{ToAttributeName}' attribute missing.");
var from = TryAndReportError(element, () => DomainSpecificationParser.Parse(fromValue.Trim()));
var to = TryAndReportError(element, () => DomainSpecificationParser.Parse(toValue.Trim()));
return new DependencyRule(from, to);
}
private static T TryAndReportError<T>(XObject xObject, Func<T> parserDelegate)
{
try
{
return parserDelegate();
}
catch (Exception e)
{
throw new Exception($"{GetLineInfo(xObject)}{e.Message}", e);
}
}
private static TypeNameSet ParseTypeNameSet(XElement element, string childElementName)
{
var typeNameSet = new TypeNameSet();
foreach (var xElement in element.Elements(childElementName))
{
var typeName = GetAttributeValue(xElement, TypeNameAttributeName);
if (typeName == null)
throw new Exception($"{GetLineInfo(xElement)}'{TypeNameAttributeName}' attribute missing.");
if (!string.IsNullOrWhiteSpace(typeName))
typeNameSet.Add(typeName.Trim());
}
return typeNameSet;
}
/// <summary>
/// Returns an attribute's value, or null if the attribute was not found.
/// </summary>
/// <param name="element">The parent element of the attribute.</param>
/// <param name="attributeName">The name of the attribute.</param>
/// <returns>The value of the attribute or null if the attribute was not found.</returns>
private static string GetAttributeValue(XElement element, string attributeName)
{
return element.Attribute(attributeName)?.Value;
}
private static void AddOrUpdateAttribute(XElement element, string attributeName, string newValue)
{
var attribute = element.Attribute(attributeName);
if (attribute == null)
element.Add(new XAttribute(attributeName, newValue));
else
attribute.Value = newValue;
}
/// <summary>
/// Defines the signature of a TryParse-like method, that is used to parse a value of T from string.
/// </summary>
/// <typeparam name="T">The type of the parse result.</typeparam>
/// <param name="s">The string that must be parsed.</param>
/// <param name="t">The successfully parsed value.</param>
/// <returns>True if successfully parsed, false otherwise.</returns>
private delegate bool TryParseMethod<T>(string s, out T t);
private static T? ParseValueType<T>(XElement element, string attributeName, TryParseMethod<T> tryParseMethod)
where T : struct
{
var attribute = element.Attribute(attributeName);
if (attribute == null)
return null;
if (tryParseMethod(attribute.Value, out var parseResult))
return parseResult;
throw new FormatException($"{GetLineInfo(element)}Error parsing '{attribute.Name}' value '{attribute.Value}'.");
}
private static string GetLineInfo(XObject xObject)
{
var xmlLineInfo = xObject as IXmlLineInfo;
return xmlLineInfo.HasLineInfo()
? $"[Line: {xmlLineInfo.LineNumber}, Pos: {xmlLineInfo.LinePosition}] "
: string.Empty;
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/Implementation/XmlFileConfigProvider.cs
================================================
using System.Xml.Linq;
using Codartis.NsDepCop.Util;
namespace Codartis.NsDepCop.Config.Implementation
{
/// <summary>
/// Extracts config information from an xml config file.
/// </summary>
/// <remarks>
/// Base class handles config load errors so no need to catch exceptions here.
/// </remarks>
public sealed class XmlFileConfigProvider : FileConfigProviderBase
{
private XDocument _configXDocument;
public XmlFileConfigProvider(string configFilePath, MessageHandler traceMessageHandler)
: base(configFilePath, traceMessageHandler)
{
}
public override string ToString() => $"XmlConfig:'{ConfigFilePath}'";
protected override AnalyzerConfigBuilder CreateConfigBuilderFromFile(string configFilePath)
{
_configXDocument = XDocument.Load(configFilePath, LoadOptions.SetLineInfo);
return XmlConfigParser.Parse(_configXDocument);
}
protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)
{
XmlConfigParser.UpdateMaxIssueCount(_configXDocument, newValue);
_configXDocument.Save(ConfigFilePath);
return LoadConfigCore();
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/RegexCompilationMode.cs
================================================
namespace Codartis.NsDepCop.Config;
public enum RegexCompilationMode
{
Compiled,
Interpreted
}
================================================
FILE: source/NsDepCop.Analyzer/Config/RegexDomain.cs
================================================
using System;
using System.Text.RegularExpressions;
namespace Codartis.NsDepCop.Config;
/// <summary>
/// Represents a domain specification with a regular expression pattern.
/// The given pattern must follow the dotnet regex specification found at:
/// https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference
/// </summary>
/// <remarks>
/// This class provides functionality to define a domain using a regular expression
/// and supports validation and matching of other domains against the specified pattern.
/// </remarks>
[Serializable]
public sealed class RegexDomain : DomainSpecification
{
public const string Delimiter = "/";
private static readonly TimeSpan DefaultRegexTimeout = TimeSpan.FromMilliseconds(100);
private readonly Regex _regex;
private readonly RegexOptions _regexOptions;
private readonly TimeSpan _regexTimeout;
public RegexDomain(
string value,
bool validate = true,
RegexUsageMode regexUsageMode = RegexUsageMode.Instance,
RegexCompilationMode regexCompilationMode = RegexCompilationMode.Interpreted,
TimeSpan? regexTimeout = null)
: base(value, validate, IsValid)
{
_regexTimeout = regexTimeout ?? DefaultRegexTimeout;
_regexOptions = RegexOptions.Singleline;
if (regexCompilationMode == RegexCompilationMode.Compiled)
_regexOptions |= RegexOptions.Compiled;
if (regexUsageMode == RegexUsageMode.Instance)
_regex = new Regex(Normalize(Value), _regexOptions, _regexTimeout);
}
public override int GetMatchRelevance(Domain domain)
{
try
{
if (_regex != null)
return _regex.IsMatch(domain.ToString()) ? 1 : 0;
return Regex.IsMatch(domain.ToString(), Normalize(Value), _regexOptions, _regexTimeout) ? 1 : 0;
}
catch (RegexMatchTimeoutException)
{
return 0;
}
}
private static bool IsValid(string domainAsString)
{
if (!domainAsString.StartsWith(Delimiter, StringComparison.Ordinal)
|| !domainAsString.EndsWith(Delimiter, StringComparison.Ordinal))
{
return false;
}
var normalizedDomainAsString = Normalize(domainAsString);
if (string.IsNullOrWhiteSpace(normalizedDomainAsString))
return false;
try
{
_ = new Regex(normalizedDomainAsString);
return true;
}
catch (ArgumentException)
{
return false;
}
}
private static string Normalize(string domainAsString)
=> domainAsString.Trim(Delimiter.ToCharArray());
}
================================================
FILE: source/NsDepCop.Analyzer/Config/RegexUsageMode.cs
================================================
namespace Codartis.NsDepCop.Config;
public enum RegexUsageMode
{
Static,
Instance
}
================================================
FILE: source/NsDepCop.Analyzer/Config/TypeNameSet.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// A set of type names represented as strings (without namespace part).
/// </summary>
[Serializable]
public class TypeNameSet : HashSet<string>
{
public TypeNameSet()
{
}
public TypeNameSet(IEnumerable<string> collection)
: base(collection)
{
}
protected TypeNameSet(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public override string ToString() => this.Any() ? $"{{{string.Join(",", this)}}}" : "{}";
}
}
================================================
FILE: source/NsDepCop.Analyzer/Config/WildcardDomain.cs
================================================
using System;
using System.Linq;
namespace Codartis.NsDepCop.Config
{
/// <summary>
/// Represents a domain specification with wildcards, eg. 'System.IO.*' or 'System.?.?.Generic'.
/// Each '?' can be replaced with exactly one domain component when matching against a domain.
/// Each '*' can be replaced with any number of domain components.
/// <br/>
/// This class is immutable.
/// </summary>
/// <remarks>
/// The 'any domain' (represented by a star '*') is also a domain that contains every domain.
/// </remarks>
[Serializable]
public sealed class WildcardDomain : DomainSpecification
{
private readonly string[] _domainComponents;
public const string SingleDomainMarker = "?";
public const string AnyDomainMarker = "*";
/// <summary>
/// Creates a new instance from a string representation.
/// </summary>
/// <param name="wildcardDomainAsString">The string representation of a domain pattern containing wildcards.</param>
/// <param name="validate">True means validate the input string.</param>
public WildcardDomain(string wildcardDomainAsString, bool validate = true)
: base(wildcardDomainAsString, validate, IsValid)
{
_domainComponents = wildcardDomainAsString.Split(DomainPartSeparator);
}
/// <inheritdoc />
public override int GetMatchRelevance(Domain domain)
{
var actualList = domain.ToString().Split(DomainPartSeparator);
var distance = CalcDistance(actualList, _domainComponents, 0);
return int.MaxValue - distance;
}
/// <summary>
/// Returns a boolean value indication if the given <paramref name="domainAsString"/> is a valid <see cref="WildcardDomain"/>.
/// </summary>
/// <param name="domainAsString">The domain string to check.</param>
/// <returns>True, if and only if the <paramref name="domainAsString"/> is valid.</returns>
public static bool IsValid(string domainAsString)
{
var parts = domainAsString.Split(DomainPartSeparator);
bool validChars = parts.All(s =>
!string.IsNullOrWhiteSpace(s)
&& (s is SingleDomainMarker or AnyDomainMarker || (!s.Contains(SingleDomainMarker) && !s.Contains(AnyDomainMarker)))
);
bool anyWildcard = parts.Any(s => s is SingleDomainMarker or AnyDomainMarker);
bool notAdjacentTrees = parts.Length > 0 && parts.Zip(parts.Skip(1), (a, b) => (a, b)).All(p => p.a != AnyDomainMarker || p.b != AnyDomainMarker);
return validChars && anyWildcard && notAdjacentTrees;
}
/// <summary>
/// Calculates the edit distance between <paramref name="remainingPattern"/> and <paramref name="remainingActual"/>.
/// <br/>
/// The edit distance is calculated as the sum of all edit operations which are needed to replace the wildcards with
/// the domain names. The costs are as follows:
/// <ul>
/// <li>* Replacing a `?` has a cost of 1.</li>
/// <li>* Replacing a `*` has a cost of 1 and additionally a cost of 1 per sub-domain that replaces the `*`.</li>
/// </ul>
/// </summary>
/// <param name="remainingActual">A span of nested domain names to match.</param>
/// <param name="remainingPattern">A span of nested domain names or wildcards to match with.</param>
/// <param name="actualDistance">The edit cost of the parent domain.</param>
/// <returns>
/// The sum of actualDistance and the edit distance between <paramref name="remainingActual"/> and <paramref name="remainingPattern"/>.
/// </returns>
private static int CalcDistance(ReadOnlySpan<string> remainingActual, ReadOnlySpan<string> remainingPattern, int actualDistance)
{
if (remainingPattern.IsEmpty)
{
if (remainingActual.IsEmpty)
{
// completely matched
return actualDistance;
}
// no match, as the pattern is exhausted
return int.MaxValue;
}
if (remainingActual.IsEmpty)
{
if (remainingPattern.Length == 1 && remainingPattern[0] is AnyDomainMarker)
{
// removing the trailing star costs one point
return actualDistance + 1;
}
// no match, as no more input can be matched against the pattern
return int.MaxValue;
}
System.Diagnostics.Debug.Assert(!remainingActual.IsEmpty && !remainingPattern.IsEmpty);
switch (remainingPattern[0])
{
case SingleDomainMarker:
{
// replace single wildcard at cost 1
return CalcDistance(remainingActual.Slice(1), remainingPattern.Slice(1), actualDistance + 1);
}
case AnyDomainMarker:
{
// try both options: (This moves the algorithm to complexity class O(NM).)
// remove wildcard
int v1 = CalcDistance(remainingActual, remainingPattern.Slice(1), actualDistance + 1);
// use wildcard to substitute one domain component
int v2 = CalcDistance(remainingActual.Slice(1), remainingPattern, actualDistance + 1);
return Math.Min(v1, v2);
}
default:
{
if (remainingPattern[0] == remainingActual[0])
{
// full match
return CalcDistance(remainingActual.Slice(1), remainingPattern.Slice(1), actualDistance);
}
// no match
return int.MaxValue;
}
}
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/GlobalSettings.cs
================================================
using System;
namespace Codartis.NsDepCop
{
public static class GlobalSettings
{
public static bool IsToolDisabled()
{
var environmentVariableValue = Environment.GetEnvironmentVariable(ProductConstants.DisableToolEnvironmentVariableName);
return environmentVariableValue == "1" ||
string.Equals(environmentVariableValue, "true", StringComparison.OrdinalIgnoreCase);
}
}
}
================================================
FILE: source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Codartis.NsDepCop</RootNamespace>
<IsPackable>false</IsPackable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="config.nsdepcop" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Include\CommonAssemblyInfo.cs" Link="Properties\CommonAssemblyInfo.cs" />
<Compile Include="..\Include\VersionInfo.cs" Link="Properties\VersionInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DotNet.Glob" Version="2.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageReference Include="NsDepCop" Version="2.7.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
================================================
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/ISyntaxNodeAnalyzer.cs
================================================
using System.Collections.Generic;
using Codartis.NsDepCop.Analysis;
using Microsoft.CodeAnalysis;
namespace Codartis.NsDepCop.ParserAdapter.Roslyn
{
/// <summary>
/// Analyzer logic for a single syntax node.
/// </summary>
public interface ISyntaxNodeAnalyzer
{
/// <summary>
/// Returns type dependencies for a syntax node.
/// </summary>
/// <param name="node">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the current document.</param>
/// <returns>A list of type dependencies. Can be empty.</returns>
IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node, SemanticModel semanticModel);
}
}
================================================
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeAnalyzer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using Codartis.NsDepCop.Analysis;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Codartis.NsDepCop.ParserAdapter.Roslyn
{
/// <summary>
/// Enumerates type dependencies for a syntax node using Roslyn 1.x.
/// </summary>
public class SyntaxNodeAnalyzer : ISyntaxNodeAnalyzer
{
/// <summary>
/// The list of those type kinds that can occur as a declaration.
/// </summary>
private static readonly List<TypeKind> DeclarationTypeKinds = new()
{
TypeKind.Class,
TypeKind.Delegate,
TypeKind.Enum,
TypeKind.Interface,
TypeKind.Struct,
};
/// <summary>
/// Returns type dependencies for a syntax node.
/// </summary>
/// <param name="node">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the current document.</param>
/// <returns>A list of type dependencies. Can be empty.</returns>
public IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node, SemanticModel semanticModel)
{
// Determine the type that contains the current syntax node.
var enclosingType = DetermineEnclosingType(node, semanticModel);
if (!IsAnalyzableDeclarationType(enclosingType))
yield break;
// Determine the type referenced by the symbol represented by the current syntax node.
var referencedType = DetermineReferencedType(node, semanticModel);
foreach (var type in GetConstituentTypes(referencedType, node))
yield return CreateTypeDependency(enclosingType, type, node);
// If this is an extension method invocation then determine the type declaring the extension method.
var declaringType = DetermineExtensionOrStaticMethodDeclaringType(node, semanticModel);
if (IsAnalyzableDeclarationType(declaringType))
yield return CreateTypeDependency(enclosingType, declaringType, node);
}
private static bool IsAnalyzableDeclarationType(ITypeSymbol typeSymbol)
{
return typeSymbol?.ContainingNamespace != null
&& !typeSymbol.IsAnonymousType
&& DeclarationTypeKinds.Contains(typeSymbol.TypeKind)
&& !string.IsNullOrWhiteSpace(typeSymbol.MetadataName);
}
protected virtual IEnumerable<ITypeSymbol> GetConstituentTypes(ITypeSymbol typeSymbol, SyntaxNode syntaxNode)
{
if (typeSymbol == null ||
typeSymbol.IsAnonymousType)
yield break;
var typeKind = typeSymbol.TypeKind;
switch (typeKind)
{
case TypeKind.Array:
var arrayTypeSymbol = (IArrayTypeSymbol) typeSymbol;
foreach (var type in GetConstituentTypes(arrayTypeSymbol.ElementType, syntaxNode))
yield return type;
break;
case TypeKind.Pointer:
var pointerTypeSymbol = (IPointerTypeSymbol) typeSymbol;
foreach (var type in GetConstituentTypes(pointerTypeSymbol.PointedAtType, syntaxNode))
yield return type;
break;
case TypeKind.Class:
case TypeKind.Delegate:
case TypeKind.Enum:
case TypeKind.Interface:
case TypeKind.Struct:
var namedTypeSymbol = typeSymbol as INamedTypeSymbol;
if (namedTypeSymbol == null)
yield break;
if (namedTypeSymbol.IsGenericType)
{
yield return namedTypeSymbol.ConstructedFrom;
// If the syntax node has any identifier descendants then those will trigger analysis for the type arguments
// so there's no need to recurse into the type arguments here.
if (syntaxNode.HasDescendant<IdentifierNameSyntax>())
yield break;
foreach (var typeArgument in namedTypeSymbol.TypeArguments)
foreach (var type in GetConstituentTypes(typeArgument, syntaxNode))
yield return type;
}
else
{
yield return namedTypeSymbol;
}
break;
case TypeKind.Dynamic:
case TypeKind.Error:
case TypeKind.Module:
case TypeKind.Unknown:
case TypeKind.Submission:
case TypeKind.TypeParameter:
yield break;
default:
throw new ArgumentOutOfRangeException(nameof(typeKind), typeKind, "Unexpected value.");
}
}
/// <summary>
/// Returns a type dependency object for the given types.
/// </summary>
/// <param name="fromType">The referring type.</param>
/// <param name="toType">The referenced type.</param>
/// <param name="node">The syntax node currently analyzed.</param>
/// <returns>A type dependency object.</returns>
private static TypeDependency CreateTypeDependency(ITypeSymbol fromType, ITypeSymbol toType, SyntaxNode node)
{
return new TypeDependency(
fromType.ContainingNamespace.ToDisplayString(), fromType.MetadataName,
toType.ContainingNamespace.ToDisplayString(), toType.MetadataName,
GetSourceSegment(node));
}
/// <summary>
/// Determines the type declaring the given extension method syntax node or
/// the declaring type of a static method when the type is statically imported.
/// e.g. <code>
/// using static A.ClassA;
/// StaticMethodOfClassA(); // in contrast to A.ClassA.StaticMethodOfClassA();
/// </code>
/// </summary>
/// <param name="node">A syntax node representing a static or extension method.</param>
/// <param name="semanticModel">The semantic model of the project.</param>
/// <returns>The type declaring the given static or extension method syntax node, or null if not found.</returns>
private static ITypeSymbol DetermineExtensionOrStaticMethodDeclaringType(SyntaxNode node, SemanticModel semanticModel)
{
var methodSymbol = semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol;
bool isExtensionMethodOrCallOnStaticImport =
methodSymbol != null
&& (methodSymbol.IsExtensionMethod
|| (methodSymbol.IsStatic && node.Parent is not MemberAccessExpressionSyntax));
return isExtensionMethodOrCallOnStaticImport ? methodSymbol.ContainingType : null;
}
/// <summary>
/// Determines the type referenced by the given syntax node.
/// </summary>
/// <param name="node">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the project.</param>
/// <returns>The type referenced by the given syntax node, or null if no type was referenced.</returns>
protected virtual ITypeSymbol DetermineReferencedType(SyntaxNode node, SemanticModel semanticModel)
{
var typeSymbol = semanticModel.GetTypeInfo(node).Type;
if (typeSymbol != null && typeSymbol.TypeKind != TypeKind.Error)
return typeSymbol;
// Special case: deconstructing declaration with var outside, e.g.: var (d, e) = Method2();
if (node.Parent is DeclarationExpressionSyntax &&
node.Parent.ChildNodes().Any(i => i is ParenthesizedVariableDesignationSyntax))
return DetermineReferencedType(node.Parent, semanticModel);
// In same cases GetTypeInfo(node).Type does not return the desired type symbol but GetSymbolInfo(node).Symbol does.
// E.g.: IdentifierNameSyntax inside an ObjectCreationExpression
var symbolInfo = semanticModel.GetSymbolInfo(node);
if (symbolInfo.Symbol is ITypeSymbol symbolInfoTypeSymbol)
return symbolInfoTypeSymbol;
// Special case: for method invocations we should check the return type
if (symbolInfo.Symbol is IMethodSymbol methodSymbol)
return methodSymbol.ReturnType;
// Could not determine referenced type.
return null;
}
/// <summary>
/// Determines the type that contains the given syntax node.
/// </summary>
/// <param name="node">A syntax node.</param>
/// <param name="semanticModel">The semantic model of the project.</param>
/// <returns>The type that
gitextract_m8768ds6/
├── .gitignore
├── CHANGELOG.md
├── CLAUDE.md
├── Contribute.md
├── LICENSE
├── README.md
├── appveyor.yml
├── doc/
│ ├── DependencyControl.md
│ ├── Diagnostics.md
│ ├── Help.md
│ └── Troubleshooting.md
├── images/
│ ├── docs/
│ │ ├── Figures.vsdx
│ │ └── NsDepCop_Example_w600.xcf
│ └── icons/
│ ├── NsDepCop_128.xcf
│ ├── NsDepCop_128_flat.xcf
│ ├── NsDepCop_256.xcf
│ ├── NsDepCop_40.xcf
│ ├── NsDepCop_48.xcf
│ ├── NsDepCop_ItemTemplate_40.xcf
│ ├── SetupBackground.xcf
│ └── SetupTopBanner.xcf
└── source/
├── .editorconfig
├── Directory.Build.targets
├── NsDepCop.Analyzer/
│ ├── Analysis/
│ │ ├── AssemblyDependency.cs
│ │ ├── Factory/
│ │ │ ├── AssemblyDependencyAnalyzerFactory.cs
│ │ │ └── DependencyAnalyzerFactory.cs
│ │ ├── IAssemblyDependencyAnalyzer.cs
│ │ ├── IAssemblyDependencyAnalyzerFactory.cs
│ │ ├── IDependencyAnalyzer.cs
│ │ ├── IDependencyAnalyzerFactory.cs
│ │ ├── ITypeDependencyEnumerator.cs
│ │ ├── Implementation/
│ │ │ ├── AssemblyDependencyAnalyzer.cs
│ │ │ ├── AssemblyDependencyValidator.cs
│ │ │ ├── CachingTypeDependencyValidator.cs
│ │ │ ├── DependencyAnalyzer.cs
│ │ │ ├── DependencyStatus.cs
│ │ │ ├── IAssemblyDependencyValidator.cs
│ │ │ ├── ITypeDependencyValidator.cs
│ │ │ ├── IllegalTypeDependency.cs
│ │ │ └── TypeDependencyValidator.cs
│ │ ├── Messages/
│ │ │ ├── AnalyzerMessageBase.cs
│ │ │ ├── ConfigDisabledMessage.cs
│ │ │ ├── ConfigErrorMessage.cs
│ │ │ ├── IllegalAssemblyDependencyMessage.cs
│ │ │ ├── IllegalDependencyMessage.cs
│ │ │ ├── NoConfigFileMessage.cs
│ │ │ └── ToolDisabledMessage.cs
│ │ ├── SourceSegment.cs
│ │ └── TypeDependency.cs
│ ├── Config/
│ │ ├── AnalyzerConfigState.cs
│ │ ├── ConfigDefaults.cs
│ │ ├── DependencyRule.cs
│ │ ├── Domain.cs
│ │ ├── DomainSpecification.cs
│ │ ├── DomainSpecificationParser.cs
│ │ ├── Factory/
│ │ │ └── ConfigProviderFactory.cs
│ │ ├── IAnalyzerConfig.cs
│ │ ├── IConfigProvider.cs
│ │ ├── IConfigProviderFactory.cs
│ │ ├── IDependencyRules.cs
│ │ ├── IUpdateableConfigProvider.cs
│ │ ├── Implementation/
│ │ │ ├── AnalyzerConfig.cs
│ │ │ ├── AnalyzerConfigBuilder.cs
│ │ │ ├── ConfigLoadResult.cs
│ │ │ ├── ConfigProviderBase.cs
│ │ │ ├── FileConfigProviderBase.cs
│ │ │ ├── MultiLevelXmlFileConfigProvider.cs
│ │ │ ├── RuleConfigToStringsFormatter.cs
│ │ │ ├── XmlConfigParser.cs
│ │ │ └── XmlFileConfigProvider.cs
│ │ ├── RegexCompilationMode.cs
│ │ ├── RegexDomain.cs
│ │ ├── RegexUsageMode.cs
│ │ ├── TypeNameSet.cs
│ │ └── WildcardDomain.cs
│ ├── GlobalSettings.cs
│ ├── NsDepCop.Analyzer.csproj
│ ├── ParserAdapter/
│ │ └── Roslyn/
│ │ ├── ISyntaxNodeAnalyzer.cs
│ │ ├── SyntaxNodeAnalyzer.cs
│ │ ├── SyntaxNodeExtensions.cs
│ │ ├── TypeDependencyEnumerator.cs
│ │ └── TypeDependencyEnumeratorSyntaxVisitor.cs
│ ├── ProductConstants.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── RoslynAnalyzer/
│ │ ├── AnalyzerProvider.cs
│ │ ├── DiagnosticDefinitions.cs
│ │ ├── IAnalyzerProvider.cs
│ │ └── NsDepCopAnalyzer.cs
│ ├── Util/
│ │ ├── ConcurrentDictionaryExtensions.cs
│ │ ├── DictionaryExtensions.cs
│ │ ├── EnumerableExtensions.cs
│ │ ├── ICacheStatistics.cs
│ │ ├── IDateTimeProvider.cs
│ │ ├── IDiagnosticSupport.cs
│ │ ├── IndentHelper.cs
│ │ ├── LinqExtensions.cs
│ │ ├── MathHelper.cs
│ │ └── MessageHandler.cs
│ └── config.nsdepcop
├── NsDepCop.Benchmarks/
│ ├── NsDepCop.Benchmarks.RuleTypesBenchmarks-report-github.md
│ ├── NsDepCop.Benchmarks.csproj
│ ├── Program.cs
│ ├── RuleTypesBenchmarks.cs
│ └── readme.txt
├── NsDepCop.ConfigSchema/
│ ├── NsDepCopCatalog.xml
│ └── NsDepCopConfig.xsd
├── NsDepCop.NuGet/
│ ├── NsDepCop.NuGet.csproj
│ └── tools/
│ ├── install.ps1
│ └── uninstall.ps1
├── NsDepCop.SourceTest/
│ ├── AnalyzerFeatureTests.cs
│ ├── AnalyzerFeature_AllowedDependency/
│ │ ├── AnalyzerFeature_AllowedDependency.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ChildCanDependOnParentImplicitly/
│ │ ├── AnalyzerFeature_ChildCanDependOnParentImplicitly.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_DisallowedDependency/
│ │ ├── AnalyzerFeature_DisallowedDependency.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ExcludedFiles/
│ │ ├── AnalyzerFeature_ExcludedFiles.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ExcludedFiles_WithWildcard/
│ │ ├── AnalyzerFeature_ExcludedFiles_WithWildcard.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_ParentCanDependOnChildImplicitly/
│ │ ├── AnalyzerFeature_ParentCanDependOnChildImplicitly.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/
│ │ ├── AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_SameNamespaceAlwaysAllowed/
│ │ ├── AnalyzerFeature_SameNamespaceAlwaysAllowed.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_VisibleMembersOfAllowedRule/
│ │ ├── AnalyzerFeature_VisibleMembersOfAllowedRule.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_VisibleMembersOfNamespace/
│ │ ├── AnalyzerFeature_VisibleMembersOfNamespace.cs
│ │ └── config.nsdepcop
│ ├── AnalyzerFeature_WithTopLevelStatement/
│ │ ├── AnalyzerFeature_WithTopLevelStatement.cs
│ │ └── config.nsdepcop
│ ├── Cs6Tests.cs
│ ├── Cs6_AliasQualifiedName/
│ │ ├── Cs6_AliasQualifiedName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ArrayType/
│ │ ├── Cs6_ArrayType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Attributes/
│ │ ├── Cs6_Attributes.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Delegates/
│ │ ├── Cs6_Delegates.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ElementAccess/
│ │ ├── Cs6_ElementAccess.cs
│ │ └── config.nsdepcop
│ ├── Cs6_EveryUserDefinedTypeKind/
│ │ ├── Cs6_EveryUserDefinedTypeKind.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ExtensionMethodInvocation/
│ │ ├── Cs6_ExtensionMethodInvocation.cs
│ │ └── config.nsdepcop
│ ├── Cs6_GenericName/
│ │ ├── Cs6_GenericName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_GenericTypeArgument/
│ │ ├── Cs6_GenericTypeArgument.cs
│ │ └── config.nsdepcop
│ ├── Cs6_InvocationExpression/
│ │ ├── Cs6_InvocationExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_InvocationWithTypeArg/
│ │ ├── Cs6_InvocationWithTypeArg.cs
│ │ └── config.nsdepcop
│ ├── Cs6_MemberAccessExpression/
│ │ ├── Cs6_MemberAccessExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_NestedType/
│ │ ├── Cs6_NestedType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_NullableType/
│ │ ├── Cs6_NullableType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_ObjectCreationExpression/
│ │ ├── Cs6_ObjectCreationExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs6_PointerType/
│ │ ├── Cs6_PointerType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_QualifiedName/
│ │ ├── Cs6_QualifiedName.cs
│ │ └── config.nsdepcop
│ ├── Cs6_StaticImport/
│ │ ├── Cs6_StaticImport.cs
│ │ └── config.nsdepcop
│ ├── Cs6_Var/
│ │ ├── Cs6_Var.cs
│ │ └── config.nsdepcop
│ ├── Cs6_VarWithConstructedGenericType/
│ │ ├── Cs6_VarWithConstructedGenericType.cs
│ │ └── config.nsdepcop
│ ├── Cs6_VeryComplexType/
│ │ ├── Cs6_VeryComplexType.cs
│ │ └── config.nsdepcop
│ ├── Cs7Tests.cs
│ ├── Cs7_1_DefaultLiteral/
│ │ ├── Cs7_1_DefaultLiteral.cs
│ │ └── config.nsdepcop
│ ├── Cs7_1_InferredTupleNames/
│ │ ├── Cs7_1_InferredTupleNames.cs
│ │ └── config.nsdepcop
│ ├── Cs7_1_Tests.cs
│ ├── Cs7_2_NonTrailingNamedArguments/
│ │ ├── Cs7_2_NonTrailingNamedArguments.cs
│ │ └── config.nsdepcop
│ ├── Cs7_2_Tests.cs
│ ├── Cs7_3_AttributeOnPropertyBackingField/
│ │ ├── Cs7_3_AttributeOnPropertyBackingField.cs
│ │ └── config.nsdepcop
│ ├── Cs7_3_Tests.cs
│ ├── Cs7_Deconstruction/
│ │ ├── Cs7_Deconstruction.cs
│ │ └── config.nsdepcop
│ ├── Cs7_IsExpressionWithPattern/
│ │ ├── Cs7_IsExpressionWithPattern.cs
│ │ └── config.nsdepcop
│ ├── Cs7_LocalFunction/
│ │ ├── Cs7_LocalFunction.cs
│ │ └── config.nsdepcop
│ ├── Cs7_Out/
│ │ ├── Cs7_Out.cs
│ │ └── config.nsdepcop
│ ├── Cs7_SwitchWithPattern/
│ │ ├── Cs7_SwitchWithPattern.cs
│ │ └── config.nsdepcop
│ ├── Cs7_ThrowExpression/
│ │ ├── Cs7_ThrowExpression.cs
│ │ └── config.nsdepcop
│ ├── Cs7_Tuples/
│ │ ├── Cs7_Tuples.cs
│ │ └── config.nsdepcop
│ ├── FileBasedTestsBase.cs
│ ├── NsDepCop.SourceTest.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── SourceLineSegment.cs
│ └── SourceTestSpecification.cs
├── NsDepCop.Test/
│ ├── FileBasedTestsBase.cs
│ ├── Implementation/
│ │ ├── Analysis/
│ │ │ ├── AssemblyDependencyAnalyzerTests.cs
│ │ │ ├── CachingTypeDependencyValidatorTests.cs
│ │ │ ├── DependencyAnalyzerTests.cs
│ │ │ ├── DependencyRulesBuilder.cs
│ │ │ ├── TypeDependencyValidatorExtensions.cs
│ │ │ └── TypeDependencyValidatorTests.cs
│ │ └── Config/
│ │ ├── AnalyzerConfigBuilderTests.cs
│ │ ├── MultiLevelXmlFileConfigProviderTests/
│ │ │ ├── Attributes_LowerLevelWins/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── Attributes_MissingDoesNotOverwrite/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtHigherLevelButEnabledAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigDisabledAtProjectLevel/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigEnabled/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ConfigError/
│ │ │ │ ├── Level2/
│ │ │ │ │ ├── Level1/
│ │ │ │ │ │ └── config.nsdepcop
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── ExcludedFiles_AllCorrectlyRooted/
│ │ │ │ └── Level2/
│ │ │ │ ├── Excluded File 4.cs
│ │ │ │ ├── ExcludedFile3.cs
│ │ │ │ ├── Level1/
│ │ │ │ │ ├── Excluded File 2.cs
│ │ │ │ │ ├── ExcludedFile1.cs
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── NoConfig/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── RefreshConfig_EnabledToConfigError/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToDisabled/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToEnabledButChanged/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToNoConfig/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── RefreshConfig_InheritanceDepthChanged/
│ │ │ │ ├── Level2/
│ │ │ │ │ └── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── RefreshConfig_NoConfigToEnabled/
│ │ │ │ └── Level2/
│ │ │ │ └── Level1/
│ │ │ │ └── placeholder.txt
│ │ │ ├── Rules_Merged/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ ├── UpdateMaxIssueCount_Level1ContainsMaxIssueCount/
│ │ │ │ └── Level2/
│ │ │ │ ├── Level1/
│ │ │ │ │ └── config.nsdepcop
│ │ │ │ └── config.nsdepcop
│ │ │ └── UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount/
│ │ │ └── Level2/
│ │ │ ├── Level1/
│ │ │ │ └── config.nsdepcop
│ │ │ └── config.nsdepcop
│ │ ├── MultiLevelXmlFileConfigProviderTests.cs
│ │ ├── XmlConfigParserTests/
│ │ │ ├── AllowedAssemblyRules.nsdepcop
│ │ │ ├── AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute.nsdepcop
│ │ │ ├── AllowedRuleForWildcardNamespaceWithVisibleMembers.nsdepcop
│ │ │ ├── AllowedRuleFromAttributeMissing.nsdepcop
│ │ │ ├── AllowedRuleToAttributeMissing.nsdepcop
│ │ │ ├── AllowedRules.nsdepcop
│ │ │ ├── DisallowedAssemblyRules.nsdepcop
│ │ │ ├── DisallowedRules.nsdepcop
│ │ │ ├── InvalidAttributeValue.nsdepcop
│ │ │ ├── InvalidDuplicatedWildcardNamespaceString.nsdepcop
│ │ │ ├── InvalidNamespaceString.nsdepcop
│ │ │ ├── NoRootAttributes.nsdepcop
│ │ │ ├── NsDepCopConfigElementNotFound.nsdepcop
│ │ │ ├── RootAttributes.nsdepcop
│ │ │ ├── VisibleMembers.nsdepcop
│ │ │ ├── VisibleMembersOfNamespaceMissing.nsdepcop
│ │ │ └── VisibleMembersTypeNameAttributeMissing.nsdepcop
│ │ ├── XmlConfigParserTests.cs
│ │ ├── XmlFileConfigProviderTests/
│ │ │ ├── Disabled.nsdepcop
│ │ │ ├── Enabled.nsdepcop
│ │ │ ├── Erronous.nsdepcop
│ │ │ ├── Excluded File 2.cs
│ │ │ ├── ExcludedFile1.cs
│ │ │ ├── ExcludedFiles.nsdepcop
│ │ │ ├── RefreshConfig_EnabledToConfigError.nsdepcop
│ │ │ └── RefreshConfig_EnabledToDisabled.nsdepcop
│ │ ├── XmlFileConfigProviderTests.cs
│ │ └── XmlFileConfigTestBase.cs
│ ├── Interface/
│ │ └── Config/
│ │ ├── DomainSpecificationParserTests.cs
│ │ ├── DomainSpecificationTests.cs
│ │ ├── DomainTests.cs
│ │ ├── RegexDomainTests.cs
│ │ └── WildcardDomainTests.cs
│ ├── NsDepCop.Test.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ └── RoslynAnalyzer/
│ └── AnalyzerProviderTests.cs
├── NsDepCop.Vsix/
│ ├── NsDepCop.Vsix.csproj
│ ├── readme.txt
│ └── source.extension.vsixmanifest
├── NsDepCop.sln
├── NsDepCop.sln.DotSettings
├── config.nsdepcop
└── include/
├── CommonAssemblyInfo.cs
└── VersionInfo.cs
SYMBOL INDEX (774 symbols across 149 files)
FILE: source/NsDepCop.Analyzer/Analysis/AssemblyDependency.cs
type AssemblyDependency (line 6) | [Serializable]
method AssemblyDependency (line 15) | public AssemblyDependency(AssemblyIdentity fromAssembly, AssemblyIdent...
method ToString (line 21) | public override string ToString() => $"{FromAssembly?.Name}->{ToAssemb...
method Equals (line 23) | public bool Equals(AssemblyDependency other)
method Equals (line 29) | public override bool Equals(object obj)
method GetHashCode (line 35) | public override int GetHashCode()
FILE: source/NsDepCop.Analyzer/Analysis/Factory/AssemblyDependencyAnalyzerFactory.cs
class AssemblyDependencyAnalyzerFactory (line 6) | public sealed class AssemblyDependencyAnalyzerFactory : IAssemblyDepende...
method Create (line 8) | public IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider co...
FILE: source/NsDepCop.Analyzer/Analysis/Factory/DependencyAnalyzerFactory.cs
class DependencyAnalyzerFactory (line 10) | public sealed class DependencyAnalyzerFactory : IDependencyAnalyzerFactory
method DependencyAnalyzerFactory (line 14) | public DependencyAnalyzerFactory(MessageHandler traceMessageHandler)
method Create (line 19) | public IDependencyAnalyzer Create(IUpdateableConfigProvider configProv...
FILE: source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzer.cs
type IAssemblyDependencyAnalyzer (line 12) | public interface IAssemblyDependencyAnalyzer
method AnalyzeProject (line 14) | IEnumerable<AnalyzerMessageBase> AnalyzeProject(AssemblyIdentity sourc...
method RefreshConfig (line 19) | void RefreshConfig();
FILE: source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzerFactory.cs
type IAssemblyDependencyAnalyzerFactory (line 5) | public interface IAssemblyDependencyAnalyzerFactory
method Create (line 7) | IAssemblyDependencyAnalyzer Create(IUpdateableConfigProvider configPro...
FILE: source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzer.cs
type IDependencyAnalyzer (line 12) | public interface IDependencyAnalyzer
method AnalyzeProject (line 20) | IEnumerable<AnalyzerMessageBase> AnalyzeProject(IEnumerable<string> so...
method AnalyzeSyntaxNode (line 28) | IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode syntaxNo...
method RefreshConfig (line 33) | void RefreshConfig();
FILE: source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzerFactory.cs
type IDependencyAnalyzerFactory (line 8) | public interface IDependencyAnalyzerFactory
method Create (line 10) | IDependencyAnalyzer Create(IUpdateableConfigProvider configProvider, I...
FILE: source/NsDepCop.Analyzer/Analysis/ITypeDependencyEnumerator.cs
type ITypeDependencyEnumerator (line 10) | public interface ITypeDependencyEnumerator
method GetTypeDependencies (line 19) | IEnumerable<TypeDependency> GetTypeDependencies(
method GetTypeDependencies (line 31) | IEnumerable<TypeDependency> GetTypeDependencies(
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyAnalyzer.cs
class AssemblyDependencyAnalyzer (line 11) | public sealed class AssemblyDependencyAnalyzer : IAssemblyDependencyAnal...
method AssemblyDependencyAnalyzer (line 19) | public AssemblyDependencyAnalyzer(
method AnalyzeProject (line 59) | public IEnumerable<AnalyzerMessageBase> AnalyzeProject(
method GetAssemblyDependencies (line 77) | private IEnumerable<AssemblyDependency> GetAssemblyDependencies(Assemb...
method RefreshConfig (line 85) | public void RefreshConfig()
method UpdateConfig (line 94) | private void UpdateConfig()
method CreateTypeDependencyValidator (line 105) | private AssemblyDependencyValidator CreateTypeDependencyValidator()
method AnalyzeCore (line 112) | private IEnumerable<AnalyzerMessageBase> AnalyzeCore(IEnumerable<Assem...
method PerformAnalysis (line 126) | private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(IEnume...
method GetIllegalAssemblyDependencies (line 131) | private IEnumerable<AssemblyDependency> GetIllegalAssemblyDependencies...
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyValidator.cs
class AssemblyDependencyValidator (line 9) | public sealed class AssemblyDependencyValidator : IAssemblyDependencyVal...
method AssemblyDependencyValidator (line 14) | public AssemblyDependencyValidator(IDependencyRules dependencyRules)
method IsDependencyAllowed (line 22) | public DependencyStatus IsDependencyAllowed(AssemblyDependency assembl...
method GetMostSpecificAllowRule (line 44) | private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)
method GetDisallowRule (line 51) | private DependencyRule GetDisallowRule(Domain from, Domain to)
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/CachingTypeDependencyValidator.cs
class CachingTypeDependencyValidator (line 10) | public class CachingTypeDependencyValidator : TypeDependencyValidator, I...
method CachingTypeDependencyValidator (line 18) | public CachingTypeDependencyValidator(IDependencyRules dependencyRules...
method IsAllowedDependency (line 27) | public override DependencyStatus IsAllowedDependency(TypeDependency ty...
method LogTraceMessage (line 47) | private void LogTraceMessage(string message) => _traceMessageHandler?....
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/DependencyAnalyzer.cs
class DependencyAnalyzer (line 15) | public sealed class DependencyAnalyzer : IDependencyAnalyzer
method DependencyAnalyzer (line 26) | public DependencyAnalyzer(
method AnalyzeProject (line 71) | public IEnumerable<AnalyzerMessageBase> AnalyzeProject(
method AnalyzeSyntaxNode (line 90) | public IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode(SyntaxNode s...
method RefreshConfig (line 104) | public void RefreshConfig()
method UpdateConfig (line 113) | private void UpdateConfig()
method CreateTypeDependencyValidator (line 125) | private CachingTypeDependencyValidator CreateTypeDependencyValidator()
method AnalyzeCore (line 132) | private IEnumerable<AnalyzerMessageBase> AnalyzeCore(Func<IEnumerable<...
method PerformAnalysis (line 144) | private static IEnumerable<AnalyzerMessageBase> PerformAnalysis(Func<I...
method GetIllegalTypeDependencies (line 155) | private IEnumerable<IllegalTypeDependency> GetIllegalTypeDependencies(...
method GetCacheStatisticsMessage (line 172) | private static string GetCacheStatisticsMessage(ICacheStatisticsProvid...
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/DependencyStatus.cs
class DependencyStatus (line 5) | public class DependencyStatus
method DependencyStatus (line 7) | private DependencyStatus()
method DisallowedUseOfMember (line 19) | public static DependencyStatus DisallowedUseOfMember(string[] allowedT...
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/IAssemblyDependencyValidator.cs
type IAssemblyDependencyValidator (line 3) | public interface IAssemblyDependencyValidator
method IsDependencyAllowed (line 5) | DependencyStatus IsDependencyAllowed(AssemblyDependency assemblyDepend...
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/ITypeDependencyValidator.cs
type ITypeDependencyValidator (line 6) | internal interface ITypeDependencyValidator
method IsAllowedDependency (line 13) | DependencyStatus IsAllowedDependency(TypeDependency typeDependency);
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/IllegalTypeDependency.cs
class IllegalTypeDependency (line 3) | public class IllegalTypeDependency
method IllegalTypeDependency (line 9) | public IllegalTypeDependency(TypeDependency typeDependency, string[] a...
FILE: source/NsDepCop.Analyzer/Analysis/Implementation/TypeDependencyValidator.cs
class TypeDependencyValidator (line 11) | public class TypeDependencyValidator : ITypeDependencyValidator
method TypeDependencyValidator (line 19) | public TypeDependencyValidator(IDependencyRules dependencyRules)
method IsAllowedDependency (line 33) | public virtual DependencyStatus IsAllowedDependency(TypeDependency typ...
method IsAllowedBecauseChildCanDependOnParent (line 68) | private bool IsAllowedBecauseChildCanDependOnParent(Domain fromNamespa...
method IsAllowedBecauseParentCanDependOnChild (line 73) | private bool IsAllowedBecauseParentCanDependOnChild(Domain fromNamespa...
method GetMostSpecificAllowRule (line 78) | private DependencyRule GetMostSpecificAllowRule(Domain from, Domain to)
method GetDisallowRule (line 85) | private DependencyRule GetDisallowRule(Domain from, Domain to)
method GetVisibleMembers (line 91) | private TypeNameSet GetVisibleMembers(DependencyRule allowRule, Domain...
FILE: source/NsDepCop.Analyzer/Analysis/Messages/AnalyzerMessageBase.cs
class AnalyzerMessageBase (line 6) | public abstract class AnalyzerMessageBase
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ConfigDisabledMessage.cs
class ConfigDisabledMessage (line 6) | public sealed class ConfigDisabledMessage : AnalyzerMessageBase
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ConfigErrorMessage.cs
class ConfigErrorMessage (line 8) | public sealed class ConfigErrorMessage : AnalyzerMessageBase
method ConfigErrorMessage (line 12) | public ConfigErrorMessage(Exception exception)
FILE: source/NsDepCop.Analyzer/Analysis/Messages/IllegalAssemblyDependencyMessage.cs
class IllegalAssemblyDependencyMessage (line 3) | public sealed class IllegalAssemblyDependencyMessage : AnalyzerMessageBase
method IllegalAssemblyDependencyMessage (line 7) | public IllegalAssemblyDependencyMessage(AssemblyDependency illegalAsse...
FILE: source/NsDepCop.Analyzer/Analysis/Messages/IllegalDependencyMessage.cs
class IllegalDependencyMessage (line 8) | public sealed class IllegalDependencyMessage : AnalyzerMessageBase
method IllegalDependencyMessage (line 14) | public IllegalDependencyMessage(TypeDependency illegalDependency, stri...
FILE: source/NsDepCop.Analyzer/Analysis/Messages/NoConfigFileMessage.cs
class NoConfigFileMessage (line 6) | public sealed class NoConfigFileMessage : AnalyzerMessageBase
FILE: source/NsDepCop.Analyzer/Analysis/Messages/ToolDisabledMessage.cs
class ToolDisabledMessage (line 6) | public sealed class ToolDisabledMessage : AnalyzerMessageBase
FILE: source/NsDepCop.Analyzer/Analysis/SourceSegment.cs
type SourceSegment (line 8) | [Serializable]
method SourceSegment (line 41) | public SourceSegment(int startLine, int startColumn, int endLine, int ...
method ToString (line 51) | public override string ToString() => $"{Path} ({StartLine},{StartColum...
FILE: source/NsDepCop.Analyzer/Analysis/TypeDependency.cs
type TypeDependency (line 9) | [Serializable]
method TypeDependency (line 37) | public TypeDependency(string fromNamespaceName, string fromTypeName, s...
method ToString (line 52) | public override string ToString() => $"{FromNamespaceName}.{FromTypeNa...
method Equals (line 55) | public bool Equals(TypeDependency other)
method Equals (line 63) | public override bool Equals(object obj)
method GetHashCode (line 70) | public override int GetHashCode()
FILE: source/NsDepCop.Analyzer/Config/AnalyzerConfigState.cs
type AnalyzerConfigState (line 6) | public enum AnalyzerConfigState
FILE: source/NsDepCop.Analyzer/Config/ConfigDefaults.cs
class ConfigDefaults (line 6) | public static class ConfigDefaults
FILE: source/NsDepCop.Analyzer/Config/DependencyRule.cs
class DependencyRule (line 13) | [Serializable]
method DependencyRule (line 31) | public DependencyRule(DomainSpecification from, DomainSpecification to)
method DependencyRule (line 42) | public DependencyRule(string from, string to)
method ToString (line 50) | public override string ToString()
method Equals (line 59) | public bool Equals(DependencyRule other)
method Equals (line 64) | public override bool Equals(object obj)
method GetHashCode (line 72) | public override int GetHashCode()
FILE: source/NsDepCop.Analyzer/Config/Domain.cs
class Domain (line 12) | [Serializable]
method Domain (line 27) | public Domain(string domainAsString, bool validate = true)
method GetMatchRelevance (line 32) | public override int GetMatchRelevance(Domain domain)
method IsSubDomain (line 44) | public bool IsSubDomain(Domain parentCandidate)
method IsValid (line 61) | public static bool IsValid(string domainAsString)
method Normalize (line 79) | private static string Normalize(string domainAsString)
FILE: source/NsDepCop.Analyzer/Config/DomainSpecification.cs
class DomainSpecification (line 8) | [Serializable]
method DomainSpecification (line 24) | protected DomainSpecification(string value, bool validate, Func<string...
method GetMatchRelevance (line 42) | public abstract int GetMatchRelevance(Domain domain);
method Matches (line 49) | public bool Matches(Domain domain) => GetMatchRelevance(domain) > 0;
method ToString (line 51) | public override string ToString() => Value;
method Equals (line 53) | public bool Equals(DomainSpecification other)
method Equals (line 60) | public override bool Equals(object obj)
method GetHashCode (line 68) | public override int GetHashCode()
FILE: source/NsDepCop.Analyzer/Config/DomainSpecificationParser.cs
class DomainSpecificationParser (line 6) | public static class DomainSpecificationParser
method Parse (line 16) | public static DomainSpecification Parse(string domainSpecificationAsSt...
FILE: source/NsDepCop.Analyzer/Config/Factory/ConfigProviderFactory.cs
class ConfigProviderFactory (line 9) | public class ConfigProviderFactory : IConfigProviderFactory
method ConfigProviderFactory (line 13) | public ConfigProviderFactory(MessageHandler traceMessageHandler)
method CreateFromXmlConfigFile (line 18) | public IUpdateableConfigProvider CreateFromXmlConfigFile(string config...
method CreateFromMultiLevelXmlConfigFile (line 23) | public IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(str...
FILE: source/NsDepCop.Analyzer/Config/IAnalyzerConfig.cs
type IAnalyzerConfig (line 8) | public interface IAnalyzerConfig : IDependencyRules, IDiagnosticSupport
FILE: source/NsDepCop.Analyzer/Config/IConfigProvider.cs
type IConfigProvider (line 8) | public interface IConfigProvider
method RefreshConfig (line 33) | void RefreshConfig();
FILE: source/NsDepCop.Analyzer/Config/IConfigProviderFactory.cs
type IConfigProviderFactory (line 6) | public interface IConfigProviderFactory
method CreateFromXmlConfigFile (line 13) | IUpdateableConfigProvider CreateFromXmlConfigFile(string configFilePath);
method CreateFromMultiLevelXmlConfigFile (line 20) | IUpdateableConfigProvider CreateFromMultiLevelXmlConfigFile(string fol...
FILE: source/NsDepCop.Analyzer/Config/IDependencyRules.cs
type IDependencyRules (line 8) | public interface IDependencyRules
FILE: source/NsDepCop.Analyzer/Config/IUpdateableConfigProvider.cs
type IUpdateableConfigProvider (line 6) | public interface IUpdateableConfigProvider: IConfigProvider
method UpdateMaxIssueCount (line 12) | void UpdateMaxIssueCount(int newValue);
FILE: source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfig.cs
class AnalyzerConfig (line 9) | [Serializable]
method AnalyzerConfig (line 25) | public AnalyzerConfig(
method ToStrings (line 54) | public IEnumerable<string> ToStrings()
FILE: source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfigBuilder.cs
class AnalyzerConfigBuilder (line 12) | public class AnalyzerConfigBuilder
method AnalyzerConfigBuilder (line 28) | public AnalyzerConfigBuilder()
method ToAnalyzerConfig (line 38) | public IAnalyzerConfig ToAnalyzerConfig()
method Combine (line 56) | public AnalyzerConfigBuilder Combine(AnalyzerConfigBuilder analyzerCon...
method SetInheritanceDepth (line 76) | public AnalyzerConfigBuilder SetInheritanceDepth(int? inheritanceDepth)
method SetIsEnabled (line 83) | public AnalyzerConfigBuilder SetIsEnabled(bool? isEnabled)
method AddSourcePathExclusionPatterns (line 90) | public AnalyzerConfigBuilder AddSourcePathExclusionPatterns(IEnumerabl...
method SetCheckAssemblyDependencies (line 98) | public AnalyzerConfigBuilder SetCheckAssemblyDependencies(bool? checkA...
method MakePathsRooted (line 105) | public AnalyzerConfigBuilder MakePathsRooted(string rootPath)
method SetChildCanDependOnParentImplicitly (line 115) | public AnalyzerConfigBuilder SetChildCanDependOnParentImplicitly(bool?...
method SetParentCanDependOnChildImplicitly (line 122) | public AnalyzerConfigBuilder SetParentCanDependOnChildImplicitly(bool?...
method AddAllowRule (line 129) | public AnalyzerConfigBuilder AddAllowRule(DependencyRule dependencyRul...
method AddAllowRules (line 135) | private AnalyzerConfigBuilder AddAllowRules(IEnumerable<KeyValuePair<D...
method AddDisallowRule (line 142) | public AnalyzerConfigBuilder AddDisallowRule(DependencyRule dependency...
method AddDisallowRules (line 148) | private AnalyzerConfigBuilder AddDisallowRules(IEnumerable<DependencyR...
method AddAllowedAssemblyRule (line 155) | public AnalyzerConfigBuilder AddAllowedAssemblyRule(DependencyRule ass...
method AddAllowedAssemblyRules (line 161) | private AnalyzerConfigBuilder AddAllowedAssemblyRules(IEnumerable<Depe...
method AddDisallowedAssemblyRule (line 168) | public AnalyzerConfigBuilder AddDisallowedAssemblyRule(DependencyRule ...
method AddDisallowedAssemblyRules (line 174) | private AnalyzerConfigBuilder AddDisallowedAssemblyRules(IEnumerable<D...
method AddVisibleTypesByNamespace (line 181) | public AnalyzerConfigBuilder AddVisibleTypesByNamespace(Domain domain,...
method AddVisibleTypesByNamespace (line 187) | private AnalyzerConfigBuilder AddVisibleTypesByNamespace(IEnumerable<K...
method SetMaxIssueCount (line 194) | public AnalyzerConfigBuilder SetMaxIssueCount(int? maxIssueCount)
method SetAutoLowerMaxIssueCount (line 201) | public AnalyzerConfigBuilder SetAutoLowerMaxIssueCount(bool? autoLower...
method ToStrings (line 208) | public IEnumerable<string> ToStrings()
method ToRootedPath (line 234) | private static string ToRootedPath(string rootPath, string path)
FILE: source/NsDepCop.Analyzer/Config/Implementation/ConfigLoadResult.cs
type ConfigLoadResult (line 9) | public readonly struct ConfigLoadResult
method ConfigLoadResult (line 16) | private ConfigLoadResult(AnalyzerConfigState configState, AnalyzerConf...
method CreateWithError (line 25) | public static ConfigLoadResult CreateWithError(Exception configException)
method CreateWithNoConfig (line 33) | public static ConfigLoadResult CreateWithNoConfig()
method CreateWithConfig (line 38) | public static ConfigLoadResult CreateWithConfig(AnalyzerConfigBuilder ...
method ToStrings (line 49) | public IEnumerable<string> ToStrings()
FILE: source/NsDepCop.Analyzer/Config/Implementation/ConfigProviderBase.cs
class ConfigProviderBase (line 12) | public abstract class ConfigProviderBase : IUpdateableConfigProvider
method ConfigProviderBase (line 24) | protected ConfigProviderBase(MessageHandler traceMessageHandler)
method RefreshConfig (line 79) | public void RefreshConfig()
method UpdateMaxIssueCount (line 88) | public void UpdateMaxIssueCount(int newValue)
method LoadConfigCore (line 101) | protected abstract ConfigLoadResult LoadConfigCore();
method RefreshConfigCore (line 102) | protected abstract ConfigLoadResult RefreshConfigCore();
method UpdateMaxIssueCountCore (line 103) | protected abstract ConfigLoadResult UpdateMaxIssueCountCore(int newVal...
method EnsureInitialized (line 105) | protected void EnsureInitialized()
FILE: source/NsDepCop.Analyzer/Config/Implementation/FileConfigProviderBase.cs
class FileConfigProviderBase (line 14) | public abstract class FileConfigProviderBase : ConfigProviderBase
method FileConfigProviderBase (line 22) | protected FileConfigProviderBase(string configFilePath, MessageHandler...
method HasConfigFileChanged (line 32) | public bool HasConfigFileChanged()
method LoadConfigCore (line 38) | protected override ConfigLoadResult LoadConfigCore()
method RefreshConfigCore (line 44) | protected override ConfigLoadResult RefreshConfigCore()
method LoadConfigFromFile (line 53) | private ConfigLoadResult LoadConfigFromFile()
method CreateConfigBuilderFromFile (line 75) | protected abstract AnalyzerConfigBuilder CreateConfigBuilderFromFile(s...
method ConfigFileCreatedOrDeleted (line 77) | private bool ConfigFileCreatedOrDeleted()
method ConfigFileModifiedSinceLastLoad (line 82) | private bool ConfigFileModifiedSinceLastLoad()
method LogTraceMessage (line 88) | private void LogTraceMessage(string message) => TraceMessageHandler?.I...
FILE: source/NsDepCop.Analyzer/Config/Implementation/MultiLevelXmlFileConfigProvider.cs
class MultiLevelXmlFileConfigProvider (line 16) | public sealed class MultiLevelXmlFileConfigProvider : ConfigProviderBase
method MultiLevelXmlFileConfigProvider (line 32) | public MultiLevelXmlFileConfigProvider(string projectFolder, MessageHa...
method ToString (line 52) | public override string ToString() => $"MultiLevelXmlConfig:'{ProjectFo...
method LoadConfigCore (line 54) | protected override ConfigLoadResult LoadConfigCore()
method RefreshConfigCore (line 65) | protected override ConfigLoadResult RefreshConfigCore()
method UpdateMaxIssueCountCore (line 88) | protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)
method CombineFileConfigProvidersAndSaveResult (line 95) | private ConfigLoadResult CombineFileConfigProvidersAndSaveResult()
method CombineFileConfigProviders (line 105) | private ConfigLoadResult CombineFileConfigProviders()
method CreateAnalyzerConfigBuilder (line 147) | private static AnalyzerConfigBuilder CreateAnalyzerConfigBuilder() => ...
method AnyChildConfigChanged (line 149) | private bool AnyChildConfigChanged() => _fileConfigProviders.Any(i => ...
method CreateFileConfigProviderList (line 151) | private List<XmlFileConfigProvider> CreateFileConfigProviderList(XmlFi...
method GetConfigFilePath (line 171) | private static string GetConfigFilePath(string folderPath) => Path.Com...
method LogTraceMessage (line 173) | private void LogTraceMessage(IEnumerable<string> messages)
method LogTraceMessage (line 179) | private void LogTraceMessage(string message) => TraceMessageHandler?.I...
FILE: source/NsDepCop.Analyzer/Config/Implementation/RuleConfigToStringsFormatter.cs
class RuleConfigToStringsFormatter (line 8) | public static class RuleConfigToStringsFormatter
method ToStrings (line 10) | public static IEnumerable<string> ToStrings(this IDictionary<Dependenc...
method ToStrings (line 17) | public static IEnumerable<string> ToStrings(this ISet<DependencyRule> ...
method ToStrings (line 24) | public static IEnumerable<string> ToStrings(this IDictionary<Domain, T...
FILE: source/NsDepCop.Analyzer/Config/Implementation/XmlConfigParser.cs
class XmlConfigParser (line 14) | public static class XmlConfigParser
method Parse (line 36) | public static AnalyzerConfigBuilder Parse(XDocument configXml)
method UpdateMaxIssueCount (line 47) | public static void UpdateMaxIssueCount(XDocument configXml, int newValue)
method GetRootElement (line 54) | private static XElement GetRootElement(XDocument configXml)
method ParseRootNodeAttributes (line 62) | private static void ParseRootNodeAttributes(XElement rootElement, Anal...
method ParseStringList (line 74) | private static IEnumerable<string> ParseStringList(XElement element, s...
method Split (line 81) | private static IEnumerable<string> Split(string s, char separatorChar)
method ParseChildElements (line 86) | private static void ParseChildElements(XElement rootElement, AnalyzerC...
method ParseAllowedElement (line 114) | private static void ParseAllowedElement(XElement element, AnalyzerConf...
method ParseDisallowedElement (line 125) | private static void ParseDisallowedElement(XElement element, AnalyzerC...
method ParseAllowedAssemblyElement (line 132) | private static void ParseAllowedAssemblyElement(XElement element, Anal...
method ParseDisallowedAssemblyElement (line 139) | private static void ParseDisallowedAssemblyElement(XElement element, A...
method ParseVisibleMembersInsideAllowedRule (line 146) | private static TypeNameSet ParseVisibleMembersInsideAllowedRule(XEleme...
method ParseVisibleMembersElement (line 162) | private static void ParseVisibleMembersElement(XElement element, Analy...
method ParseDependencyRule (line 177) | private static DependencyRule ParseDependencyRule(XElement element)
method ParseAssemblyDependencyRule (line 193) | private static DependencyRule ParseAssemblyDependencyRule(XElement ele...
method TryAndReportError (line 209) | private static T TryAndReportError<T>(XObject xObject, Func<T> parserD...
method ParseTypeNameSet (line 221) | private static TypeNameSet ParseTypeNameSet(XElement element, string c...
method GetAttributeValue (line 244) | private static string GetAttributeValue(XElement element, string attri...
method AddOrUpdateAttribute (line 249) | private static void AddOrUpdateAttribute(XElement element, string attr...
method ParseValueType (line 268) | private static T? ParseValueType<T>(XElement element, string attribute...
method GetLineInfo (line 281) | private static string GetLineInfo(XObject xObject)
FILE: source/NsDepCop.Analyzer/Config/Implementation/XmlFileConfigProvider.cs
class XmlFileConfigProvider (line 12) | public sealed class XmlFileConfigProvider : FileConfigProviderBase
method XmlFileConfigProvider (line 16) | public XmlFileConfigProvider(string configFilePath, MessageHandler tra...
method ToString (line 21) | public override string ToString() => $"XmlConfig:'{ConfigFilePath}'";
method CreateConfigBuilderFromFile (line 23) | protected override AnalyzerConfigBuilder CreateConfigBuilderFromFile(s...
method UpdateMaxIssueCountCore (line 29) | protected override ConfigLoadResult UpdateMaxIssueCountCore(int newValue)
FILE: source/NsDepCop.Analyzer/Config/RegexCompilationMode.cs
type RegexCompilationMode (line 3) | public enum RegexCompilationMode
FILE: source/NsDepCop.Analyzer/Config/RegexDomain.cs
class RegexDomain (line 15) | [Serializable]
method RegexDomain (line 26) | public RegexDomain(
method GetMatchRelevance (line 44) | public override int GetMatchRelevance(Domain domain)
method IsValid (line 59) | private static bool IsValid(string domainAsString)
method Normalize (line 82) | private static string Normalize(string domainAsString)
FILE: source/NsDepCop.Analyzer/Config/RegexUsageMode.cs
type RegexUsageMode (line 3) | public enum RegexUsageMode
FILE: source/NsDepCop.Analyzer/Config/TypeNameSet.cs
class TypeNameSet (line 11) | [Serializable]
method TypeNameSet (line 14) | public TypeNameSet()
method TypeNameSet (line 18) | public TypeNameSet(IEnumerable<string> collection)
method TypeNameSet (line 23) | protected TypeNameSet(SerializationInfo info, StreamingContext context)
method ToString (line 28) | public override string ToString() => this.Any() ? $"{{{string.Join(","...
FILE: source/NsDepCop.Analyzer/Config/WildcardDomain.cs
class WildcardDomain (line 16) | [Serializable]
method WildcardDomain (line 28) | public WildcardDomain(string wildcardDomainAsString, bool validate = t...
method GetMatchRelevance (line 35) | public override int GetMatchRelevance(Domain domain)
method IsValid (line 49) | public static bool IsValid(string domainAsString)
method CalcDistance (line 79) | private static int CalcDistance(ReadOnlySpan<string> remainingActual, ...
FILE: source/NsDepCop.Analyzer/GlobalSettings.cs
class GlobalSettings (line 5) | public static class GlobalSettings
method IsToolDisabled (line 7) | public static bool IsToolDisabled()
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/ISyntaxNodeAnalyzer.cs
type ISyntaxNodeAnalyzer (line 10) | public interface ISyntaxNodeAnalyzer
method GetTypeDependencies (line 18) | IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node, Seman...
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeAnalyzer.cs
class SyntaxNodeAnalyzer (line 13) | public class SyntaxNodeAnalyzer : ISyntaxNodeAnalyzer
method GetTypeDependencies (line 33) | public IEnumerable<TypeDependency> GetTypeDependencies(SyntaxNode node...
method IsAnalyzableDeclarationType (line 51) | private static bool IsAnalyzableDeclarationType(ITypeSymbol typeSymbol)
method GetConstituentTypes (line 59) | protected virtual IEnumerable<ITypeSymbol> GetConstituentTypes(ITypeSy...
method CreateTypeDependency (line 129) | private static TypeDependency CreateTypeDependency(ITypeSymbol fromTyp...
method DetermineExtensionOrStaticMethodDeclaringType (line 148) | private static ITypeSymbol DetermineExtensionOrStaticMethodDeclaringTy...
method DetermineReferencedType (line 166) | protected virtual ITypeSymbol DetermineReferencedType(SyntaxNode node,...
method DetermineEnclosingType (line 197) | private static ITypeSymbol DetermineEnclosingType(SyntaxNode node, Sem...
method GetSourceSegment (line 218) | private static SourceSegment GetSourceSegment(SyntaxNode syntaxNode)
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeExtensions.cs
class SyntaxNodeExtensions (line 8) | public static class SyntaxNodeExtensions
method IsTypeDeclaration (line 10) | public static bool IsTypeDeclaration(this SyntaxNode syntaxNode)
method HasDescendant (line 16) | public static bool HasDescendant<T>(this SyntaxNode syntaxNode)
method IsOrHasDescendant (line 25) | public static bool IsOrHasDescendant<T>(this SyntaxNode syntaxNode)
method HasParent (line 37) | public static bool HasParent<T>(this SyntaxNode syntaxNode)
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumerator.cs
class TypeDependencyEnumerator (line 16) | public class TypeDependencyEnumerator : ITypeDependencyEnumerator
method TypeDependencyEnumerator (line 23) | public TypeDependencyEnumerator(ISyntaxNodeAnalyzer syntaxNodeAnalyzer...
method CreateSyntaxVisitor (line 29) | private static TypeDependencyEnumeratorSyntaxVisitor CreateSyntaxVisitor(
method GetTypeDependencies (line 36) | public IEnumerable<TypeDependency> GetTypeDependencies(
method IsExcludedFilePath (line 51) | private static bool IsExcludedFilePath(string filePath, IEnumerable<Gl...
method GetTypeDependenciesForSyntaxTree (line 56) | private static IEnumerable<TypeDependency> GetTypeDependenciesForSynta...
method GetTypeDependencies (line 68) | public IEnumerable<TypeDependency> GetTypeDependencies(
method LoadMetadata (line 79) | private MetadataReference LoadMetadata(string fileName)
method ParseFile (line 92) | private SyntaxTree ParseFile(string fileName)
method LogTraceMessage (line 110) | private void LogTraceMessage(string message) => _traceMessageHandler?....
FILE: source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumeratorSyntaxVisitor.cs
class TypeDependencyEnumeratorSyntaxVisitor (line 17) | public class TypeDependencyEnumeratorSyntaxVisitor : CSharpSyntaxVisitor
method TypeDependencyEnumeratorSyntaxVisitor (line 39) | public TypeDependencyEnumeratorSyntaxVisitor(SemanticModel semanticMod...
method DefaultVisit (line 53) | public override void DefaultVisit(SyntaxNode node)
method VisitIdentifierName (line 59) | public override void VisitIdentifierName(IdentifierNameSyntax node)
method VisitGenericName (line 65) | public override void VisitGenericName(GenericNameSyntax node)
method VisitLiteralExpression (line 71) | public override void VisitLiteralExpression(LiteralExpressionSyntax node)
method AnalyzeNode (line 81) | private void AnalyzeNode(SyntaxNode node)
FILE: source/NsDepCop.Analyzer/ProductConstants.cs
class ProductConstants (line 8) | public static class ProductConstants
FILE: source/NsDepCop.Analyzer/RoslynAnalyzer/AnalyzerProvider.cs
class AnalyzerProvider (line 14) | public sealed class AnalyzerProvider : IAnalyzerProvider
method AnalyzerProvider (line 27) | public AnalyzerProvider(
method GetDependencyAnalyzer (line 39) | public IDependencyAnalyzer GetDependencyAnalyzer(string csprojFilePath)
method CreateDependencyAnalyzer (line 52) | private IDependencyAnalyzer CreateDependencyAnalyzer(string projectFil...
method GetAssemblyDependencyAnalyzer (line 59) | public IAssemblyDependencyAnalyzer GetAssemblyDependencyAnalyzer(strin...
method CreateAssemblyDependencyAnalyzer (line 72) | private IAssemblyDependencyAnalyzer CreateAssemblyDependencyAnalyzer(s...
FILE: source/NsDepCop.Analyzer/RoslynAnalyzer/DiagnosticDefinitions.cs
class DiagnosticDefinitions (line 9) | public static class DiagnosticDefinitions
method CreateDiagnosticDescriptor (line 77) | private static DiagnosticDescriptor CreateDiagnosticDescriptor(
FILE: source/NsDepCop.Analyzer/RoslynAnalyzer/IAnalyzerProvider.cs
type IAnalyzerProvider (line 8) | public interface IAnalyzerProvider
method GetDependencyAnalyzer (line 15) | IDependencyAnalyzer GetDependencyAnalyzer(string csprojFilePath);
method GetAssemblyDependencyAnalyzer (line 17) | IAssemblyDependencyAnalyzer GetAssemblyDependencyAnalyzer(string cspro...
FILE: source/NsDepCop.Analyzer/RoslynAnalyzer/NsDepCopAnalyzer.cs
class NsDepCopAnalyzer (line 23) | [DiagnosticAnalyzer(LanguageNames.CSharp)]
method NsDepCopAnalyzer (line 47) | public NsDepCopAnalyzer()
method Initialize (line 59) | public override void Initialize(AnalysisContext analysisContext)
method OnCompilationStart (line 68) | private void OnCompilationStart(CompilationStartAnalysisContext compil...
method AnalyzeSyntaxNodeAndReportDiagnostics (line 105) | private static void AnalyzeSyntaxNodeAndReportDiagnostics(
method GetInterlocked (line 150) | private static int GetInterlocked(ref int issueCount) => Interlocked.C...
method OnCompilation (line 152) | private void OnCompilation(CompilationAnalysisContext compilationAnaly...
method ReportForSyntaxTree (line 197) | private static void ReportForSyntaxTree(
method ReportForSyntaxNode (line 207) | private static void ReportForSyntaxNode(
method ReportForCompilationAnalysisContext (line 218) | private static void ReportForCompilationAnalysisContext(
method CreateDiagnostic (line 227) | private static Diagnostic CreateDiagnostic(DiagnosticDescriptor diagno...
method GetConfigFilePath (line 232) | private static string GetConfigFilePath(ImmutableArray<AdditionalText>...
method IsConfigFile (line 237) | private static bool IsConfigFile(AdditionalText additionalText)
method LogTraceMessage (line 242) | private static void LogTraceMessage(string message) => Debug.WriteLine...
FILE: source/NsDepCop.Analyzer/Util/ConcurrentDictionaryExtensions.cs
class ConcurrentDictionaryExtensions (line 9) | public static class ConcurrentDictionaryExtensions
method GetOrAdd (line 22) | public static TValue GetOrAdd<TKey, TValue>(this ConcurrentDictionary<...
FILE: source/NsDepCop.Analyzer/Util/DictionaryExtensions.cs
class DictionaryExtensions (line 9) | public static class DictionaryExtensions
method AddOrUnion (line 21) | public static void AddOrUnion<TKey, TCollection, TValue>(this Dictiona...
FILE: source/NsDepCop.Analyzer/Util/EnumerableExtensions.cs
class EnumerableExtensions (line 10) | public static class EnumerableExtensions
method EmptyIfNull (line 18) | public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> collec...
method IsNullOrEmpty (line 29) | public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)
method ToSingleString (line 44) | public static string ToSingleString<T>(this IEnumerable<T> collection,...
method ToEnumerable (line 72) | public static IEnumerable<T> ToEnumerable<T>(this T item)
FILE: source/NsDepCop.Analyzer/Util/ICacheStatistics.cs
type ICacheStatisticsProvider (line 6) | public interface ICacheStatisticsProvider
FILE: source/NsDepCop.Analyzer/Util/IDateTimeProvider.cs
type IDateTimeProvider (line 11) | public interface IDateTimeProvider
FILE: source/NsDepCop.Analyzer/Util/IDiagnosticSupport.cs
type IDiagnosticSupport (line 8) | public interface IDiagnosticSupport
method ToStrings (line 13) | IEnumerable<string> ToStrings();
FILE: source/NsDepCop.Analyzer/Util/IndentHelper.cs
class IndentHelper (line 9) | public static class IndentHelper
method Indent (line 13) | public static IEnumerable<string> Indent(string message, int indent = 0)
method Indent (line 16) | public static IEnumerable<string> Indent(IEnumerable<string> messages,...
method Format (line 19) | private static string Format(string message, int indent = 0)
FILE: source/NsDepCop.Analyzer/Util/LinqExtensions.cs
class LinqExtensions (line 6) | public static class LinqExtensions
method MinByOrDefault (line 8) | public static TSource MinByOrDefault<TSource, TKey>(this IEnumerable<T...
method MinByOrDefault (line 13) | public static TSource MinByOrDefault<TSource, TKey>(this IEnumerable<T...
method MaxByOrDefault (line 42) | public static TSource MaxByOrDefault<TSource, TKey>(this IEnumerable<T...
method MaxByOrDefault (line 47) | public static TSource MaxByOrDefault<TSource, TKey>(this IEnumerable<T...
FILE: source/NsDepCop.Analyzer/Util/MathHelper.cs
class MathHelper (line 6) | public static class MathHelper
method CalculatePercent (line 8) | public static double CalculatePercent(double part, double total)
FILE: source/NsDepCop.Benchmarks/Program.cs
class Program (line 5) | public class Program
method Main (line 7) | public static void Main(string[] args)
FILE: source/NsDepCop.Benchmarks/RuleTypesBenchmarks.cs
class RuleTypesBenchmarks (line 12) | [MemoryDiagnoser]
method SimpleRule (line 19) | [Benchmark]
method WildcardRule (line 26) | [Benchmark]
method RegexRule_Instance (line 36) | [Benchmark]
method RegexRule_Static (line 59) | [Benchmark]
method BenchmarkCore (line 73) | private static void BenchmarkCore(IDependencyRules config, int iterati...
FILE: source/NsDepCop.SourceTest/AnalyzerFeatureTests.cs
class AnalyzerFeatureTests (line 11) | public class AnalyzerFeatureTests
method AnalyzerFeature_AllowedDependency (line 13) | [Fact]
method AnalyzerFeature_DisallowedDependency (line 19) | [Fact]
method AnalyzerFeature_ExcludedFiles (line 29) | [Fact]
method AnalyzerFeature_ExcludedFiles_WithWildcard (line 35) | [Fact]
method AnalyzerFeature_SameNamespaceAlwaysAllowed (line 41) | [Fact]
method AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined (line 47) | [Fact]
method AnalyzerFeature_ChildCanDependOnParentImplicitly (line 53) | [Fact]
method AnalyzerFeature_ParentCanDependOnChildImplicitly (line 59) | [Fact]
method AnalyzerFeature_VisibleMembersOfNamespace (line 65) | [Fact]
method AnalyzerFeature_VisibleMembersOfAllowedRule (line 85) | [Fact]
method AnalyzerFeature_WithTopLevelStatement (line 100) | [Fact]
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_AllowedDependency/AnalyzerFeature_AllowedDependency.cs
class NoIssue (line 3) | public class NoIssue
type MyEnum (line 13) | public enum MyEnum
type MyGlobalEnum (line 17) | public enum MyGlobalEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_ChildCanDependOnParentImplicitly/AnalyzerFeature_ChildCanDependOnParentImplicitly.cs
class NoIssue (line 3) | public class NoIssue
type MyEnum (line 12) | public enum MyEnum
type MyGlobalEnum (line 16) | public enum MyGlobalEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_DisallowedDependency/AnalyzerFeature_DisallowedDependency.cs
class NoIssue (line 3) | public class NoIssue
type MyEnum (line 13) | public enum MyEnum
type MyGlobalEnum (line 17) | public enum MyGlobalEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles/AnalyzerFeature_ExcludedFiles.cs
class MyClass (line 3) | public class MyClass
type MyEnum (line 11) | public enum MyEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles_WithWildcard/AnalyzerFeature_ExcludedFiles_WithWildcard.cs
class MyClass (line 3) | public class MyClass
type MyEnum (line 11) | public enum MyEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_ParentCanDependOnChildImplicitly/AnalyzerFeature_ParentCanDependOnChildImplicitly.cs
class NoIssue (line 1) | public class NoIssue
type MyEnum (line 9) | public enum MyEnum
type MyGlobalEnum (line 15) | public enum MyGlobalEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs
class NoIssue (line 3) | public class NoIssue
type MyEnum (line 8) | public enum MyEnum
class OnlyTypeVisibleOutside (line 11) | public class OnlyTypeVisibleOutside
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAlwaysAllowed/AnalyzerFeature_SameNamespaceAlwaysAllowed.cs
class NoIssue (line 3) | public class NoIssue
type MyEnum (line 8) | public enum MyEnum
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfAllowedRule/AnalyzerFeature_VisibleMembersOfAllowedRule.cs
class MyClass (line 3) | public class MyClass
type MyEnum (line 12) | public enum MyEnum { }
class MyClass (line 17) | public class MyClass
type MyEnum (line 26) | public enum MyEnum { }
type VisibleType (line 31) | public enum VisibleType
type InvisibleType (line 34) | public enum InvisibleType
class OnlyGenericIsVisibleType (line 37) | public class OnlyGenericIsVisibleType<T>
class OnlyGenericIsVisibleType (line 40) | public class OnlyGenericIsVisibleType
class InvisibleGenericType (line 43) | public class InvisibleGenericType<T>
FILE: source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfNamespace/AnalyzerFeature_VisibleMembersOfNamespace.cs
class MyClass (line 3) | public class MyClass
type MyEnum (line 12) | public enum MyEnum { }
class MyClass (line 17) | public class MyClass
type MyEnum (line 26) | public enum MyEnum { }
type VisibleType (line 31) | public enum VisibleType
type InvisibleType (line 34) | public enum InvisibleType
class OnlyGenericIsVisibleType (line 37) | public class OnlyGenericIsVisibleType<T>
class OnlyGenericIsVisibleType (line 40) | public class OnlyGenericIsVisibleType
class InvisibleGenericType (line 43) | public class InvisibleGenericType<T>
FILE: source/NsDepCop.SourceTest/Cs6Tests.cs
class Cs6Tests (line 11) | public class Cs6Tests
method Cs6_AliasQualifiedName (line 13) | [Fact]
method Cs6_ArrayType (line 21) | [Fact]
method Cs6_QualifiedName (line 31) | [Fact]
method Cs6_InvocationExpression (line 39) | [Fact]
method Cs6_InvocationWithTypeArg (line 59) | [Fact]
method Cs6_MemberAccessExpression (line 74) | [Fact]
method Cs6_GenericName (line 82) | [Fact]
method Cs6_GenericTypeArgument (line 107) | [Fact]
method Cs6_NestedType (line 116) | [Fact]
method Cs6_PointerType (line 127) | [Fact]
method Cs6_VeryComplexType (line 137) | [Fact]
method Cs6_NullableType (line 159) | [Fact]
method Cs6_EveryUserDefinedTypeKind (line 167) | [Fact]
method Cs6_ExtensionMethodInvocation (line 179) | [Fact]
method Cs6_ObjectCreationExpression (line 188) | [Fact]
method Cs6_Var (line 196) | [Fact]
method Cs6_VarWithConstructedGenericType (line 206) | [Fact]
method Cs6_Attributes (line 231) | [Fact]
method Cs6_Delegates (line 263) | [Fact]
method Cs6_ElementAccess (line 276) | [Fact]
method Cs6_StaticImport (line 296) | [Fact]
FILE: source/NsDepCop.SourceTest/Cs6_AliasQualifiedName/Cs6_AliasQualifiedName.cs
type MyEnum (line 1) | enum MyEnum {}
class MyClass (line 5) | class MyClass
FILE: source/NsDepCop.SourceTest/Cs6_ArrayType/Cs6_ArrayType.cs
class Class1 (line 5) | class Class1
method Method1 (line 9) | private void Method1()
class Class2 (line 21) | class Class2
method Method2 (line 23) | public static Class3[] Method2() { return null; }
method Method3 (line 24) | public static Class3[][] Method3() { return null; }
class Class3 (line 30) | class Class3
FILE: source/NsDepCop.SourceTest/Cs6_Attributes/Cs6_Attributes.cs
class AllowedAttributeWithTypeArg (line 12) | [AttributeUsage(AttributeTargets.All)]
method AllowedAttributeWithTypeArg (line 15) | public AllowedAttributeWithTypeArg(Type t)
class Foo2 (line 20) | [Forbidden("Attributes defined in the foreign namespace detected ok")]
class Foo3 (line 26) | [AllowedAttributeWithTypeArg(typeof(ForbiddenType))]
class Foo4 (line 31) | class Foo4
type Foo5 (line 38) | enum Foo5
class ForbiddenAttribute (line 50) | class ForbiddenAttribute : Attribute
method ForbiddenAttribute (line 52) | public ForbiddenAttribute(string s)
class ForbiddenType (line 56) | class ForbiddenType
FILE: source/NsDepCop.SourceTest/Cs6_Delegates/Cs6_Delegates.cs
class Class1 (line 10) | class Class1<T>
class Class2 (line 14) | class Class2
FILE: source/NsDepCop.SourceTest/Cs6_ElementAccess/Cs6_ElementAccess.cs
class Class1 (line 5) | class Class1
method Method1 (line 7) | public void Method1()
class Class2 (line 17) | class Class2<T>
class Class3 (line 21) | class Class3
FILE: source/NsDepCop.SourceTest/Cs6_EveryUserDefinedTypeKind/Cs6_EveryUserDefinedTypeKind.cs
class Foo (line 5) | class Foo
class MyClass (line 17) | class MyClass { }
type IMyInterface (line 18) | interface IMyInterface { }
type MyStruct (line 19) | struct MyStruct { }
type MyEnum (line 20) | enum MyEnum { }
FILE: source/NsDepCop.SourceTest/Cs6_ExtensionMethodInvocation/Cs6_ExtensionMethodInvocation.cs
class MyClass (line 5) | class MyClass
method MyMethod (line 7) | void MyMethod()
class MyClassExtensions (line 19) | static class MyClassExtensions
method MyExtensionMethod (line 21) | public static void MyExtensionMethod(this MyClass myClass)
method MyGenericExtensionMethod (line 25) | public static void MyGenericExtensionMethod<T>(this T t)
FILE: source/NsDepCop.SourceTest/Cs6_GenericName/Cs6_GenericName.cs
class MyClass (line 5) | class MyClass
class MyClass2 (line 17) | class MyClass2 { }
class MyGenericClass (line 22) | class MyGenericClass<T1> { }
class MyGenericClass2 (line 24) | class MyGenericClass2<T1, T2, T3> { }
class MyClass3 (line 26) | class MyClass3 { }
FILE: source/NsDepCop.SourceTest/Cs6_GenericTypeArgument/Cs6_GenericTypeArgument.cs
class MyClass (line 5) | class MyClass
class MyGenericClass (line 11) | class MyGenericClass<T1> { }
class MyClass2 (line 16) | class MyClass2 { }
FILE: source/NsDepCop.SourceTest/Cs6_InvocationExpression/Cs6_InvocationExpression.cs
class Class1 (line 5) | class Class1
method Method1 (line 7) | void Method1()
method Method2 (line 15) | C.Class3 Method2() { return null; }
class Class2 (line 23) | class Class2
method Method3 (line 25) | public Class3 Method3()
method Method4 (line 30) | public static Class3 Method4()
method Method5 (line 35) | public static Class4<Class3> Method5()
class Class3 (line 44) | class Class3
class Class4 (line 48) | class Class4<T>
FILE: source/NsDepCop.SourceTest/Cs6_InvocationWithTypeArg/Cs6_InvocationWithTypeArg.cs
class Class1 (line 6) | class Class1
method Method1 (line 8) | void Method1()
class Class2 (line 18) | static class Class2
method Method2 (line 20) | public static void Method2<T>()
class Class3 (line 28) | class Class3
class Class4 (line 32) | class Class4<T>
FILE: source/NsDepCop.SourceTest/Cs6_MemberAccessExpression/Cs6_MemberAccessExpression.cs
class MyClass (line 5) | class MyClass
method MyMethod (line 7) | void MyMethod()
class MyOtherClass (line 16) | static class MyOtherClass
type MyEnum (line 24) | enum MyEnum
FILE: source/NsDepCop.SourceTest/Cs6_NestedType/Cs6_NestedType.cs
class MyClass (line 5) | class MyClass
class MyClass2 (line 14) | class MyClass2
class MySubclass (line 16) | public class MySubclass { }
FILE: source/NsDepCop.SourceTest/Cs6_NullableType/Cs6_NullableType.cs
class MyClass (line 5) | class MyClass
type MyStruct (line 13) | struct MyStruct { }
FILE: source/NsDepCop.SourceTest/Cs6_ObjectCreationExpression/Cs6_ObjectCreationExpression.cs
class MyClass (line 5) | class MyClass
method MyMethod (line 7) | void MyMethod()
class MyOtherClass (line 16) | class MyOtherClass { }
FILE: source/NsDepCop.SourceTest/Cs6_PointerType/Cs6_PointerType.cs
class Class1 (line 5) | unsafe class Class1
method Method1 (line 9) | private void Method1()
class Class2 (line 21) | unsafe class Class2
method Method2 (line 23) | public static Class3* Method2() { return null; }
method Method3 (line 24) | public static Class3** Method3() { return null; }
type Class3 (line 30) | struct Class3
FILE: source/NsDepCop.SourceTest/Cs6_QualifiedName/Cs6_QualifiedName.cs
class MyClass (line 3) | class MyClass
type MyEnum (line 11) | enum MyEnum
FILE: source/NsDepCop.SourceTest/Cs6_StaticImport/Cs6_StaticImport.cs
class ClassB (line 5) | public class ClassB
method CallA (line 7) | public void CallA()
class ClassA (line 17) | public class ClassA
method IsCalledReturnsVoid (line 19) | public static void IsCalledReturnsVoid() { _ = new ClassA();}
method IsCalledReturnsClassA (line 20) | public static ClassA IsCalledReturnsClassA() { return new ClassA(); }
FILE: source/NsDepCop.SourceTest/Cs6_Var/Cs6_Var.cs
class Class1 (line 3) | public class Class1
method Method (line 5) | public void Method()
type MyEnum (line 14) | public enum MyEnum
FILE: source/NsDepCop.SourceTest/Cs6_VarWithConstructedGenericType/Cs6_VarWithConstructedGenericType.cs
class ClassA (line 3) | public class ClassA
method Method (line 5) | public void Method()
type EnumA (line 12) | public enum EnumA
type EnumB (line 19) | public enum EnumB
class ClassB (line 23) | public class ClassB<T1, T2, T3>
FILE: source/NsDepCop.SourceTest/Cs6_VeryComplexType/Cs6_VeryComplexType.cs
class Class1 (line 6) | unsafe class Class1
method Method1 (line 8) | private void Method1()
class Class2 (line 19) | unsafe class Class2
method Method2 (line 21) | public static Class4<Class3[], Class4<Class3*[], Class3[][]>> Method2(...
type Class3 (line 27) | struct Class3
class Class4 (line 31) | class Class4<T1, T2>
FILE: source/NsDepCop.SourceTest/Cs7Tests.cs
class Cs7Tests (line 11) | public class Cs7Tests
method Cs7_Out (line 13) | [Fact]
method Cs7_Tuples (line 22) | [Fact]
method Cs7_Deconstruction (line 51) | [Fact]
method Cs7_IsExpressionWithPattern (line 72) | [Fact]
method Cs7_SwitchWithPattern (line 86) | [Fact]
method Cs7_LocalFunction (line 97) | [Fact]
method Cs7_ThrowExpression (line 108) | [Fact]
FILE: source/NsDepCop.SourceTest/Cs7_1_DefaultLiteral/Cs7_1_DefaultLiteral.cs
class Class1 (line 7) | public class Class1
method M1 (line 11) | public Class2 M1(Class2 p1 = default)
class Class2 (line 22) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_1_InferredTupleNames/Cs7_1_InferredTupleNames.cs
class Class1 (line 7) | public class Class1
method M1 (line 11) | public void M1(Class2 p1)
class Class2 (line 23) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_1_Tests.cs
class Cs7_1_Tests (line 12) | public class Cs7_1_Tests
method Cs7_1_DefaultLiteral (line 14) | [Fact]
method Cs7_1_InferredTupleNames (line 39) | [Fact]
FILE: source/NsDepCop.SourceTest/Cs7_2_NonTrailingNamedArguments/Cs7_2_NonTrailingNamedArguments.cs
class Class1 (line 7) | public class Class1
method M1 (line 11) | public void M1(Class2 p1, Class2 p2)
class Class2 (line 20) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_2_Tests.cs
class Cs7_2_Tests (line 12) | public class Cs7_2_Tests
method Cs7_2_NonTrailingNamedArguments (line 14) | [Fact]
FILE: source/NsDepCop.SourceTest/Cs7_3_AttributeOnPropertyBackingField/Cs7_3_AttributeOnPropertyBackingField.cs
class Class1 (line 5) | [Serializable]
FILE: source/NsDepCop.SourceTest/Cs7_3_Tests.cs
class Cs7_3_Tests (line 12) | public class Cs7_3_Tests
method Cs7_3_AttributeOnPropertyBackingField (line 14) | [Fact]
FILE: source/NsDepCop.SourceTest/Cs7_Deconstruction/Cs7_Deconstruction.cs
class Class1 (line 8) | public class Class1
method Method (line 10) | public void Method()
method Method2 (line 27) | public Deconstructable Method2() => throw new NotImplementedException();
class Deconstructable (line 33) | public class Deconstructable
method Deconstruct (line 38) | public void Deconstruct(out Class1 class1, out Class2 class2)
class Class2 (line 48) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_IsExpressionWithPattern/Cs7_IsExpressionWithPattern.cs
class Class1 (line 5) | public class Class1
method Method (line 7) | public void Method(Class2 o)
class Class2 (line 16) | public class Class2
class Class3 (line 19) | public class Class3 : Class2
FILE: source/NsDepCop.SourceTest/Cs7_LocalFunction/Cs7_LocalFunction.cs
class Class1 (line 5) | public class Class1
method Method (line 7) | public void Method()
class Class2 (line 16) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_Out/Cs7_Out.cs
class Class1 (line 7) | public class Class1
method Method (line 9) | public void Method()
type MyEnum (line 18) | public enum MyEnum
FILE: source/NsDepCop.SourceTest/Cs7_SwitchWithPattern/Cs7_SwitchWithPattern.cs
class Class1 (line 5) | public class Class1
method Method (line 7) | public void Method(object o)
class Class2 (line 20) | public class Class2
FILE: source/NsDepCop.SourceTest/Cs7_ThrowExpression/Cs7_ThrowExpression.cs
class Class1 (line 7) | public class Class1
method Method (line 9) | public void Method() => throw new MyException();
class MyException (line 15) | public class MyException : Exception
FILE: source/NsDepCop.SourceTest/Cs7_Tuples/Cs7_Tuples.cs
class Class1 (line 7) | public class Class1
method Method1 (line 10) | public (Class1, Class2) Method1()
method Method2 (line 17) | public (Class1 class1, Class2 class2) Method2()
method Method3 (line 23) | public void Method3()
class Class2 (line 37) | public class Class2
FILE: source/NsDepCop.SourceTest/FileBasedTestsBase.cs
class FileBasedTestsBase (line 11) | public abstract class FileBasedTestsBase
method GetExecutingAssemblyDirectory (line 13) | protected static string GetExecutingAssemblyDirectory() => GetAssembly...
method GetAssemblyPath (line 15) | protected static string GetAssemblyPath(Assembly assembly)
method GetAssemblyDirectory (line 20) | protected static string GetAssemblyDirectory(Assembly assembly)
method GetBinFilePath (line 26) | protected static string GetBinFilePath(string filename)
method LoadFile (line 31) | protected string LoadFile(string fullPath)
method Rename (line 40) | protected static void Rename(string fromFilename, string toFilename)
method Delete (line 51) | protected static void Delete(string filename)
FILE: source/NsDepCop.SourceTest/SourceLineSegment.cs
type SourceLineSegment (line 5) | public readonly struct SourceLineSegment
method SourceLineSegment (line 11) | public SourceLineSegment(int line, int startColumn, int endColumn)
method Equals (line 18) | public bool Equals(SourceSegment sourceSegment)
method ToString (line 26) | public override string ToString() => $"({Line},{StartColumn}-{EndColum...
FILE: source/NsDepCop.SourceTest/SourceTestSpecification.cs
class SourceTestSpecification (line 17) | internal sealed class SourceTestSpecification : FileBasedTestsBase
method SourceTestSpecification (line 26) | private SourceTestSpecification(string name, ITypeDependencyEnumerator...
method Create (line 32) | public static SourceTestSpecification Create([CallerMemberName] string...
method ExpectInvalidSegment (line 35) | public SourceTestSpecification ExpectInvalidSegment(int line, int star...
method ExpectInvalidSegment (line 41) | public SourceTestSpecification ExpectInvalidSegment(int line, int star...
method Execute (line 48) | public void Execute(OutputKind? outputKind = null)
method DebugMessageHandler (line 57) | private static void DebugMessageHandler(string message) => Debug.Write...
method ValidateCompilation (line 59) | private void ValidateCompilation(IEnumerable<string> sourceFiles, IEnu...
method AssertIllegalDependencies (line 71) | private void AssertIllegalDependencies(IEnumerable<string> sourceFiles...
method GetIllegalDependencies (line 93) | private IEnumerable<IllegalDependencyMessage> GetIllegalDependencies(s...
method GetTestFileFullPath (line 102) | private static string GetTestFileFullPath(string testName)
method GetReferencedAssemblyPaths (line 108) | private static IEnumerable<string> GetReferencedAssemblyPaths()
FILE: source/NsDepCop.Test/FileBasedTestsBase.cs
class FileBasedTestsBase (line 11) | public abstract class FileBasedTestsBase
method GetExecutingAssemblyDirectory (line 13) | protected static string GetExecutingAssemblyDirectory() => GetAssembly...
method GetAssemblyPath (line 15) | protected static string GetAssemblyPath(Assembly assembly)
method GetAssemblyDirectory (line 20) | protected static string GetAssemblyDirectory(Assembly assembly)
method GetBinFilePath (line 26) | protected static string GetBinFilePath(string filename)
method GetFilePathInTestClassFolder (line 31) | protected string GetFilePathInTestClassFolder(string filename)
method LoadFile (line 39) | protected string LoadFile(string fullPath)
method Rename (line 48) | protected static void Rename(string fromFilename, string toFilename)
method Delete (line 59) | protected static void Delete(string filename)
FILE: source/NsDepCop.Test/Implementation/Analysis/AssemblyDependencyAnalyzerTests.cs
class AssemblyDependencyAnalyzerTests (line 15) | public class AssemblyDependencyAnalyzerTests
method NoConfig_ReturnsNoConfigMessage (line 24) | [Fact]
method ConfigDisabled_ReturnsConfigDisabledMessage (line 32) | [Fact]
method ConfigError_ReturnsConfigErrorMessage (line 40) | [Fact]
method AnalyzeProject_TwoIllegalAssemblyDependencyMessagesReturned (line 52) | [Fact]
method AnalyzeProject_NoIllegalAssemblyDependencyMessageReturned (line 65) | [Fact]
method AnalyzeProject_NoIllegalAssemblyDependencyMessageReturnedWhenAllowedAssemblyRulesDefined (line 78) | [Fact]
method AnalyzeProject_OneIllegalAssemblyDependencyMessageReturnedWhenDisallowedAssemblyRulesDefined (line 101) | [Fact]
method SetUpEnabledConfig (line 126) | private void SetUpEnabledConfig(bool checkAssemblyDependencies = true)
method AnalyzeProject (line 137) | private IEnumerable<AnalyzerMessageBase> AnalyzeProject()
method CreateDependencyAnalyzer (line 144) | private IAssemblyDependencyAnalyzer CreateDependencyAnalyzer()
FILE: source/NsDepCop.Test/Implementation/Analysis/CachingTypeDependencyValidatorTests.cs
class CachingTypeDependencyValidatorTests (line 8) | public class CachingTypeDependencyValidatorTests
method NoRule_SameNamespaceIsAlwaysAllowed (line 10) | [Fact]
method ValidatingATypeDependencyTwice_FirstCacheMissThenCacheHit (line 19) | [Fact]
method CreateCachingTypeDependencyValidator (line 35) | private static CachingTypeDependencyValidator CreateCachingTypeDepende...
FILE: source/NsDepCop.Test/Implementation/Analysis/DependencyAnalyzerTests.cs
class DependencyAnalyzerTests (line 17) | public class DependencyAnalyzerTests
method NoConfig_ReturnsNoConfigMessage (line 25) | [Fact]
method ConfigDisabled_ReturnsConfigDisabledMessage (line 34) | [Fact]
method ConfigError_ReturnsConfigErrorMessage (line 43) | [Fact]
method AnalyzeProject_TypeDependenciesReturned (line 62) | [Fact]
method AnalyzeSyntaxNode_TypeDependenciesReturned (line 74) | [Fact]
method RefreshConfig_Works (line 86) | [Fact(Skip = "MaxIssueCount temporarily not working for AnalyzeProject...
method AutoLowerMaxIssueCount_Works (line 103) | [Theory(Skip = "This feature is temporarily commented out.")]
method SetUpEnabledConfig (line 125) | private void SetUpEnabledConfig(int maxIssueCount = 100, bool autoLowe...
method AnalyzeProject (line 138) | private IEnumerable<AnalyzerMessageBase> AnalyzeProject()
method AnalyzeSyntaxNode (line 143) | private IEnumerable<AnalyzerMessageBase> AnalyzeSyntaxNode()
method CreateDependencyAnalyzer (line 152) | private IDependencyAnalyzer CreateDependencyAnalyzer()
FILE: source/NsDepCop.Test/Implementation/Analysis/DependencyRulesBuilder.cs
class DependencyRulesBuilder (line 9) | public class DependencyRulesBuilder : IDependencyRules
method DependencyRulesBuilder (line 17) | public DependencyRulesBuilder()
method SetChildCanDependOnParentImplicitly (line 38) | public DependencyRulesBuilder SetChildCanDependOnParentImplicitly(bool...
method AddAllowed (line 44) | public DependencyRulesBuilder AddAllowed(DomainSpecification from, Dom...
method AddAllowed (line 50) | public DependencyRulesBuilder AddAllowed(string from, string to, param...
method AddDisallowed (line 56) | public DependencyRulesBuilder AddDisallowed(string from, string to)
method AddAllowedAssemblyDependency (line 62) | public DependencyRulesBuilder AddAllowedAssemblyDependency(string from...
method AddDisallowedAssemblyDependency (line 68) | public DependencyRulesBuilder AddDisallowedAssemblyDependency(string f...
method AddVisibleMembers (line 74) | public DependencyRulesBuilder AddVisibleMembers(string targetNamespace...
FILE: source/NsDepCop.Test/Implementation/Analysis/TypeDependencyValidatorExtensions.cs
class TypeDependencyValidatorExtensions (line 6) | internal static class TypeDependencyValidatorExtensions
method IsAllowedDependency (line 10) | public static bool IsAllowedDependency(this TypeDependencyValidator ty...
FILE: source/NsDepCop.Test/Implementation/Analysis/TypeDependencyValidatorTests.cs
class TypeDependencyValidatorTests (line 8) | public class TypeDependencyValidatorTests
method NoRule_SameNamespaceIsAlwaysAllowed (line 10) | [Fact]
method NoRule_EverythingIsDisallowed_ExceptSameNamespace (line 19) | [Fact]
method AllowRule (line 28) | [Fact]
method AllowRule_WithSubnamespace (line 40) | [Fact]
method AllowRule_WithPrefixWildcard (line 54) | [Fact]
method AllowRule_WithSingleNamespacePrefix (line 69) | [Fact]
method AllowRule_WithWildcard (line 82) | [Fact]
method AllowRule_WithMultipleWildcards (line 98) | [Fact]
method AllowRule_WithAnyNamespace (line 112) | [Fact]
method AllowRule_MoreSpecificRuleWithWildcardsIsStronger (line 124) | [Fact]
method AllowRule_WildcardRuleIsStrongerThanRegexRule (line 136) | [Fact]
method DisallowRule_LessSpecificRuleWithWildcardsIsStronger (line 148) | [Fact]
method AllowRuleWithVisibleMembers_AffectsOnlyAllowRuleSource (line 160) | [Fact]
method AllowRule_GlobalVisibleMembers_AffectsAllRuleSources (line 177) | [Fact]
method DisallowRule (line 195) | [Fact]
method DisallowRule_StrongerThanAllowRule (line 205) | [Fact]
method DisallowRule_ButSameNamespaceShouldBeAllowed (line 216) | [Fact]
method DisallowRule_IsStrongerThanChildCanDependOnParentImplicitly (line 226) | [Fact]
method ChildCanDependOnParentImplicitly (line 237) | [Fact]
method ChildCanDependOnParentImplicitly_ButDisallowWins (line 248) | [Fact]
method ChildCanDependOnParentImplicitly_ButDisallowWins_WithWildcard (line 260) | [Fact]
method CreateTypeDependencyValidator (line 272) | private static TypeDependencyValidator CreateTypeDependencyValidator(I...
FILE: source/NsDepCop.Test/Implementation/Config/AnalyzerConfigBuilderTests.cs
class AnalyzerConfigBuilderTests (line 11) | public class AnalyzerConfigBuilderTests
method ToAnalyzerConfig_AppliesDefaults (line 13) | [Fact]
method ToAnalyzerConfig_ConvertsPathsToRooted (line 23) | [Theory]
method SetMethods_WithNonNullValues_OverwriteProperties (line 43) | [Fact]
method SetMethods_WithNullValues_DoNotOverwriteProperties (line 60) | [Fact]
method AddAllowRule_Works (line 84) | [Fact]
method AddDisallowRule_Works (line 104) | [Fact]
method AddVisibleTypesByNamespace_Works (line 124) | [Fact]
method Combine_EmptyWithEmpty (line 144) | [Fact]
method AddAllowedAssemblyRule_Works (line 162) | [Fact]
method AddDisallowedAssemblyRule_Works (line 183) | [Fact]
method Combine_NonEmptyWithEmpty (line 204) | [Fact]
method Combine_EmptyWithNonEmpty (line 233) | [Fact]
method Combine_NonEmptyWithNonEmpty (line 262) | [Fact]
FILE: source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests.cs
class MultiLevelXmlFileConfigProviderTests (line 11) | public class MultiLevelXmlFileConfigProviderTests : XmlFileConfigTestBase
method Rules_Merged (line 13) | [Fact]
method Attributes_LowerLevelWins (line 28) | [Fact]
method Attributes_MissingDoesNotOverwrite (line 36) | [Fact]
method ExcludedFiles_AllCorrectlyRooted (line 44) | [Fact]
method Properties_ConfigNotFound (line 62) | [Fact]
method Properties_ConfigError (line 72) | [Fact]
method Properties_ConfigEnabled (line 82) | [Fact]
method Properties_ConfigDisabledAtProjectLevel_EffectiveDisabled (line 92) | [Fact]
method Properties_ConfigDisabledAtHigherLevelAndUndefinedAtProjectLevel_EffectiveDisabled (line 102) | [Fact]
method Properties_ConfigDisabledAtHigherLevelButEnabledAtProjectLevel_DisabledConfigNotCombinedToEffective (line 112) | [Fact]
method RefreshConfig_Unchanged (line 122) | [Fact]
method RefreshConfig_EnabledToEnabledButChanged (line 136) | [Fact]
method RefreshConfig_EnabledToDisabled (line 158) | [Fact]
method RefreshConfig_EnabledToConfigError (line 175) | [Fact]
method RefreshConfig_NoConfigToEnabled (line 192) | [Fact]
method RefreshConfig_EnabledToNoConfig (line 208) | [Fact]
method RefreshConfig_InheritanceDepthChangedFrom0To2 (line 225) | [Fact]
method RefreshConfig_InheritanceDepthChangedFrom2To0 (line 244) | [Fact]
method UpdateMaxIssueCount_Level1ContainsNoMaxIssueCount_SetToNewValue (line 263) | [Fact]
method UpdateMaxIssueCount_Level1ContainsMaxIssueCount_SetToNewValue (line 281) | [Fact]
method GetConfigFilePath (line 299) | private static string GetConfigFilePath(string path)
method CreateConfigProvider (line 304) | private static MultiLevelXmlFileConfigProvider CreateConfigProvider(st...
FILE: source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Excluded File 4.cs
class ExcludedFile4 (line 1) | class ExcludedFile4
FILE: source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/ExcludedFile3.cs
class ExcludedFile3 (line 1) | class ExcludedFile3
FILE: source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Level1/Excluded File 2.cs
class ExcludedFile2a (line 1) | class ExcludedFile2a
FILE: source/NsDepCop.Test/Implementation/Config/MultiLevelXmlFileConfigProviderTests/ExcludedFiles_AllCorrectlyRooted/Level2/Level1/ExcludedFile1.cs
class ExcludedFile1a (line 1) | class ExcludedFile1a
FILE: source/NsDepCop.Test/Implementation/Config/XmlConfigParserTests.cs
class XmlConfigParserTests (line 10) | public class XmlConfigParserTests : FileBasedTestsBase
method Parse_NoRootAttributes (line 12) | [Fact]
method Parse_RootAttributes (line 26) | [Fact]
method Parse_AllowedRules (line 40) | [Fact]
method Parse_DisallowedRules (line 64) | [Fact]
method Parse_VisibleMembers (line 77) | [Fact]
method Parse_AllowedAssemblyRules (line 98) | [Fact]
method Parse_DisallowedAssemblyRules (line 111) | [Fact]
method Parse_AllowedRuleForWildcardNamespaceWithVisibleMembers_Throws (line 124) | [Fact]
method Parse_AllowedRuleForNamespaceWithVisibleMembersWithOfNamespaceAttribute_Throws (line 132) | [Fact]
method Parse_VisibleMembersOfNamespaceMissing_Throws (line 140) | [Fact]
method Parse_AllowedRuleFromAttributeMissing_Throws (line 148) | [Fact]
method Parse_AllowedRuleToAttributeMissing_Throws (line 156) | [Fact]
method Parse_VisibleMembersTypeNameAttributeMissing_Throws (line 164) | [Fact]
method Parse_NsDepCopConfigElementNotFound_Throws (line 172) | [Fact]
method Parse_InvalidNamespaceString_Throws (line 180) | [Fact]
method Parse_InvalidDuplicatedWildcardNamespaceString_Throws (line 188) | [Fact]
method Parse_InvalidAttributeValue_Throws (line 196) | [Fact]
method UpdateMaxIssueCount_HasMaxIssueCountAttribute_Works (line 204) | [Fact]
method UpdateMaxIssueCount_NoMaxIssueCountAttribute_Works (line 213) | [Fact]
method LoadXml (line 222) | private XDocument LoadXml(string filename)
FILE: source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests.cs
class XmlFileConfigProviderTests (line 12) | public class XmlFileConfigProviderTests : XmlFileConfigTestBase
method Properties_ConfigNotFound (line 14) | [Fact]
method Properties_ConfigEnabled (line 24) | [Fact]
method Properties_ExcludedFiles_AreRooted (line 34) | [Fact]
method Properties_ConfigDisabled (line 51) | [Fact]
method Properties_ConfigError (line 61) | [Fact]
method RefreshConfig_Unchanged (line 71) | [Fact]
method RefreshConfig_EnabledToDisabled (line 85) | [Fact]
method RefreshConfig_EnabledToConfigError (line 102) | [Fact]
method RefreshConfig_NoConfigToEnabled (line 119) | [Fact]
method RefreshConfig_EnabledToNoConfig (line 135) | [Fact]
method UpdateMaxIssueCount_DisabledConfig_Throws (line 152) | [Fact]
method UpdateMaxIssueCount_FromNoneToNewValue (line 169) | [Fact]
method UpdateMaxIssueCount_FromOldValueToNewValue (line 186) | [Fact]
method CreateConfigProvider (line 203) | private static XmlFileConfigProvider CreateConfigProvider(string path)
FILE: source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/Excluded File 2.cs
class ExcludedFile2b (line 1) | class ExcludedFile2b
FILE: source/NsDepCop.Test/Implementation/Config/XmlFileConfigProviderTests/ExcludedFile1.cs
class ExcludedFile1b (line 1) | class ExcludedFile1b
FILE: source/NsDepCop.Test/Implementation/Config/XmlFileConfigTestBase.cs
class XmlFileConfigTestBase (line 5) | public class XmlFileConfigTestBase : FileBasedTestsBase
method CreateConfigFile (line 7) | protected static void CreateConfigFile(string path, string isEnabledSt...
method GetMaxIssueCountAttributeString (line 13) | private static string GetMaxIssueCountAttributeString(int? maxIssueCount)
method GetAttribute (line 18) | protected static string GetAttribute(string path, string attributeName)
method SetAttribute (line 24) | protected static void SetAttribute(string path, string attributeName, ...
method RemoveAttribute (line 37) | protected static void RemoveAttribute(string path, string attributeName)
FILE: source/NsDepCop.Test/Interface/Config/DomainSpecificationParserTests.cs
class DomainSpecificationParserTests (line 8) | public class DomainSpecificationParserTests
method Parse_DomainSpecification (line 10) | [Theory]
method Parse_WildcardDomainSpecification (line 18) | [Theory]
method Parse_RegexDomainSpecification (line 32) | [Theory]
method Parse_Invalid (line 40) | [Theory]
FILE: source/NsDepCop.Test/Interface/Config/DomainSpecificationTests.cs
class DomainSpecificationTests (line 8) | public class DomainSpecificationTests
method GetMatchRelevance_ShouldReturnTheExpectedValue (line 10) | [Theory]
method GetMatchRelevance_ShouldPrioritizeProperly (line 54) | [Theory]
FILE: source/NsDepCop.Test/Interface/Config/DomainTests.cs
class DomainTests (line 8) | public class DomainTests
method Create_Works (line 10) | [Theory]
method Create_GlobalDomainRepresentationNormalized (line 19) | [Theory]
method Create_WithNull_ThrowsArgumentNullException (line 27) | [Fact]
method Create_AnyDomain_ThrowsFormatException (line 33) | [Theory]
method IsSubDomainOf_Works (line 41) | [Fact]
method Equals_Works (line 55) | [Fact]
method GlobalDomain_IsEqualToOtherInstanceOfGlobalDomain (line 62) | [Fact]
FILE: source/NsDepCop.Test/Interface/Config/RegexDomainTests.cs
class RegexDomainTests (line 9) | public sealed class RegexDomainTests
method Create_Works (line 11) | [Theory]
method Create_WithNull_ThrowsArgumentNullException (line 19) | [Fact]
method Create_InvalidRegexDomain_ThrowsFormatException (line 26) | [Theory]
method Equals_Works (line 39) | [Fact]
method GetMatchRelevance_WhenTimeoutOccurs_ShouldReturnNoMatch_WithoutThrowingException (line 47) | [Fact]
FILE: source/NsDepCop.Test/Interface/Config/WildcardDomainTests.cs
class WildcardDomainTests (line 9) | public class WildcardDomainTests
method Create_Works (line 11) | [Theory]
method Create_WithNull_ThrowsArgumentNullException (line 24) | [Fact]
method Create_NotAWildcardDomain_ThrowsFormatException (line 30) | [Theory]
method Create_InvalidWildcardDomain_ThrowsFormatException (line 38) | [Theory]
method Equals_Works (line 53) | [Fact]
method AnyDomain_IsEqualToOtherInstanceOfAnyDomain (line 61) | [Fact]
FILE: source/NsDepCop.Test/RoslynAnalyzer/AnalyzerProviderTests.cs
class AnalyzerProviderTests (line 9) | public class AnalyzerProviderTests
method AnalyzerProviderTests (line 16) | public AnalyzerProviderTests()
method GetDependencyAnalyzer_RetrievedOnce_CallsFactory (line 24) | [Fact]
method GetDependencyAnalyzer_RetrievedTwice_CallsFactoryThenAnalyzerRefresh (line 36) | [Fact]
method GetAssemblyDependencyAnalyzer_RetrievedTwice_CallsFactoryThenAnalyzerRefresh (line 55) | [Fact]
method SetUpFactoryCall (line 74) | private void SetUpFactoryCall(IDependencyAnalyzer analyzer)
method VerifyDependencyAnalyzerFactoryCall (line 81) | private void VerifyDependencyAnalyzerFactoryCall(Times times)
method VerifyAssemblyDependencyAnalyzerFactoryCall (line 87) | private void VerifyAssemblyDependencyAnalyzerFactoryCall(Times times)
method SetUpFactoryCall (line 92) | private void SetUpFactoryCall(IAssemblyDependencyAnalyzer analyzer)
method CreateAnalyzerProvider (line 99) | private IAnalyzerProvider CreateAnalyzerProvider()
Condensed preview — 297 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (527K chars).
[
{
"path": ".gitignore",
"chars": 3130,
"preview": "## Ignore Visual Studio temporary files, build results, and\r\n## files generated by popular Visual Studio add-ons.\r\n\r\n# U"
},
{
"path": "CHANGELOG.md",
"chars": 6720,
"preview": "# NsDepCop Change Log\n\n## v2.7.0\n(12/2025)\n\n- [x] Perf: Avoids unnecessary rebuilds when only a solution-level config.ns"
},
{
"path": "CLAUDE.md",
"chars": 5367,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "Contribute.md",
"chars": 513,
"preview": "## How to build the source\n1. Prerequisites\n * Visual Studio 2019 or later (16.10.0 or later, any edition)\n * With"
},
{
"path": "LICENSE",
"chars": 18047,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "README.md",
"chars": 2066,
"preview": "# NsDepCop - Namespace and Assembly Dependency Checker Tool for C# #\n\nNsDepCop is a static code analysis tool that enfor"
},
{
"path": "appveyor.yml",
"chars": 888,
"preview": "image: Visual Studio 2022\n\nenvironment:\n shortversion: '2.7.0'\n informationalversion: '2.7.0'\n\nversion: '$(shortversio"
},
{
"path": "doc/DependencyControl.md",
"chars": 3766,
"preview": "# Dependency Control\n\n## Why Care About Code Dependencies?\nThe number one enemy of a developer is complexity.\n\nAmong the"
},
{
"path": "doc/Diagnostics.md",
"chars": 2299,
"preview": "# NsDepCop Diagnostics Reference\n\n### NSDEPCOP01\n\nTitle|Illegal namespace reference.\n:-|:-\nDefault Severity|Warning\nExpl"
},
{
"path": "doc/Help.md",
"chars": 20239,
"preview": "# NsDepCop Help\n\n* [Supported project types](#supported-project-types)\n* [Dependency rules](#dependency-rules)\n* [Config"
},
{
"path": "doc/Troubleshooting.md",
"chars": 2296,
"preview": "# NsDepCop Troubleshooting\n\n* [Exception: Unable to communicate with NsDepCop service](#item5)\n* [NsDepCop NuGet package"
},
{
"path": "source/.editorconfig",
"chars": 298,
"preview": "root = true\n\n[*.cs]\n\n# Default severity for analyzer diagnostics with category 'MicrosoftCodeAnalysisReleaseTracking'\nd"
},
{
"path": "source/Directory.Build.targets",
"chars": 710,
"preview": "<Project>\n\n <!--Begin: Avoid cycle error when package builds itself-->\n <Choose>\n <When Condition=\"$(AvoidCycleErr"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/AssemblyDependency.cs",
"chars": 1788,
"preview": "using System;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n [Serializable]\n public struc"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Factory/AssemblyDependencyAnalyzerFactory.cs",
"chars": 419,
"preview": "using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis."
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Factory/DependencyAnalyzerFactory.cs",
"chars": 826,
"preview": "using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespa"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzer.cs",
"chars": 1068,
"preview": "using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Conf"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/IAssemblyDependencyAnalyzerFactory.cs",
"chars": 228,
"preview": "using Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n public interface IAssemblyDependencyAnalyze"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzer.cs",
"chars": 1930,
"preview": "using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Codartis.NsDepCop.Conf"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/IDependencyAnalyzerFactory.cs",
"chars": 346,
"preview": "using Codartis.NsDepCop.Config;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n /// <summary>\n /// Creates dependency an"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/ITypeDependencyEnumerator.cs",
"chars": 1746,
"preview": "using System.Collections.Generic;\nusing DotNet.Globbing;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.Anal"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyAnalyzer.cs",
"chars": 5352,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Cod"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/AssemblyDependencyValidator.cs",
"chars": 2228,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDep"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/CachingTypeDependencyValidator.cs",
"chars": 1896,
"preview": "using System.Collections.Concurrent;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis."
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/DependencyAnalyzer.cs",
"chars": 7110,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis.Messages;\nusing Cod"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/DependencyStatus.cs",
"chars": 662,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Analysis.Implementation\n{\n public class DependencyStatus\n {\n pr"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/IAssemblyDependencyValidator.cs",
"chars": 203,
"preview": "namespace Codartis.NsDepCop.Analysis.Implementation\n{\n public interface IAssemblyDependencyValidator\n {\n D"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/ITypeDependencyValidator.cs",
"chars": 591,
"preview": "namespace Codartis.NsDepCop.Analysis.Implementation\n{\n /// <summary>\n /// Determines whether a type-to-type depen"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/IllegalTypeDependency.cs",
"chars": 426,
"preview": "namespace Codartis.NsDepCop.Analysis.Implementation\n{\n public class IllegalTypeDependency\n {\n public TypeD"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Implementation/TypeDependencyValidator.cs",
"chars": 4649,
"preview": "using System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Config;\nusing Codartis.NsDepCop.Util;\n\nnam"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/AnalyzerMessageBase.cs",
"chars": 224,
"preview": "namespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// Abstract base class for messages returned by "
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/ConfigDisabledMessage.cs",
"chars": 243,
"preview": "namespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// A message indicating that analysis was disabl"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/ConfigErrorMessage.cs",
"chars": 387,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// A message that describes a con"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/IllegalAssemblyDependencyMessage.cs",
"chars": 392,
"preview": "namespace Codartis.NsDepCop.Analysis.Messages\n{\n public sealed class IllegalAssemblyDependencyMessage : AnalyzerMess"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/IllegalDependencyMessage.cs",
"chars": 605,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// A message containing an illega"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/NoConfigFileMessage.cs",
"chars": 251,
"preview": "namespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// A message indicating that no config file was "
},
{
"path": "source/NsDepCop.Analyzer/Analysis/Messages/ToolDisabledMessage.cs",
"chars": 248,
"preview": "namespace Codartis.NsDepCop.Analysis.Messages\n{\n /// <summary>\n /// A message indicating that analysis was disabl"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/SourceSegment.cs",
"chars": 1485,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n /// <summary>\n /// Describes a certain segment of a source"
},
{
"path": "source/NsDepCop.Analyzer/Analysis/TypeDependency.cs",
"chars": 3454,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Analysis\n{\n /// <summary>\n /// Describes a dependency between two type"
},
{
"path": "source/NsDepCop.Analyzer/Config/AnalyzerConfigState.cs",
"chars": 262,
"preview": "namespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Enumerates the possible states of an analyzer's config.\n"
},
{
"path": "source/NsDepCop.Analyzer/Config/ConfigDefaults.cs",
"chars": 579,
"preview": "namespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Defines the default values of the config properties.\n "
},
{
"path": "source/NsDepCop.Analyzer/Config/DependencyRule.cs",
"chars": 2900,
"preview": "using System;\nusing System.Text;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Represents a dependenc"
},
{
"path": "source/NsDepCop.Analyzer/Config/Domain.cs",
"chars": 3458,
"preview": "using System;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Represents a domain, e"
},
{
"path": "source/NsDepCop.Analyzer/Config/DomainSpecification.cs",
"chars": 3005,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Represents a domain or a domain pattern. "
},
{
"path": "source/NsDepCop.Analyzer/Config/DomainSpecificationParser.cs",
"chars": 1215,
"preview": "namespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Converts a string to a domain specification.\n /// </su"
},
{
"path": "source/NsDepCop.Analyzer/Config/Factory/ConfigProviderFactory.cs",
"chars": 889,
"preview": "using Codartis.NsDepCop.Config.Implementation;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Factor"
},
{
"path": "source/NsDepCop.Analyzer/Config/IAnalyzerConfig.cs",
"chars": 1251,
"preview": "using Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// The configuration for an a"
},
{
"path": "source/NsDepCop.Analyzer/Config/IConfigProvider.cs",
"chars": 925,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Provides config info and config state fro"
},
{
"path": "source/NsDepCop.Analyzer/Config/IConfigProviderFactory.cs",
"chars": 919,
"preview": "namespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Creates config provider objects.\n /// </summary>\n "
},
{
"path": "source/NsDepCop.Analyzer/Config/IDependencyRules.cs",
"chars": 1690,
"preview": "using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Describes dependency "
},
{
"path": "source/NsDepCop.Analyzer/Config/IUpdateableConfigProvider.cs",
"chars": 507,
"preview": "namespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Provides config info and config state. Some config data "
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfig.cs",
"chars": 3143,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /// <summary>\n "
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/AnalyzerConfigBuilder.cs",
"chars": 10510,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Util;\n\nnames"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/ConfigLoadResult.cs",
"chars": 2114,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /// <summary>\n"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/ConfigProviderBase.cs",
"chars": 3308,
"preview": "using System;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /// <summary>\n "
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/FileConfigProviderBase.cs",
"chars": 2979,
"preview": "using System;\nusing System.IO;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/MultiLevelXmlFileConfigProvider.cs",
"chars": 7059,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Util;\n\nname"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/RuleConfigToStringsFormatter.cs",
"chars": 1299,
"preview": "using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /// <summary>\n /// Static"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/XmlConfigParser.cs",
"chars": 13424,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Xml;\nusing Sys"
},
{
"path": "source/NsDepCop.Analyzer/Config/Implementation/XmlFileConfigProvider.cs",
"chars": 1243,
"preview": "using System.Xml.Linq;\nusing Codartis.NsDepCop.Util;\n\nnamespace Codartis.NsDepCop.Config.Implementation\n{\n /// <summ"
},
{
"path": "source/NsDepCop.Analyzer/Config/RegexCompilationMode.cs",
"chars": 103,
"preview": "namespace Codartis.NsDepCop.Config;\n\npublic enum RegexCompilationMode\n{\n Compiled,\n Interpreted\n}"
},
{
"path": "source/NsDepCop.Analyzer/Config/RegexDomain.cs",
"chars": 2728,
"preview": "using System;\nusing System.Text.RegularExpressions;\n\nnamespace Codartis.NsDepCop.Config;\n\n/// <summary>\n/// Represents a"
},
{
"path": "source/NsDepCop.Analyzer/Config/RegexUsageMode.cs",
"chars": 92,
"preview": "namespace Codartis.NsDepCop.Config;\n\npublic enum RegexUsageMode\n{\n Static,\n Instance\n}"
},
{
"path": "source/NsDepCop.Analyzer/Config/TypeNameSet.cs",
"chars": 731,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.Serialization;\n\nnamespace Codar"
},
{
"path": "source/NsDepCop.Analyzer/Config/WildcardDomain.cs",
"chars": 6165,
"preview": "using System;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Config\n{\n /// <summary>\n /// Represents a domain sp"
},
{
"path": "source/NsDepCop.Analyzer/GlobalSettings.cs",
"chars": 454,
"preview": "using System;\n\nnamespace Codartis.NsDepCop\n{\n public static class GlobalSettings\n {\n public static bool Is"
},
{
"path": "source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj",
"chars": 1068,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n <RootNam"
},
{
"path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/ISyntaxNodeAnalyzer.cs",
"chars": 715,
"preview": "using System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.Ns"
},
{
"path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeAnalyzer.cs",
"chars": 10716,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.Co"
},
{
"path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/SyntaxNodeExtensions.cs",
"chars": 1448,
"preview": "using System;\nusing System.Linq;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp.Syntax;\n\nnamespace C"
},
{
"path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumerator.cs",
"chars": 4496,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nu"
},
{
"path": "source/NsDepCop.Analyzer/ParserAdapter/Roslyn/TypeDependencyEnumeratorSyntaxVisitor.cs",
"chars": 3251,
"preview": "using System;\nusing System.Collections.Generic;\nusing Codartis.NsDepCop.Analysis;\nusing Microsoft.CodeAnalysis;\nusing M"
},
{
"path": "source/NsDepCop.Analyzer/ProductConstants.cs",
"chars": 498,
"preview": "using System.Reflection;\n\nnamespace Codartis.NsDepCop\n{\n /// <summary>\n /// Product-wide constant values.\n ///"
},
{
"path": "source/NsDepCop.Analyzer/Properties/AssemblyInfo.cs",
"chars": 203,
"preview": "using System.Reflection;\n\n[assembly: AssemblyTitle(\"NsDepCop.Analyzer\")]\n[assembly: AssemblyDescription(\"Static code an"
},
{
"path": "source/NsDepCop.Analyzer/RoslynAnalyzer/AnalyzerProvider.cs",
"chars": 3970,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.IO;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsD"
},
{
"path": "source/NsDepCop.Analyzer/RoslynAnalyzer/DiagnosticDefinitions.cs",
"chars": 4821,
"preview": "using System.Globalization;\nusing Microsoft.CodeAnalysis;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n /// <summary"
},
{
"path": "source/NsDepCop.Analyzer/RoslynAnalyzer/IAnalyzerProvider.cs",
"chars": 686,
"preview": "using Codartis.NsDepCop.Analysis;\n\nnamespace Codartis.NsDepCop.RoslynAnalyzer\n{\n /// <summary>\n /// Provides confi"
},
{
"path": "source/NsDepCop.Analyzer/RoslynAnalyzer/NsDepCopAnalyzer.cs",
"chars": 11108,
"preview": "using System;\nusing System.Collections.Immutable;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing S"
},
{
"path": "source/NsDepCop.Analyzer/Util/ConcurrentDictionaryExtensions.cs",
"chars": 1595,
"preview": "using System;\nusing System.Collections.Concurrent;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Extens"
},
{
"path": "source/NsDepCop.Analyzer/Util/DictionaryExtensions.cs",
"chars": 1948,
"preview": "using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Stat"
},
{
"path": "source/NsDepCop.Analyzer/Util/EnumerableExtensions.cs",
"chars": 3205,
"preview": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <su"
},
{
"path": "source/NsDepCop.Analyzer/Util/ICacheStatistics.cs",
"chars": 282,
"preview": "namespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Provides cache efficiency statistics.\n /// </summary>\n "
},
{
"path": "source/NsDepCop.Analyzer/Util/IDateTimeProvider.cs",
"chars": 387,
"preview": "using System;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Provides date and time information.\n ///"
},
{
"path": "source/NsDepCop.Analyzer/Util/IDiagnosticSupport.cs",
"chars": 363,
"preview": "using System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Provides diagnostic sup"
},
{
"path": "source/NsDepCop.Analyzer/Util/IndentHelper.cs",
"chars": 708,
"preview": "using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Stat"
},
{
"path": "source/NsDepCop.Analyzer/Util/LinqExtensions.cs",
"chars": 2983,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Codartis.NsDepCop.Util\n{\n public static class LinqExtensi"
},
{
"path": "source/NsDepCop.Analyzer/Util/MathHelper.cs",
"chars": 425,
"preview": "namespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// Static helper class for simple math operations.\n /// </s"
},
{
"path": "source/NsDepCop.Analyzer/Util/MessageHandler.cs",
"chars": 232,
"preview": "namespace Codartis.NsDepCop.Util\n{\n /// <summary>\n /// A delegate that receives a string message.\n /// </summa"
},
{
"path": "source/NsDepCop.Analyzer/config.nsdepcop",
"chars": 1084,
"preview": "<NsDepCopConfig InheritanceDepth=\"1\">\n\t<Allowed From=\"Codartis.NsDepCop.*\" To=\"DotNet.Globbing\" />\n\t<Allowed From=\"Coda"
},
{
"path": "source/NsDepCop.Benchmarks/NsDepCop.Benchmarks.RuleTypesBenchmarks-report-github.md",
"chars": 1923,
"preview": "```\n\nBenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.5608/22H2/2022Update)\nIntel Core i7-10850H CPU 2.70GHz, 1 CPU, 12 l"
},
{
"path": "source/NsDepCop.Benchmarks/NsDepCop.Benchmarks.csproj",
"chars": 703,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>Exe</OutputType>\n\t\t<TargetFramework>net8.0</TargetFra"
},
{
"path": "source/NsDepCop.Benchmarks/Program.cs",
"chars": 196,
"preview": "using BenchmarkDotNet.Running;\n\nnamespace NsDepCop.Benchmarks;\n\npublic class Program\n{\n public static void Main(stri"
},
{
"path": "source/NsDepCop.Benchmarks/RuleTypesBenchmarks.cs",
"chars": 3437,
"preview": "using System.Text.RegularExpressions;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Order;\nusing Codartis.NsD"
},
{
"path": "source/NsDepCop.Benchmarks/readme.txt",
"chars": 289,
"preview": "How to run the benchmarks?\n\n1. Build the solution with Release config.\n2. Run the NsDepCop.Benchmarks project.\n3. Compar"
},
{
"path": "source/NsDepCop.ConfigSchema/NsDepCopCatalog.xml",
"chars": 213,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SchemaCatalog xmlns=\"http://schemas.microsoft.com/xsd/catalog\">\n <Association e"
},
{
"path": "source/NsDepCop.ConfigSchema/NsDepCopConfig.xsd",
"chars": 11173,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\"\n "
},
{
"path": "source/NsDepCop.NuGet/NsDepCop.NuGet.csproj",
"chars": 2695,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n <Include"
},
{
"path": "source/NsDepCop.NuGet/tools/install.ps1",
"chars": 14364,
"preview": "param($installPath, $toolsPath, $package, $project)\n\nif($project.Object.SupportsPackageDependencyResolution)\n{\n if($p"
},
{
"path": "source/NsDepCop.NuGet/tools/uninstall.ps1",
"chars": 14493,
"preview": "param($installPath, $toolsPath, $package, $project)\n\nif($project.Object.SupportsPackageDependencyResolution)\n{\n if($p"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeatureTests.cs",
"chars": 3208,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests analyzer features on source file"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_AllowedDependency/AnalyzerFeature_AllowedDependency.cs",
"chars": 237,
"preview": "namespace A\n{\n public class NoIssue\n {\n private B.MyEnum field1;\n private MyGlobalEnum field2;\n "
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_AllowedDependency/config.nsdepcop",
"chars": 177,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\".\" />\n <Allowed From=\"A\" To=\"Syste"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ChildCanDependOnParentImplicitly/AnalyzerFeature_ChildCanDependOnParentImplicitly.cs",
"chars": 203,
"preview": "namespace A.B\n{\n public class NoIssue\n {\n private A.MyEnum field1;\n private MyGlobalEnum field2;\n "
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ChildCanDependOnParentImplicitly/config.nsdepcop",
"chars": 97,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig ChildCanDependOnParentImplicitly=\"true\"/>"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_DisallowedDependency/AnalyzerFeature_DisallowedDependency.cs",
"chars": 237,
"preview": "namespace A\n{\n public class NoIssue\n {\n private B.MyEnum field1;\n private MyGlobalEnum field2;\n "
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_DisallowedDependency/config.nsdepcop",
"chars": 219,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" /> \n <Disallowed From=\"*\" To=\"."
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles/AnalyzerFeature_ExcludedFiles.cs",
"chars": 139,
"preview": "namespace A\n{\n public class MyClass\n {\n private B.MyEnum field1;\n }\n}\n\nnamespace B\n{\n public enum My"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles/config.nsdepcop",
"chars": 84,
"preview": "<NsDepCopConfig ExcludedFiles=\"AnalyzerFeature_ExcludedFiles.cs\">\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles_WithWildcard/AnalyzerFeature_ExcludedFiles_WithWildcard.cs",
"chars": 139,
"preview": "namespace A\n{\n public class MyClass\n {\n private B.MyEnum field1;\n }\n}\n\nnamespace B\n{\n public enum My"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ExcludedFiles_WithWildcard/config.nsdepcop",
"chars": 56,
"preview": "<NsDepCopConfig ExcludedFiles=\"*.cs\">\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ParentCanDependOnChildImplicitly/AnalyzerFeature_ParentCanDependOnChildImplicitly.cs",
"chars": 199,
"preview": "public class NoIssue\n{\n private A.MyEnum field1;\n private A.B.MyGlobalEnum field2;\n}\n\nnamespace A\n{\n public en"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_ParentCanDependOnChildImplicitly/config.nsdepcop",
"chars": 97,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig ParentCanDependOnChildImplicitly=\"true\"/>"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined.cs",
"chars": 166,
"preview": "namespace A\n{\n public class NoIssue\n {\n private A.MyEnum field;\n }\n\n public enum MyEnum\n { }\n\n "
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAllowedEvenWhenVisibleMembersDefined/config.nsdepcop",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <VisibleMembers OfNamespace=\"A\">\n <Type Name=\"OnlyTy"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_SameNamespaceAlwaysAllowed/AnalyzerFeature_SameNamespaceAlwaysAllowed.cs",
"chars": 117,
"preview": "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",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfAllowedRule/AnalyzerFeature_VisibleMembersOfAllowedRule.cs",
"chars": 897,
"preview": "namespace A\n{\n public class MyClass\n {\n private C.VisibleType field1;\n private C.InvisibleType fiel"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfAllowedRule/config.nsdepcop",
"chars": 301,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n\n <Allowed From=\"A\" To=\"C\" >\n <VisibleMembers>\n "
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfNamespace/AnalyzerFeature_VisibleMembersOfNamespace.cs",
"chars": 897,
"preview": "namespace A\n{\n public class MyClass\n {\n private C.VisibleType field1;\n private C.InvisibleType fiel"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_VisibleMembersOfNamespace/config.nsdepcop",
"chars": 291,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n\n <Allowed From=\"A\" To=\"C\" />\n <Allowed From=\"B\" To=\"C\" /"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_WithTopLevelStatement/AnalyzerFeature_WithTopLevelStatement.cs",
"chars": 20,
"preview": "System.Type field3;"
},
{
"path": "source/NsDepCop.SourceTest/AnalyzerFeature_WithTopLevelStatement/config.nsdepcop",
"chars": 74,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6Tests.cs",
"chars": 9554,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests that the analyzer handles variou"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_AliasQualifiedName/Cs6_AliasQualifiedName.cs",
"chars": 97,
"preview": "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",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ArrayType/Cs6_ArrayType.cs",
"chars": 426,
"preview": "namespace A\n{\n using B;\n\n class Class1\n {\n private C.Class3[] e;\n\n private void Method1()\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ArrayType/config.nsdepcop",
"chars": 138,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"B\" />\n <Allowed From=\"B\" To=\"C\" />"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_Attributes/Cs6_Attributes.cs",
"chars": 1327,
"preview": "using System;\n\n// not analyzed: [assembly: A.AllowedAttributeWithTypeArg(typeof(B.ForbiddenType))]\n// not analyzed: [mo"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_Attributes/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 158,
"preview": "namespace A\n{\n using B;\n\n delegate Class1<Class2> Delegate1(Class2 c);\n}\n\nnamespace B\n{\n class Class1<T>\n {"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_Delegates/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ElementAccess/Cs6_ElementAccess.cs",
"chars": 257,
"preview": "namespace A\n{\n using B;\n\n class Class1\n {\n public void Method1()\n {\n var a = new Clas"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ElementAccess/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_EveryUserDefinedTypeKind/Cs6_EveryUserDefinedTypeKind.cs",
"chars": 351,
"preview": "namespace A\n{\n using B;\n\n class Foo\n {\n private MyClass x1;\n private IMyInterface x2;\n pr"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_EveryUserDefinedTypeKind/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ExtensionMethodInvocation/Cs6_ExtensionMethodInvocation.cs",
"chars": 460,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n void MyMethod()\n {\n new MyClass().MyExten"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ExtensionMethodInvocation/config.nsdepcop",
"chars": 143,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"System\" />\n <Allowed From=\"B\" To=\""
},
{
"path": "source/NsDepCop.SourceTest/Cs6_GenericName/Cs6_GenericName.cs",
"chars": 558,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n // Generic type is not allowed\n private MyGenericCla"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_GenericName/config.nsdepcop",
"chars": 74,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_GenericTypeArgument/Cs6_GenericTypeArgument.cs",
"chars": 229,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n private MyGenericClass<MyClass2> e1;\n private A.MyGe"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_GenericTypeArgument/config.nsdepcop",
"chars": 74,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_InvocationExpression/Cs6_InvocationExpression.cs",
"chars": 664,
"preview": "namespace A\n{\n using B;\n\n class Class1\n {\n void Method1()\n {\n Method2();\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs6_InvocationExpression/config.nsdepcop",
"chars": 172,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"System\"/>\n <Allowed From=\"A\" To=\"B"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_InvocationWithTypeArg/Cs6_InvocationWithTypeArg.cs",
"chars": 392,
"preview": "namespace A\n{\n using B;\n using C;\n\n class Class1\n {\n void Method1()\n {\n Class2.Met"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_InvocationWithTypeArg/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"System\"/>\n <Allowed From=\"A\" To=\"B"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_MemberAccessExpression/Cs6_MemberAccessExpression.cs",
"chars": 327,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n void MyMethod()\n {\n object o = MyOtherCla"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_MemberAccessExpression/config.nsdepcop",
"chars": 172,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"System\"/>\n <Allowed From=\"A\" To=\"B"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_NestedType/Cs6_NestedType.cs",
"chars": 228,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n private MyClass2.MySubclass e1;\n private B.MyClass2."
},
{
"path": "source/NsDepCop.SourceTest/Cs6_NestedType/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_NullableType/Cs6_NullableType.cs",
"chars": 131,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n private MyStruct? e;\n }\n}\n\nnamespace B\n{\n struct MySt"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_NullableType/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ObjectCreationExpression/Cs6_ObjectCreationExpression.cs",
"chars": 183,
"preview": "namespace A\n{\n using B;\n\n class MyClass\n {\n void MyMethod()\n {\n new MyOtherClass();\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs6_ObjectCreationExpression/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_PointerType/Cs6_PointerType.cs",
"chars": 437,
"preview": "namespace A\n{\n using B;\n\n unsafe class Class1\n {\n private C.Class3* e;\n\n private void Method1()\n"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_PointerType/config.nsdepcop",
"chars": 138,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"B\" />\n <Allowed From=\"B\" To=\"C\" />"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_QualifiedName/Cs6_QualifiedName.cs",
"chars": 120,
"preview": "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",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_StaticImport/Cs6_StaticImport.cs",
"chars": 520,
"preview": "namespace B\n{\n using static A.ClassA;\n\n public class ClassB\n {\n public void CallA()\n {\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs6_StaticImport/config.nsdepcop",
"chars": 145,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"B.*\" To=\""
},
{
"path": "source/NsDepCop.SourceTest/Cs6_Var/Cs6_Var.cs",
"chars": 213,
"preview": "namespace A\n{\n public class Class1\n {\n public void Method()\n {\n var a = B.MyEnum.EnumVal"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_Var/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_VarWithConstructedGenericType/Cs6_VarWithConstructedGenericType.cs",
"chars": 471,
"preview": "namespace A\n{\n public class ClassA\n {\n public void Method()\n {\n // var and Instance shou"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_VarWithConstructedGenericType/config.nsdepcop",
"chars": 57,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig/>"
},
{
"path": "source/NsDepCop.SourceTest/Cs6_VeryComplexType/Cs6_VeryComplexType.cs",
"chars": 462,
"preview": "namespace A\n{\n using B;\n using C;\n\n unsafe class Class1\n {\n private void Method1()\n {\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs6_VeryComplexType/config.nsdepcop",
"chars": 138,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"A\" To=\"B\" />\n <Allowed From=\"B\" To=\"C\" />"
},
{
"path": "source/NsDepCop.SourceTest/Cs7Tests.cs",
"chars": 3613,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests that the analyzer handles variou"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_1_DefaultLiteral/Cs7_1_DefaultLiteral.cs",
"chars": 406,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n // https://github.com/dotnet/csharplan"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_1_DefaultLiteral/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"A\" To=\"B\""
},
{
"path": "source/NsDepCop.SourceTest/Cs7_1_InferredTupleNames/Cs7_1_InferredTupleNames.cs",
"chars": 440,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n // https://github.com/dotnet/csharplan"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_1_InferredTupleNames/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"A\" To=\"B\""
},
{
"path": "source/NsDepCop.SourceTest/Cs7_1_Tests.cs",
"chars": 1601,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests that the analyzer handles variou"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_2_NonTrailingNamedArguments/Cs7_2_NonTrailingNamedArguments.cs",
"chars": 341,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n // https://github.com/dotnet/csharplan"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_2_NonTrailingNamedArguments/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"A\" To=\"B\""
},
{
"path": "source/NsDepCop.SourceTest/Cs7_2_Tests.cs",
"chars": 854,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests that the analyzer handles variou"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_3_AttributeOnPropertyBackingField/Cs7_3_AttributeOnPropertyBackingField.cs",
"chars": 157,
"preview": "using System;\n\nnamespace A\n{\n [Serializable]\n public class Class1\n {\n [field: NonSerialized]\n pu"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_3_AttributeOnPropertyBackingField/config.nsdepcop",
"chars": 74,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n</NsDepCopConfig>"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_3_Tests.cs",
"chars": 742,
"preview": "using Xunit;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n /// <summary>\n /// Tests that the analyzer handles variou"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_Deconstruction/Cs7_Deconstruction.cs",
"chars": 963,
"preview": "using System;\nusing A;\nusing B;\nusing C;\n\nnamespace A\n{\n public class Class1\n {\n public void Method()\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs7_Deconstruction/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"A\" To=\"C\""
},
{
"path": "source/NsDepCop.SourceTest/Cs7_IsExpressionWithPattern/Cs7_IsExpressionWithPattern.cs",
"chars": 258,
"preview": "namespace A\n{\n using B;\n\n public class Class1\n {\n public void Method(Class2 o)\n {\n if"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_IsExpressionWithPattern/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 221,
"preview": "namespace A\n{\n using B;\n\n public class Class1\n {\n public void Method()\n {\n Class2 Loc"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_LocalFunction/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 256,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n public void Method()\n {\n "
},
{
"path": "source/NsDepCop.SourceTest/Cs7_Out/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 306,
"preview": "namespace A\n{\n using B;\n\n public class Class1\n {\n public void Method(object o)\n {\n sw"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_SwitchWithPattern/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 204,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n public void Method() => throw new MyEx"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_ThrowExpression/config.nsdepcop",
"chars": 111,
"preview": "<?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",
"chars": 795,
"preview": "using System;\n\nnamespace A\n{\n using B;\n\n public class Class1\n {\n // Tuple return type\n public (C"
},
{
"path": "source/NsDepCop.SourceTest/Cs7_Tuples/config.nsdepcop",
"chars": 141,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<NsDepCopConfig>\n <Allowed From=\"*\" To=\"*\" />\n <Disallowed From=\"A\" To=\"B\""
},
{
"path": "source/NsDepCop.SourceTest/FileBasedTestsBase.cs",
"chars": 1867,
"preview": "using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace Codartis.NsDepCop.SourceTest"
},
{
"path": "source/NsDepCop.SourceTest/NsDepCop.SourceTest.csproj",
"chars": 18278,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net8.0</TargetFramework>\n <RootNamespace>C"
},
{
"path": "source/NsDepCop.SourceTest/Properties/AssemblyInfo.cs",
"chars": 169,
"preview": "using System.Reflection;\n\n[assembly: AssemblyTitle(\"NsDepCop.Analyzer.SourceTest\")]\n[assembly: AssemblyDescription(\"Tes"
},
{
"path": "source/NsDepCop.SourceTest/SourceLineSegment.cs",
"chars": 821,
"preview": "using Codartis.NsDepCop.Analysis;\n\nnamespace Codartis.NsDepCop.SourceTest\n{\n public readonly struct SourceLineSegmen"
},
{
"path": "source/NsDepCop.SourceTest/SourceTestSpecification.cs",
"chars": 5322,
"preview": "using System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.Co"
},
{
"path": "source/NsDepCop.Test/FileBasedTestsBase.cs",
"chars": 2230,
"preview": "using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace Codartis.NsDepCop.Test\n{\n "
},
{
"path": "source/NsDepCop.Test/Implementation/Analysis/AssemblyDependencyAnalyzerTests.cs",
"chars": 5735,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsD"
},
{
"path": "source/NsDepCop.Test/Implementation/Analysis/CachingTypeDependencyValidatorTests.cs",
"chars": 1578,
"preview": "using Codartis.NsDepCop.Analysis.Implementation;\nusing Codartis.NsDepCop.Config;\nusing FluentAssertions;\nusing Xunit;\n\n"
},
{
"path": "source/NsDepCop.Test/Implementation/Analysis/DependencyAnalyzerTests.cs",
"chars": 7309,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Codartis.NsDepCop.Analysis;\nusing Codartis.NsD"
}
]
// ... and 97 more files (download for full content)
About this extraction
This page contains the full source code of the realvizu/NsDepCop GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 297 files (468.7 KB), approximately 131.1k tokens, and a symbol index with 774 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.