Browse Source

uniqueInputObjectFields;

bjorn 9 years ago
parent
commit
590fa1817a
3 changed files with 44 additions and 10 deletions
  1. 1 1
      parse.lua
  2. 26 5
      rules.lua
  3. 17 4
      validate.lua

+ 1 - 1
parse.lua

@@ -69,7 +69,7 @@ end
 
 
 local function cObject(fields)
 local function cObject(fields)
   return {
   return {
-    kind = 'object',
+    kind = 'inputObject',
     values = fields
     values = fields
   }
   }
 end
 end

+ 26 - 5
rules.lua

@@ -25,7 +25,7 @@ function rules.loneAnonymousOperation(node, context)
 end
 end
 
 
 function rules.fieldsDefinedOnType(node, context)
 function rules.fieldsDefinedOnType(node, context)
-  if context.currentField == false then
+  if context.objects[#context.objects] == false then
     local parent = context.objects[#context.objects - 1]
     local parent = context.objects[#context.objects - 1]
     error('Field "' .. node.name.value .. '" is not defined on type "' .. parent.name .. '"')
     error('Field "' .. node.name.value .. '" is not defined on type "' .. parent.name .. '"')
   end
   end
@@ -44,13 +44,13 @@ function rules.argumentsDefinedOnType(node, context)
 end
 end
 
 
 function rules.scalarFieldsAreLeaves(node, context)
 function rules.scalarFieldsAreLeaves(node, context)
-  if context.currentField.__type == 'Scalar' and node.selectionSet then
+  if context.objects[#context.objects].__type == 'Scalar' and node.selectionSet then
     error('Scalar values cannot have subselections')
     error('Scalar values cannot have subselections')
   end
   end
 end
 end
 
 
 function rules.compositeFieldsAreNotLeaves(node, context)
 function rules.compositeFieldsAreNotLeaves(node, context)
-  local _type = context.currentField.__type
+  local _type = context.objects[#context.objects].__type
   local isCompositeType = _type == 'Object' or _type == 'Interface' or _type == 'Union'
   local isCompositeType = _type == 'Object' or _type == 'Interface' or _type == 'Union'
 
 
   if isCompositeType and not node.selectionSet then
   if isCompositeType and not node.selectionSet then
@@ -189,8 +189,8 @@ function rules.argumentsOfCorrectType(node, context)
     end
     end
 
 
     if argumentType.__type == 'InputObject' then
     if argumentType.__type == 'InputObject' then
-      if valueNode.kind ~= 'object' then
-        error('Expected an object')
+      if valueNode.kind ~= 'inputObject' then
+        error('Expected an input object')
       end
       end
 
 
       for _, field in ipairs(valueNode.values) do
       for _, field in ipairs(valueNode.values) do
@@ -363,4 +363,25 @@ function rules.fragmentSpreadIsPossible(node, context)
   end
   end
 end
 end
 
 
+function rules.uniqueInputObjectFields(node, context)
+  local function validateValue(value)
+    if value.kind == 'listType' or value.kind == 'nonNullType' then
+      return validateValue(value.type)
+    elseif value.kind == 'inputObject' then
+      local fieldMap = {}
+      for _, field in ipairs(value.values) do
+        if fieldMap[field.name] then
+          error('Multiple input object fields named "' .. field.name .. '"')
+        end
+
+        fieldMap[field.name] = true
+
+        validateValue(field.value)
+      end
+    end
+  end
+
+  validateValue(node.value)
+end
+
 return rules
 return rules

+ 17 - 4
validate.lua

@@ -49,20 +49,29 @@ local visitors = {
       local parentField = context.objects[#context.objects].fields[node.name.value]
       local parentField = context.objects[#context.objects].fields[node.name.value]
 
 
       -- false is a special value indicating that the field was not present in the type definition.
       -- false is a special value indicating that the field was not present in the type definition.
-      context.currentField = parentField and parentField.kind or false
+      local field = parentField and parentField.kind or false
 
 
-      table.insert(context.objects, context.currentField)
+      table.insert(context.objects, field)
     end,
     end,
 
 
     exit = function(node, context)
     exit = function(node, context)
       table.remove(context.objects)
       table.remove(context.objects)
-      context.currentField = nil
     end,
     end,
 
 
     children = function(node)
     children = function(node)
+      local children = {}
+
+      if node.arguments then
+        for i = 1, #node.arguments do
+          table.insert(children, node.arguments[i])
+        end
+      end
+
       if node.selectionSet then
       if node.selectionSet then
-        return {node.selectionSet}
+        table.insert(children, node.selectionSet)
       end
       end
+
+      return children
     end,
     end,
 
 
     rules = {
     rules = {
@@ -128,6 +137,10 @@ local visitors = {
     end,
     end,
 
 
     rules = { rules.fragmentHasValidType, rules.fragmentDefinitionHasNoCycles }
     rules = { rules.fragmentHasValidType, rules.fragmentDefinitionHasNoCycles }
+  },
+
+  argument = {
+    rules = { rules.uniqueInputObjectFields }
   }
   }
 }
 }