#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

369 lines
15 KiB

//
// InconsistentNamingIssue.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[IssueDescription("Inconsistent Naming",
Description = "Name doesn't match the defined style for this entity.",
Category = IssueCategories.ConstraintViolations,
Severity = Severity.Warning,
ResharperDisableKeyword = "CheckNamespace")]
public class InconsistentNamingIssue : ICodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
var visitor = new GatherVisitor(context);
context.RootNode.AcceptVisitor(visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase<InconsistentNamingIssue>
{
readonly NamingConventionService service;
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
{
service = (NamingConventionService)ctx.GetService (typeof (NamingConventionService));
}
void CheckName(TypeDeclaration node, AffectedEntity entity, Identifier identifier, Modifiers accessibilty)
{
TypeResolveResult resolveResult = ctx.Resolve(node) as TypeResolveResult;
if (resolveResult == null)
return;
var type = resolveResult.Type;
if (type.DirectBaseTypes.Any(t => t.FullName == "System.Attribute")) {
if (CheckNamedResolveResult(resolveResult, node, AffectedEntity.CustomAttributes, identifier, accessibilty)) {
return;
}
} else if (type.DirectBaseTypes.Any(t => t.FullName == "System.EventArgs")) {
if (CheckNamedResolveResult(resolveResult, node, AffectedEntity.CustomEventArgs, identifier, accessibilty)) {
return;
}
} else if (type.DirectBaseTypes.Any(t => t.FullName == "System.Exception")) {
if (CheckNamedResolveResult(resolveResult, node, AffectedEntity.CustomExceptions, identifier, accessibilty)) {
return;
}
}
var typeDef = type.GetDefinition();
if (typeDef != null && typeDef.Attributes.Any(attr => attr.AttributeType.FullName == "NUnit.Framework.TestFixtureAttribute")) {
if (CheckNamedResolveResult(resolveResult, node, AffectedEntity.TestType, identifier, accessibilty)) {
return;
}
}
CheckNamedResolveResult(resolveResult, node, entity, identifier, accessibilty);
}
void CheckName(MethodDeclaration node, AffectedEntity entity, Identifier identifier, Modifiers accessibilty)
{
ResolveResult resolveResult = null;
if (node != null && node.Attributes.Any ())
resolveResult = ctx.Resolve(node);
if (resolveResult is MemberResolveResult) {
var member = ((MemberResolveResult)resolveResult).Member;
if (member.SymbolKind == SymbolKind.Method && member.Attributes.Any(attr => attr.AttributeType.FullName == "NUnit.Framework.TestAttribute")) {
if (CheckNamedResolveResult(resolveResult, node, AffectedEntity.TestMethod, identifier, accessibilty)) {
return;
}
}
}
CheckNamedResolveResult(resolveResult, node, entity, identifier, accessibilty);
}
void CheckName(AstNode node, AffectedEntity entity, Identifier identifier, Modifiers accessibilty)
{
CheckNamedResolveResult(null, node, entity, identifier, accessibilty);
}
bool CheckNamedResolveResult(ResolveResult resolveResult, AstNode node, AffectedEntity entity, Identifier identifier, Modifiers accessibilty)
{
bool wasHandled = false;
foreach (var rule in service.Rules) {
if (!rule.AffectedEntity.HasFlag(entity)) {
continue;
}
if (!rule.VisibilityMask.HasFlag(accessibilty)) {
continue;
}
if (!rule.IncludeInstanceMembers || !rule.IncludeStaticEntities) {
EntityDeclaration typeSystemEntity;
if (node is VariableInitializer) {
typeSystemEntity = node.Parent as EntityDeclaration;
} else {
typeSystemEntity = node as EntityDeclaration;
}
if (!rule.IncludeInstanceMembers) {
if (typeSystemEntity == null || !typeSystemEntity.HasModifier (Modifiers.Static) || typeSystemEntity.HasModifier (Modifiers.Sealed)) {
continue;
}
}
if (!rule.IncludeStaticEntities) {
if (typeSystemEntity == null || typeSystemEntity.HasModifier (Modifiers.Static) || typeSystemEntity.HasModifier (Modifiers.Sealed)) {
continue;
}
}
}
wasHandled = true;
if (!rule.IsValid(identifier.Name)) {
IList<string> suggestedNames;
var msg = rule.GetErrorMessage(ctx, identifier.Name, out suggestedNames);
var actions = new List<CodeAction>(suggestedNames.Select(n => new CodeAction(string.Format(ctx.TranslateString("Rename to '{0}'"), n), (Script script) => {
if (resolveResult == null)
resolveResult = ctx.Resolve (node);
if (resolveResult is MemberResolveResult) {
script.Rename(((MemberResolveResult)resolveResult).Member, n);
} else if (resolveResult is TypeResolveResult) {
var def = resolveResult.Type.GetDefinition();
if (def != null) {
script.Rename(def, n);
} else if (resolveResult.Type.Kind == TypeKind.TypeParameter) {
script.Rename((ITypeParameter)resolveResult.Type, n);
}
} else if (resolveResult is LocalResolveResult) {
script.Rename(((LocalResolveResult)resolveResult).Variable, n);
} else if (resolveResult is NamespaceResolveResult) {
script.Rename(((NamespaceResolveResult)resolveResult).Namespace, n);
} else {
script.Replace(identifier, Identifier.Create(n));
}
}, identifier)));
if (entity != AffectedEntity.Label) {
actions.Add(new CodeAction(string.Format(ctx.TranslateString("Rename '{0}'..."), identifier.Name), (Script script) => {
if (resolveResult == null)
resolveResult = ctx.Resolve (node);
if (resolveResult is MemberResolveResult) {
script.Rename(((MemberResolveResult)resolveResult).Member);
} else if (resolveResult is TypeResolveResult) {
var def = resolveResult.Type.GetDefinition();
if (def != null) {
script.Rename(def);
} else if (resolveResult.Type.Kind == TypeKind.TypeParameter) {
script.Rename((ITypeParameter)resolveResult.Type);
}
} else if (resolveResult is LocalResolveResult) {
script.Rename(((LocalResolveResult)resolveResult).Variable);
} else if (resolveResult is NamespaceResolveResult) {
script.Rename(((NamespaceResolveResult)resolveResult).Namespace);
}
}, identifier));
}
AddIssue(identifier, msg, actions);
}
}
return wasHandled;
}
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{
base.VisitNamespaceDeclaration(namespaceDeclaration);
foreach (var id in namespaceDeclaration.Identifiers) {
CheckNamedResolveResult(null, namespaceDeclaration, AffectedEntity.Namespace, id, Modifiers.None);
}
}
Modifiers GetAccessibiltiy(EntityDeclaration decl, Modifiers defaultModifier)
{
var accessibility = (decl.Modifiers & Modifiers.VisibilityMask);
if (accessibility == Modifiers.None) {
return defaultModifier;
}
return accessibility;
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
base.VisitTypeDeclaration(typeDeclaration);
AffectedEntity entity;
switch (typeDeclaration.ClassType) {
case ClassType.Class:
entity = AffectedEntity.Class;
break;
case ClassType.Struct:
entity = AffectedEntity.Struct;
break;
case ClassType.Interface:
entity = AffectedEntity.Interface;
break;
case ClassType.Enum:
entity = AffectedEntity.Enum;
break;
default:
throw new System.ArgumentOutOfRangeException();
}
CheckName(typeDeclaration, entity, typeDeclaration.NameToken, GetAccessibiltiy(typeDeclaration, typeDeclaration.Parent is TypeDeclaration ? Modifiers.Private : Modifiers.Internal));
}
public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
{
base.VisitDelegateDeclaration(delegateDeclaration);
CheckName(delegateDeclaration, AffectedEntity.Delegate, delegateDeclaration.NameToken, GetAccessibiltiy(delegateDeclaration, delegateDeclaration.Parent is TypeDeclaration ? Modifiers.Private : Modifiers.Internal));
}
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
if (propertyDeclaration.Modifiers.HasFlag (Modifiers.Override))
return;
base.VisitPropertyDeclaration(propertyDeclaration);
CheckName(propertyDeclaration, AffectedEntity.Property, propertyDeclaration.NameToken, GetAccessibiltiy(propertyDeclaration, Modifiers.Private));
}
public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
{
if (indexerDeclaration.Modifiers.HasFlag(Modifiers.Override)) {
var rr = ctx.Resolve (indexerDeclaration) as MemberResolveResult;
if (rr == null)
return;
var baseType = rr.Member.DeclaringType.DirectBaseTypes.FirstOrDefault (t => t.Kind != TypeKind.Interface);
var method = baseType != null ? baseType.GetProperties (m => m.IsIndexer && m.IsOverridable && m.Parameters.Count == indexerDeclaration.Parameters.Count).FirstOrDefault () : null;
if (method == null)
return;
int i = 0;
foreach (var par in indexerDeclaration.Parameters) {
if (method.Parameters[i++].Name != par.Name) {
par.AcceptVisitor (this);
}
}
return;
}
base.VisitIndexerDeclaration(indexerDeclaration);
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
if (methodDeclaration.Modifiers.HasFlag(Modifiers.Override)) {
var rr = ctx.Resolve (methodDeclaration) as MemberResolveResult;
if (rr == null)
return;
var baseType = rr.Member.DeclaringType.DirectBaseTypes.FirstOrDefault (t => t.Kind != TypeKind.Interface);
var method = baseType != null ? baseType.GetMethods (m => m.Name == rr.Member.Name && m.IsOverridable && m.Parameters.Count == methodDeclaration.Parameters.Count).FirstOrDefault () : null;
if (method == null)
return;
int i = 0;
foreach (var par in methodDeclaration.Parameters) {
if (method.Parameters[i++].Name != par.Name) {
par.AcceptVisitor (this);
}
}
return;
}
base.VisitMethodDeclaration(methodDeclaration);
CheckName(methodDeclaration, methodDeclaration.Modifiers.HasFlag(Modifiers.Async) ? AffectedEntity.AsyncMethod : AffectedEntity.Method, methodDeclaration.NameToken, GetAccessibiltiy(methodDeclaration, Modifiers.Private));
}
public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
{
base.VisitFieldDeclaration(fieldDeclaration);
var entity = AffectedEntity.Field;
if (fieldDeclaration.Modifiers.HasFlag(Modifiers.Const)) {
entity = AffectedEntity.ConstantField;
} else if (fieldDeclaration.Modifiers.HasFlag(Modifiers.Readonly)) {
entity = AffectedEntity.ReadonlyField;
}
foreach (var init in fieldDeclaration.Variables) {
CheckName(init, entity, init.NameToken, GetAccessibiltiy(fieldDeclaration, Modifiers.Private));
}
}
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
{
base.VisitFixedFieldDeclaration(fixedFieldDeclaration);
var entity = AffectedEntity.Field;
if (fixedFieldDeclaration.Modifiers.HasFlag(Modifiers.Const)) {
entity = AffectedEntity.ConstantField;
} else if (fixedFieldDeclaration.Modifiers.HasFlag(Modifiers.Readonly)) {
entity = AffectedEntity.ReadonlyField;
}
CheckName(fixedFieldDeclaration, entity, fixedFieldDeclaration.NameToken, GetAccessibiltiy(fixedFieldDeclaration, Modifiers.Private));
}
public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
{
base.VisitEventDeclaration(eventDeclaration);
foreach (var init in eventDeclaration.Variables) {
CheckName(init, AffectedEntity.Event, init.NameToken, GetAccessibiltiy(eventDeclaration, Modifiers.Private));
}
}
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
{
if (eventDeclaration.Modifiers.HasFlag (Modifiers.Override))
return;
base.VisitCustomEventDeclaration(eventDeclaration);
CheckName(eventDeclaration, AffectedEntity.Event, eventDeclaration.NameToken, GetAccessibiltiy(eventDeclaration, Modifiers.Private));
}
public override void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
{
base.VisitEnumMemberDeclaration(enumMemberDeclaration);
CheckName(enumMemberDeclaration, AffectedEntity.EnumMember, enumMemberDeclaration.NameToken, GetAccessibiltiy(enumMemberDeclaration, Modifiers.Private));
}
public override void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
{
base.VisitParameterDeclaration(parameterDeclaration);
CheckNamedResolveResult(null, parameterDeclaration, parameterDeclaration.Parent is LambdaExpression ? AffectedEntity.LambdaParameter : AffectedEntity.Parameter, parameterDeclaration.NameToken, Modifiers.None);
}
public override void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
{
base.VisitTypeParameterDeclaration(typeParameterDeclaration);
CheckNamedResolveResult(null, typeParameterDeclaration, AffectedEntity.TypeParameter, typeParameterDeclaration.NameToken, Modifiers.None);
}
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
{
base.VisitVariableDeclarationStatement(variableDeclarationStatement);
var entity = variableDeclarationStatement.Modifiers.HasFlag(Modifiers.Const) ? AffectedEntity.LocalConstant : AffectedEntity.LocalVariable;
foreach (var init in variableDeclarationStatement.Variables) {
CheckNamedResolveResult(null, init, entity, init.NameToken, Modifiers.None);
}
}
public override void VisitLabelStatement(LabelStatement labelStatement)
{
base.VisitLabelStatement(labelStatement);
CheckNamedResolveResult(null, labelStatement, AffectedEntity.Label, labelStatement.LabelToken, Modifiers.None);
}
}
}
}