Property definitions

nitc $ RestfulPhase :: defaultinit
private class RestfulPhase
	super Phase

	# Classes with methods marked with the `restful` annotation
	var restful_classes = new HashSet[MClassDef]

	redef fun process_annotated_node(node, nat)
	do
		# Skip if we are not interested
		var text = nat.n_atid.n_id.text
		if text != "restful" then return

		if not node isa AMethPropdef then
			toolcontext.error(nat.location,
				"Syntax Error: `restful` can only be applied on method definitions")
			return
		end

		var mpropdef = node.mpropdef
		if mpropdef == null then return
		var mproperty = mpropdef.mproperty
		var mclassdef = mpropdef.mclassdef
		var mmodule = mclassdef.mmodule

		var http_resources = new Array[String]
		var http_methods = new Array[String]
		for arg in nat.n_args do
			var str = arg.as_string
			var id = arg.collect_text
			if str != null then
				# String -> rename resource
				http_resources.add str
			else if arg isa ATypeExpr and not id.chars.has("[") then
				# Class id -> HTTP method
				http_methods.add id
			else if id == "async" then
				mproperty.restful_async = true
			else
				toolcontext.error(nat.location,
					"Syntax Error: `restful` expects String literals or ids as arguments.")
				return
			end
		end

		# Test subclass of `RestfulAction`
		var sup_class_name = "RestfulAction"
		var sup_class = toolcontext.modelbuilder.try_get_mclass_by_name(
			nat, mmodule, sup_class_name)
		var in_hierarchy = mclassdef.in_hierarchy
		if in_hierarchy == null or sup_class == null then return
		var sup_classes = in_hierarchy.greaters
		if not sup_classes.has(sup_class.intro) then
			toolcontext.error(nat.location,
				"Syntax Error: `restful` is only valid within subclasses of `{sup_class_name}`")
			return
		end

		# Register the property
		mclassdef.restful_methods.add mproperty
		restful_classes.add mclassdef

		if http_resources.not_empty then mproperty.restful_resources = http_resources
		mproperty.restful_verbs = http_methods
	end
end
src/nitrestful.nit:22,1--86,3