Exemplo n.º 1
0
		private void CheckForLegalCall (MethodDefinition caller, Instruction ins)
		{
			MethodDefinition target = ((MethodReference) ins.Operand).Resolve ();
			if (target != null) {
				ThreadModel callerModel = caller.ThreadingModel ();
				ThreadModel targetModel = target.ThreadingModel ();
				if (!IsValidCall (callerModel, targetModel)) {
					string mesg = string.Format ("{0} {1} cannot call {2} {3}.", callerModel, caller.Name, targetModel, target.Name);
					
					++DefectCount;
					Log.WriteLine (this, "Defect: {0}", mesg);
					Defect defect = new Defect (this, caller, caller, ins, Severity.High, Confidence.High, mesg);
					Runner.Report (defect);
				}
			}
		}
Exemplo n.º 2
0
		public RuleResult CheckMethod (MethodDefinition method)
		{
			if (ThreadRocks.ThreadedNamespace (method.DeclaringType.Namespace))
				return RuleResult.DoesNotApply;
			
			Log.WriteLine (this);
			Log.WriteLine (this, "---------------------------------------");
			Log.WriteLine (this, method);

			string name = method.Name;
			IList<ParameterDefinition> pdc = method.HasParameters ? method.Parameters : null;

			// Finalizers need to be single threaded.
			ThreadModel model = method.ThreadingModel ();
			if (method.IsFinalizer ()) {
				if ((model & ~ThreadModel.AllowEveryCaller) != ThreadModel.SingleThread) {
					string mesg = "Finalizers should be decorated with [ThreadModel (ThreadModel.SingleThreaded)].";
					ReportDefect (method, Severity.High, Confidence.High, mesg);
				}
			}
			
			// Make sure all of the thread entry points are properly decorated and
			// that all calls are legit.
			if (method.HasBody && opcodes_mask.Intersect (OpCodeEngine.GetBitmask (method)))
				CheckMethodBody (method);
			
			// A delegate used with a threaded event must use the same threading model 
			// as the event.
			if (method.IsAddOn) {
				ParameterDefinition p = pdc [0];
				TypeDefinition delegateType = p.ParameterType.Resolve ();
				if (delegateType != null && !ThreadRocks.ThreadedNamespace (delegateType.Namespace)) {
					ThreadModel delegateModel = delegateType.ThreadingModel ();
					if (model != delegateModel && !delegateModel.AllowsEveryCaller ()) {
						string mesg = string.Format ("{0} event must match {1} delegate.", model, delegateModel);
						ReportDefect (method, Severity.High, Confidence.High, mesg);
					}
				}
			}

			// An override of a base method or an implementation of an interface method
			// must use the same threading model as the original method.
			if (method.IsVirtual) {
				IEnumerable<TypeDefinition> superTypes = method.DeclaringType.AllSuperTypes ();
				bool new_slot = method.IsNewSlot;
				superTypes = from s in superTypes where (s.IsInterface == new_slot) select s;
				string [] parameters = pdc != null
					? (from p in pdc.Cast<ParameterDefinition> () select p.ParameterType.FullName).ToArray ()
					: null;

				foreach (TypeDefinition type in superTypes) {
					MethodDefinition superMethod = type.GetMethod (name, method.ReturnType.FullName, parameters);
					if (superMethod != null && !ThreadRocks.ThreadedNamespace (superMethod.DeclaringType.Namespace)) {
						ThreadModel superModel = superMethod.ThreadingModel ();
						if (model != superModel) {
							string mesg = string.Format ("{0} {1} must match {2} {3} method.", model, name, superModel,
								new_slot ? "interface" : "base");
							ReportDefect (method, Severity.High, Confidence.High, mesg);
						}
					}
				}
			}
			
			// Serializable cannot be applied to static methods, but can be applied to
			// operators because they're just sugar for normal calls.
			if (method.IsStatic && model.Is (ThreadModel.Serializable) && !name.StartsWith ("op_")) {
				string mesg = "Static members cannot be decorated with Serializable.";
				ReportDefect (method, Severity.High, Confidence.High, mesg);
			}
			
			return Runner.CurrentRuleResult;
		}