parameters: (spec, label, properties)
return_statement: return [group]
docstring: Returns a PropertyGroup definition for the specified properties.
  
    Arguments:
      spec: The target project dict.
      label: An optional label for the PropertyGroup.
      properties: The dictionary to be converted.  The key is the name of the
          property.  The value is itself a dictionary; its key is the value and
          the value a list of condition for which this value is true.
docstring_summary: Returns a PropertyGroup definition for the specified properties.
docstring_tokens: Returns a PropertyGroup definition for the specified properties .
function: def _GetMSBuildPropertyGroup(spec, label, properties):
      """Returns a PropertyGroup definition for the specified properties.
  
    Arguments:
      spec: The target project dict.
      label: An optional label for the PropertyGroup.
      properties: The dictionary to be converted.  The key is the name of the
          property.  The value is itself a dictionary; its key is the value and
          the value a list of condition for which this value is true.
    """
      group = ["PropertyGroup"]
      if label:
          group.append({"Label": label})
      num_configurations = len(spec["configurations"])
  
      def GetEdges(node):
          # Use a definition of edges such that user_of_variable -> used_varible.
          # This happens to be easier in this case, since a variable's
          # definition contains all variables it references in a single string.
          edges = set()
          for value in sorted(properties[node].keys()):
              # Add to edges all $(...) references to variables.
              #
              # Variable references that refer to names not in properties are excluded
              # These can exist for instance to refer built in definitions like
              # $(SolutionDir).
              #
              # Self references are ignored. Self reference is used in a few places to
              # append to the default value. I.e. PATH=$(PATH);other_path
              edges.update(
                  {
                      v
                      for v in MSVS_VARIABLE_REFERENCE.findall(value)
                      if v in properties and v != node
                  }
              )
          return edges
  
      properties_ordered = gyp.common.TopologicallySorted(properties.keys(), GetEdges)
      # Walk properties in the reverse of a topological sort on
      # user_of_variable -> used_variable as this ensures variables are
      # defined before they are used.
      # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
      for name in reversed(properties_ordered):
          values = properties[name]
          for value, conditions in sorted(values.items()):
              if len(conditions) == num_configurations:
                  # If the value is the same all configurations,
                  # just add one unconditional entry.
                  group.append([name, value])
              else:
                  for condition in conditions:
                      group.append([name, {"Condition": condition}, value])
      return [group]
function_tokens: def _GetMSBuildPropertyGroup ( spec , label , properties ) : group = [ "PropertyGroup" ] if label : group . append ( { "Label" : label } ) num_configurations = len ( spec [ "configurations" ] ) def GetEdges ( node ) : # Use a definition of edges such that user_of_variable -> used_varible. # This happens to be easier in this case, since a variable's # definition contains all variables it references in a single string. edges = set ( ) for value in sorted ( properties [ node ] . keys ( ) ) : # Add to edges all $(...) references to variables. # # Variable references that refer to names not in properties are excluded # These can exist for instance to refer built in definitions like # $(SolutionDir). # # Self references are ignored. Self reference is used in a few places to # append to the default value. I.e. PATH=$(PATH);other_path edges . update ( { v for v in MSVS_VARIABLE_REFERENCE . findall ( value ) if v in properties and v != node } ) return edges properties_ordered = gyp . common . TopologicallySorted ( properties . keys ( ) , GetEdges ) # Walk properties in the reverse of a topological sort on # user_of_variable -> used_variable as this ensures variables are # defined before they are used. # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) for name in reversed ( properties_ordered ) : values = properties [ name ] for value , conditions in sorted ( values . items ( ) ) : if len ( conditions ) == num_configurations : # If the value is the same all configurations, # just add one unconditional entry. group . append ( [ name , value ] ) else : for condition in conditions : group . append ( [ name , { "Condition" : condition } , value ] ) return [ group ]