public RuleResult CheckType (TypeDefinition type) { // rule does not apply to interface (since [Serializable] is not applicable to interfaces) // nor does it apply to delegates if (type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; // rule does not apply if the type does not implements ISerializable if (!type.Implements ("System.Runtime.Serialization", "ISerializable")) return RuleResult.DoesNotApply; // rule applies only if base type is serializable if (!type.BaseType.IsNamed ("System", "Object")) { TypeDefinition base_type = type.BaseType.Resolve (); // in doubt don't report if ((base_type == null) || !base_type.IsSerializable) return RuleResult.DoesNotApply; } // rule applies, only Success or Failure from the point on // ok if the type has the [Serializable] pseudo-attribute if (type.IsSerializable) return RuleResult.Success; Runner.Report (type, Severity.Critical, Confidence.Total); return RuleResult.Failure; }
/// <summary> /// Create a type builder for the given type. /// </summary> internal static IClassBuilder[] Create(ReachableContext context, AssemblyCompiler compiler, TypeDefinition typeDef) { if (typeDef.FullName == "<Module>") return new IClassBuilder[] { new SkipClassBuilder() }; if (typeDef.IsDelegate()) return new IClassBuilder[] {new DelegateClassBuilder(context, compiler, typeDef) }; if (typeDef.IsAttribute()) return new IClassBuilder[] {new AttributeClassBuilder(context, compiler, typeDef) }; if (typeDef.IsAnnotation()) return new IClassBuilder[] {new AnnotationClassBuilder(context, compiler, typeDef) }; if (typeDef.HasDexImportAttribute()) return new IClassBuilder[] {new DexImportClassBuilder(context, compiler, typeDef) }; if (typeDef.HasJavaImportAttribute()) return new IClassBuilder[] {CreateJavaImportBuilder(context, compiler, typeDef)}; if (typeDef.IsEnum) { if (typeDef.UsedInNullableT) { var nullableBaseClassBuilder = new NullableEnumBaseClassBuilder(context, compiler, typeDef); IClassBuilder builder = new EnumClassBuilder(context, compiler, typeDef, nullableBaseClassBuilder); return new[] { builder, nullableBaseClassBuilder }; } return new IClassBuilder[] { new EnumClassBuilder(context, compiler, typeDef, null) }; } else { IClassBuilder builder = new StandardClassBuilder(context, compiler, typeDef); if (typeDef.UsedInNullableT) return new[] { builder, new NullableBaseClassBuilder(context, compiler, typeDef) }; return new[] { builder }; } }
public RuleResult CheckType(TypeDefinition type) { // rule applies only to types and interfaces if (type.IsEnum || type.IsDelegate() || type.IsGeneratedCode() || type.IsValueType || type.IsInterface) return RuleResult.DoesNotApply; // rule only applies to type that implements IDisposable if (!type.Implements("System", "IDisposable")) return RuleResult.DoesNotApply; // rule only applies to type that doesn't derive from class that implements IDisposable if (type.BaseType.Implements("System", "IDisposable")) return RuleResult.DoesNotApply; // rule only applies if type has a Dispose(bool) method if (!type.HasMethod(Dispose)) return RuleResult.DoesNotApply; // no problem if a finalizer is found if (type.HasMethod(MethodSignatures.Finalize)) return RuleResult.Success; Runner.Report(type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only to types, interfaces and structures (value types) if (type.IsEnum || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule onyly applies to type that implements IDisposable if (!type.Implements ("System.IDisposable")) return RuleResult.DoesNotApply; // no problem is a finalizer is found if (type.HasMethod (MethodSignatures.Finalize)) return RuleResult.Success; // otherwise check for native types foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; if (!field.FieldType.GetElementType ().IsNative ()) continue; Runner.Report (field, Severity.High, Confidence.High); } // special case: a struct cannot define a finalizer so it's a // bad candidate to hold references to unmanaged resources if (type.IsValueType && (Runner.CurrentRuleResult == RuleResult.Failure)) Runner.Report (type, Severity.High, Confidence.High, Struct); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; if (!invoke.ReturnType.IsNamed ("System", "Void")) return RuleResult.Success; if (!invoke.HasParameters) return RuleResult.Success; IList<ParameterDefinition> pdc = invoke.Parameters; if (pdc.Count != 2) return RuleResult.Success; if (!pdc [0].ParameterType.IsNamed ("System", "Object")) return RuleResult.Success; if (!pdc [1].ParameterType.Inherits ("System", "EventArgs")) return RuleResult.Success; Runner.Report (type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsInterface || type.IsValueType || type.IsDelegate ()) return RuleResult.DoesNotApply; int depth = 0; while (type.BaseType != null) { type = type.BaseType.Resolve (); if (type == null) break; if (countExternalDepth || Runner.Assemblies.Contains (type.Module.Assembly)) depth++; } if (depth <= MaximumDepth) return RuleResult.Success; // Confidence is total unless we count outside the current assembly, // where it's possible we can't resolve up to System.Object Confidence confidence = countExternalDepth ? Confidence.High : Confidence.Total; // Severity is based on the depth string msg = String.Format (CultureInfo.CurrentCulture, "Inheritance tree depth : {0}.", depth); Runner.Report (type, GetSeverity (depth), confidence, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { //does rule apply? if (type.IsEnum || type.IsInterface || type.IsAbstract || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; if (!type.HasFields || (type.Fields.Count < MinimumFieldCount)) return RuleResult.DoesNotApply; if (!type.HasMethods || (type.Methods.Count < MinimumMethodCount)) return RuleResult.DoesNotApply; //yay! rule do apply! double coh = GetCohesivenessForType (type); if (coh >= SuccessLowerLimit) return RuleResult.Success; if (0 == coh) return RuleResult.DoesNotApply; //how's severity? Severity sev = GetCohesivenessSeverity(coh); string msg = String.Format (CultureInfo.CurrentCulture, "Type cohesiveness : {0}%", (int) (coh * 100)); Runner.Report (type, sev, Confidence.Normal, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply on enums, interfaces, delegates or to compiler/tools-generated code // e.g. CSC compiles anonymous methods as an inner type that expose public fields if (type.IsEnum || type.IsInterface || !type.HasFields || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule doesn't apply to type non (externally) visible if (!type.IsVisible ()) return RuleResult.DoesNotApply; foreach (FieldDefinition fd in type.Fields) { if (!fd.IsVisible () || fd.IsSpecialName || fd.HasConstant || fd.IsInitOnly) continue; string name = fd.Name; if (fd.FieldType.IsArray) { string s = String.Format (CultureInfo.InvariantCulture, "Consider changing the field '{0}' to a private or internal field and add a 'Set{1}{2}' method.", name, Char.ToUpper (name [0], CultureInfo.InvariantCulture).ToString (CultureInfo.InvariantCulture), name.Substring (1)); Runner.Report (fd, Severity.Medium, Confidence.Total, s); } else { string s = String.Format (CultureInfo.InvariantCulture, "Field '{0}' should be private or internal and its value accessed through a property.", name); Runner.Report (fd, Severity.Medium, Confidence.Total, s); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; MethodDefinition equality = type.GetMethod (MethodSignatures.op_Equality); if ((equality == null) || type.HasMethod (MethodSignatures.Equals)) return RuleResult.Success; Runner.Report (equality, Severity.High, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to interface and enumerations if (type.IsInterface || type.IsEnum || !type.HasFields || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (FieldDefinition field in type.Fields) { if (field.IsStatic && field.IsVisible () && !field.IsInitOnly && !field.IsLiteral) { Runner.Report (field, Severity.Medium, Confidence.High); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to interface and enumerations if (type.IsInterface || type.IsEnum || !type.HasFields || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (FieldDefinition field in type.Fields) { if (field.IsStatic && field.IsVisible () && !field.IsInitOnly && !field.IsLiteral) { Runner.Report (field, Severity.Medium, Confidence.High, String.Format("Change the field \"{0}\" to read-only, or mark it [ThreadStatic], or make it non visible outside the assembly.", field.Name)); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to interface, enumerations and delegates or to types without fields if (type.IsInterface || type.IsEnum || !type.HasFields || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (FieldDefinition field in type.Fields) { //IsInitOnly == readonly if (field.IsInitOnly && field.IsVisible () && field.FieldType.IsArray) { // Medium = this will work as long as no code starts "playing" with the array values Runner.Report (field, Severity.Medium, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only to sealed types, but not to enum, value types and delegate (sealed) if (!type.IsSealed || type.IsEnum || type.IsValueType || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (MethodDefinition method in type.Methods) { // method is virtual and not final (sealed) if (method.IsVirtual && !method.IsFinal) { // so just make sure it's not an override of an ancestor if (!method.IsOverride ()) Runner.Report (method, Severity.Low, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; // get the static constructor MethodDefinition cctor = type.Methods.FirstOrDefault (m => m.IsConstructor && m.IsStatic); if (cctor == null) return RuleResult.DoesNotApply; // check if we store things into static fields if (!OpCodeEngine.GetBitmask (cctor).Get (Code.Stsfld)) return RuleResult.DoesNotApply; // verify each store we do in a static field foreach (Instruction ins in cctor.Body.Instructions) { if (ins.OpCode.Code != Code.Stsfld) continue; // make sure we assign to this type (and not another one) FieldReference fr = (ins.Operand as FieldReference); if (fr.DeclaringType != type) continue; // if it's this one then we have a FieldDefinition available FieldDefinition field = (fr as FieldDefinition); // check for static (we already know with Stsfld) and readonly if (!field.IsInitOnly) continue; // look at what is being assigned Instruction previous = ins.Previous; // while skipping conversions if (Convert.Get (previous.OpCode.Code)) previous = previous.Previous; // and report constant stuff if (Constant.Get (previous.OpCode.Code)) { // adjust severity based on the field visibility and it's type Severity s = (field.FieldType.IsNamed ("System", "String") || !field.IsVisible ()) ? Severity.High : Severity.Medium; Runner.Report (field, s, Confidence.Normal); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType(TypeDefinition type) { // rule does not apply to interface, enumerations and delegates or to types without fields if (type.IsInterface || type.IsEnum || !type.HasFields || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (FieldDefinition field in type.Fields) { if (!field.IsVisible ()) continue; //not readonly native fields or arrays of native fields if ((field.FieldType.IsNative () && !field.IsInitOnly) || (field.FieldType.IsArray && field.FieldType.GetElementType ().IsNative ())) { Runner.Report (field, Severity.Medium, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to interface, enumerations or delegates if (type.IsInterface || type.IsEnum || !type.HasMethods || type.IsDelegate ()) return RuleResult.DoesNotApply; MethodDefinition private_static_ctor = null; foreach (MethodDefinition method in type.Methods) { if (method.IsStatic && !method.IsPrivate && method.IsConstructor) { private_static_ctor = method; break; // there cannot be two .cctor's so we can stop looking } } if (private_static_ctor == null) return RuleResult.Success; Runner.Report (private_static_ctor, Severity.Critical, Confidence.Total); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enumerations and delegates if (type.IsEnum || type.IsDelegate ()) return RuleResult.DoesNotApply; // quick out if there are no events if (!type.HasEvents) return RuleResult.Success; foreach (EventDefinition evnt in type.Events) { string name = evnt.Name; if (name.StartsWith ("After", StringComparison.Ordinal) || name.StartsWith ("Before", StringComparison.Ordinal)) { Runner.Report (evnt, Severity.Medium, Confidence.Total); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (var kv in AlternativeMethodNames) { MethodDefinition op = type.GetMethod (kv.Key); if (op == null) continue; bool alternativeDefined = false; foreach (MethodDefinition alternative in type.Methods) { if (kv.Value.Matches (alternative)) { alternativeDefined = true; break; } } if (!alternativeDefined) { string s = String.Format ("This type implements the '{0}' operator. Some languages do not support overloaded operators so an alternative '{1}' method should be provided.", kv.Key.Name, kv.Value.Name); Runner.Report (op, Severity.Medium, Confidence.High, s); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsDelegate ()) return RuleResult.DoesNotApply; // we look for a Parse method defined in the type bool has_parse = false; foreach (MethodDefinition method in type.Methods) { if (method.IsConstructor) continue; if (MethodSignatures.Parse.Matches (method)) { // the type provides a "<type> <type>::Parse(string)" method has_parse = true; break; } } // if no Parse method is found; or // if a Parse method is found along with a TryParse method if (!has_parse || HasTryParseMethod (type)) return RuleResult.Success; // otherwise we report a defect to add a TryParse alternative Runner.Report (type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, delegates and to generated code if (type.IsEnum || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule applies only if the type overrides Equals(object) if (!type.HasMethod (MethodSignatures.Equals)) return RuleResult.DoesNotApply; // if so then the type should also implement Equals(type) since this avoid a cast // operation (for reference types) and also boxing (for value types). // we suggest to implement IEquatable<T> if // * the assembly targets the 2.0 (or later) runtime // * and it does not already implement it if (type.Module.Runtime >= TargetRuntime.Net_2_0) { if (!type.Implements ("System", "IEquatable`1")) { Runner.Report (type, Severity.Medium, Confidence.Total, "Implement System.IEquatable<T>"); } return Runner.CurrentRuleResult; } parameters [0] = type.GetFullName (); if (type.GetMethod (MethodAttributes.Public, "Equals", "System.Boolean", parameters) != null) return RuleResult.Success; // we consider this a step more severe for value types since it will need // boxing/unboxing with Equals(object) Severity severity = type.IsValueType ? Severity.Medium : Severity.Low; string msg = String.Format (CultureInfo.InvariantCulture, "Implement 'bool Equals({0})'", type.Name); Runner.Report (type, severity, Confidence.High, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // we don't control, nor report, p/invoke declarations - sometimes the poor C // guys don't have a choice to make long parameter lists ;-) if (OnlyContainsExternalMethods (type)) return RuleResult.DoesNotApply; if (type.IsDelegate ()) return CheckDelegate (type); if (type.HasMethods) { CheckConstructor (GetSmallestConstructorFrom (type)); foreach (MethodDefinition method in GetSmallestOverloaded (type)) CheckMethod (method); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to enums, interfaces, structs, delegates or generated code if (type.IsEnum || type.IsInterface || type.IsValueType || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition explicitDisposeMethod = null; MethodDefinition implicitDisposeMethod = null; bool abstractWarning = false; if (type.Implements ("System.IDisposable")) { implicitDisposeMethod = type.GetMethod (MethodSignatures.Dispose); explicitDisposeMethod = type.GetMethod (MethodSignatures.DisposeExplicit); if (IsAbstract (implicitDisposeMethod) || IsAbstract (explicitDisposeMethod)) { abstractWarning = true; } else { return RuleResult.Success; } } foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; TypeDefinition fieldType = field.FieldType.GetElementType ().Resolve (); if (fieldType == null) continue; // enums and primitives don't implement IDisposable if (fieldType.IsEnum || fieldType.IsPrimitive) continue; if (fieldType.Implements ("System.IDisposable")) { Runner.Report (field, Severity.High, Confidence.High, abstractWarning ? AbstractTypeMessage : TypeMessage); } } // Warn about possible confusion if the Dispose methods are abstract if (IsAbstract (implicitDisposeMethod)) Runner.Report (implicitDisposeMethod, Severity.Medium, Confidence.High, AbstractDisposeMessage); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsInterface || type.IsEnum || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (var kv in SymmetricOperators_Warning) CheckOperatorPair (kv, type, Severity.Medium); foreach (var kv in SymmetricOperators_Error) CheckOperatorPair (kv, type, Severity.High); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, interfaces and delegates // or types and structures without fields // nor does it apply to generated code (quite common for anonymous types) if (type.IsEnum || type.IsInterface || !type.HasFields || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // copy all fields into an hashset fields.Clear (); foreach (FieldDefinition field in type.Fields) { if (!field.IsPrivate || field.IsLiteral) continue; fields.Add (field); } // scan all methods, including constructors, to find if the field is used foreach (MethodDefinition method in type.Methods) { if (!method.HasBody) continue; // don't check the method if it does not access any field if (!OpCodeEngine.GetBitmask (method).Intersect (LoadStoreFields)) continue; foreach (Instruction ins in method.Body.Instructions) { FieldDefinition fd = ins.GetField (); if (fd == null) continue; fields.Remove (fd); } } // check remaining (private) fields in the set foreach (FieldDefinition field in fields) { Runner.Report (field, Severity.Medium, Confidence.Normal); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to interfaces and enums if (type.IsInterface || type.IsEnum || type.IsDelegate ()) return RuleResult.DoesNotApply; bool equals = type.HasMethod (MethodSignatures.Equals); bool getHashCode = type.HasMethod (MethodSignatures.GetHashCode); // if we have Equals but no GetHashCode method if (equals && !getHashCode) { string text = String.Format (Message, MethodSignatures.Equals, MethodSignatures.GetHashCode); Runner.Report (type, Severity.Critical, Confidence.High, text); } // if we have GetHashCode but no Equals method if (!equals && getHashCode) { string text = String.Format (Message, MethodSignatures.GetHashCode, MethodSignatures.Equals); Runner.Report (type, Severity.Medium, Confidence.High, text); } // we either have both Equals and GetHashCode or none (both fine) return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only if the type isn't: an enum, an interface, a struct, a delegate or compiler generated if (type.IsEnum || type.IsInterface || type.IsValueType || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // it also does not apply if the type is static (2.0+ only) if (type.IsStatic ()) return RuleResult.DoesNotApply; if (!IsAllStatic (type)) return RuleResult.Success; // rule applies! foreach (MethodDefinition ctor in type.Methods) { if (ctor.IsConstructor && !ctor.IsStatic && ctor.IsVisible ()) { Runner.Report (ctor, Severity.Low, Confidence.High); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (!type.IsClass || type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; if (type.HasFields) { foreach (var field in type.Fields) CheckField (field); } if (type.HasProperties) { foreach (var property in type.Properties) CheckProperty (property); } if (type.HasMethods) { foreach (var method in type.Methods) CheckMethod (method); } return Runner.CurrentRuleResult; }
protected virtual void WriteTypeInternal(TypeDefinition type, Action<IMemberDefinition> writeMember, bool showCompilerGeneratedMembers) { string typeName = string.Empty; membersStack.Push(type); if (type.IsDelegate()) { WriteDelegate(type); return; } typeName = WriteTypeDeclaration(type); int startIndex = this.formatter.CurrentPosition; this.formatter.WriteStartBlock(); WriteBeginBlock(); WriteTypeOpeningBlock(type); WriteTypeMembers(type, writeMember, showCompilerGeneratedMembers); WriteLine(); Outdent(); WriteEndBlock(typeName); membersStack.Pop(); this.currentWritingInfo.MemberDefinitionToFoldingPositionMap[type] = new OffsetSpan(startIndex, formatter.CurrentPosition - 1); this.formatter.WriteEndBlock(); }
public void WriteTypeDeclaration(TypeDefinition type, IWriterContextService writerContextService, bool showCompilerGeneratedMembers = false) { this.writerContextService = writerContextService; this.writerContext = writerContextService.GetWriterContext(type, Language); this.currentWritingInfo = new WritingInfo(type); WriteAttributes(type, new string[] { "System.Reflection.DefaultMemberAttribute" }); membersStack.Push(type); if (type.IsDelegate()) { WriteDelegate(type); WriteLine(); membersStack.Pop(); return; } WriteTypeDeclaration(type); WriteLine(); membersStack.Pop(); }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; int n = 0; Severity severity = Severity.Medium; bool use_structure = false; // check parameters for 'ref', 'out', 'params' if (invoke.HasParameters) { IList<ParameterDefinition> pdc = invoke.Parameters; n = pdc.Count; // too many parameters to directly use Action/Func // so we lower severity and suggest grouping them if (n > ((type.Module.Runtime >= TargetRuntime.Net_4_0) ? 16 : 4)) { severity = Severity.Low; n = 1; use_structure = true; } // special cases not directly usable with Action/Func foreach (ParameterDefinition pd in pdc) { if (pd.IsOut || pd.ParameterType.IsByReference || pd.IsParams ()) return RuleResult.Success; } } string msg = invoke.ReturnType.IsNamed ("System", "Void") ? ActionMessage [n] : FuncMessage [n]; if (use_structure) msg += " and use a structure to hold all your parameters into <T>."; Runner.Report (type, severity, Confidence.High, msg); return Runner.CurrentRuleResult; }