2
// Gendarme.Rules.Interoperability.Com.ReviewComRegistrationMethodsRule
5
// Yuri Stuken <stuken.yuri@gmail.com>
7
// Copyright (C) 2010 Yuri Stuken
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
using Gendarme.Framework;
33
using Gendarme.Framework.Engines;
34
using Gendarme.Framework.Helpers;
35
using Gendarme.Framework.Rocks;
37
namespace Gendarme.Rules.Interoperability.Com {
40
/// This rule checks the correctness of COM register and unregister methods,
41
/// i.e. they should not be externally visible and they should be matched
42
/// (both or none of them should exist ).
45
/// Bad example (public methods):
47
/// [ComVisible (true)
49
/// [ComRegisterFunction]
50
/// public void Register ()
54
/// [ComUnregisterFunction]
55
/// public void Unregister ()
62
/// Bad example (only one of the methods exist)
64
/// [ComVisible (true)]
66
/// [ComRegisterFunction]
67
/// public void Register ()
76
/// [ComVisible (true)]
78
/// [ComRegisterFunction]
79
/// private void Register ()
83
/// [ComUnregisterFunction]
84
/// private void Unregister ()
91
[Problem ("COM registration methods should be matched (i.e. both or none of them should exist) and should not be externally visible.")]
92
[Solution ("Add a missing method or change methods visibility to private or internal.")]
93
[FxCopCompatibility ("Microsoft.Interoperability", "CA1410:ComRegistrationMethodsShouldBeMatched")]
94
[FxCopCompatibility ("Microsoft.Interoperability", "CA1411:ComRegistrationMethodsShouldNotBeVisible")]
95
public class ReviewComRegistrationMethodsRule : Rule, ITypeRule {
97
public RuleResult CheckType (TypeDefinition type)
99
if (type.HasGenericParameters || !type.IsVisible () || !type.IsTypeComVisible ())
100
return RuleResult.DoesNotApply;
102
bool foundRegister = false; // type level variables
103
bool foundUnregister = false;
105
foreach (MethodDefinition method in type.Methods) {
106
if (!method.HasCustomAttributes)
109
bool foundRegisterUnregisterMethod = false; // method level variable
110
foreach (CustomAttribute attribute in method.CustomAttributes) {
111
TypeReference atype = attribute.AttributeType;
112
if (!foundRegister && atype.IsNamed ("System.Runtime.InteropServices", "ComRegisterFunctionAttribute")) {
113
foundRegister = true;
114
foundRegisterUnregisterMethod = true;
116
if (!foundUnregister && atype.IsNamed ("System.Runtime.InteropServices", "ComUnregisterFunctionAttribute")) {
117
foundUnregister = true;
118
foundRegisterUnregisterMethod = true;
121
if (foundRegisterUnregisterMethod && method.IsVisible ()) {
122
Runner.Report (method, Severity.High, Confidence.High,
123
"Method is marked with the ComRegisterFunctionAttribute or with the ComUnregisterFunctionAttribute and is externally visible");
127
if (foundRegister ^ foundUnregister) { // only one of them is true
129
Runner.Report (type, Severity.High, Confidence.High,
130
"Type contains has a method with ComRegisterFunctionAttribute but it doesn't contain a method with ComUnregisterFunctionAttribute");
132
Runner.Report (type, Severity.High, Confidence.High,
133
"Type contains has a method with ComUnregisterFunctionAttribute but it doesn't contain a method with ComRegisterFunctionAttribute");
136
return Runner.CurrentRuleResult;