It is conventional to name namespaces in a C# solution such that they match the default namespace for the project plus the name of any sub-directories for the containing file.
For example, a file called Haddock.cs
is in a directory called Fish
and the default namespace (in the first tab of the project's properties in VS) is Lakes
then the file should contain something like
namespace Lakes.Fish
{
public class Haddock
{
}
}
The StyleCop analyzers project contains a nice rule that validates that the class name matches the file name.
Is there any way I can write a rule that verifies that the namespace name is correct?
You can access the file path from a SyntaxTreeAction
using the Tree.FilePath
off of the SyntaxTreeContext
.
Once you have the path, you can then parse that and compare it with the name of all of the Names of the NamesSpaceDeclarationSyntax
nodes in the tree.
Unfortunately, I do not think there is a way to get at the default namespace for a project at this time.
Here is a quick sample I threw together that does what it can so far. The processing/comparing of the path to the namespace is rudimentary and there is probably a better way to do it, but this should get you started.
public override void Initialize(AnalysisContext context)
{
context.RegisterCompilationStartAction((compilationSyntax) =>
{
compilationSyntax.RegisterSyntaxTreeAction((syntaxTreeContext) =>
{
var semModel = compilationSyntax.Compilation.GetSemanticModel(syntaxTreeContext.Tree);
var filePath = syntaxTreeContext.Tree.FilePath;
if (filePath == null)
return;
var namespaceNodes = syntaxTreeContext.Tree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>();
var parentDirectory = System.IO.Path.GetDirectoryName(filePath);
// This will only work on windows and is not very robust.
var parentDirectoryWithDots = parentDirectory.Replace("\\", ".").ToLower();
foreach (var ns in namespaceNodes)
{
var symbolInfo = semModel.GetDeclaredSymbol(ns) as INamespaceSymbol;
var name = symbolInfo.ToDisplayString();
if (!parentDirectoryWithDots.EndsWith(name.ToLower().Trim()))
{
syntaxTreeContext.ReportDiagnostic(Diagnostic.Create(
Rule, ns.Name.GetLocation(), parentDirectoryWithDots));
}
}
});
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With