"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/node-gyp/gyp/tools/pretty_vcproj.py" (7 Feb 2017, 9586 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/env python
    2 
    3 # Copyright (c) 2012 Google Inc. All rights reserved.
    4 # Use of this source code is governed by a BSD-style license that can be
    5 # found in the LICENSE file.
    6 
    7 """Make the format of a vcproj really pretty.
    8 
    9    This script normalize and sort an xml. It also fetches all the properties
   10    inside linked vsprops and include them explicitly in the vcproj.
   11 
   12    It outputs the resulting xml to stdout.
   13 """
   14 
   15 __author__ = 'nsylvain (Nicolas Sylvain)'
   16 
   17 import os
   18 import sys
   19 
   20 from xml.dom.minidom import parse
   21 from xml.dom.minidom import Node
   22 
   23 REPLACEMENTS = dict()
   24 ARGUMENTS = None
   25 
   26 
   27 class CmpTuple(object):
   28   """Compare function between 2 tuple."""
   29   def __call__(self, x, y):
   30     return cmp(x[0], y[0])
   31 
   32 
   33 class CmpNode(object):
   34   """Compare function between 2 xml nodes."""
   35 
   36   def __call__(self, x, y):
   37     def get_string(node):
   38       node_string = "node"
   39       node_string += node.nodeName
   40       if node.nodeValue:
   41         node_string += node.nodeValue
   42 
   43       if node.attributes:
   44         # We first sort by name, if present.
   45         node_string += node.getAttribute("Name")
   46 
   47         all_nodes = []
   48         for (name, value) in node.attributes.items():
   49           all_nodes.append((name, value))
   50 
   51         all_nodes.sort(CmpTuple())
   52         for (name, value) in all_nodes:
   53           node_string += name
   54           node_string += value
   55 
   56       return node_string
   57 
   58     return cmp(get_string(x), get_string(y))
   59 
   60 
   61 def PrettyPrintNode(node, indent=0):
   62   if node.nodeType == Node.TEXT_NODE:
   63     if node.data.strip():
   64       print '%s%s' % (' '*indent, node.data.strip())
   65     return
   66 
   67   if node.childNodes:
   68     node.normalize()
   69   # Get the number of attributes
   70   attr_count = 0
   71   if node.attributes:
   72     attr_count = node.attributes.length
   73 
   74   # Print the main tag
   75   if attr_count == 0:
   76     print '%s<%s>' % (' '*indent, node.nodeName)
   77   else:
   78     print '%s<%s' % (' '*indent, node.nodeName)
   79 
   80     all_attributes = []
   81     for (name, value) in node.attributes.items():
   82       all_attributes.append((name, value))
   83       all_attributes.sort(CmpTuple())
   84     for (name, value) in all_attributes:
   85       print '%s  %s="%s"' % (' '*indent, name, value)
   86     print '%s>' % (' '*indent)
   87   if node.nodeValue:
   88     print '%s  %s' % (' '*indent, node.nodeValue)
   89 
   90   for sub_node in node.childNodes:
   91     PrettyPrintNode(sub_node, indent=indent+2)
   92   print '%s</%s>' % (' '*indent, node.nodeName)
   93 
   94 
   95 def FlattenFilter(node):
   96   """Returns a list of all the node and sub nodes."""
   97   node_list = []
   98 
   99   if (node.attributes and
  100       node.getAttribute('Name') == '_excluded_files'):
  101       # We don't add the "_excluded_files" filter.
  102     return []
  103 
  104   for current in node.childNodes:
  105     if current.nodeName == 'Filter':
  106       node_list.extend(FlattenFilter(current))
  107     else:
  108       node_list.append(current)
  109 
  110   return node_list
  111 
  112 
  113 def FixFilenames(filenames, current_directory):
  114   new_list = []
  115   for filename in filenames:
  116     if filename:
  117       for key in REPLACEMENTS:
  118         filename = filename.replace(key, REPLACEMENTS[key])
  119       os.chdir(current_directory)
  120       filename = filename.strip('"\' ')
  121       if filename.startswith('$'):
  122         new_list.append(filename)
  123       else:
  124         new_list.append(os.path.abspath(filename))
  125   return new_list
  126 
  127 
  128 def AbsoluteNode(node):
  129   """Makes all the properties we know about in this node absolute."""
  130   if node.attributes:
  131     for (name, value) in node.attributes.items():
  132       if name in ['InheritedPropertySheets', 'RelativePath',
  133                   'AdditionalIncludeDirectories',
  134                   'IntermediateDirectory', 'OutputDirectory',
  135                   'AdditionalLibraryDirectories']:
  136         # We want to fix up these paths
  137         path_list = value.split(';')
  138         new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
  139         node.setAttribute(name, ';'.join(new_list))
  140       if not value:
  141         node.removeAttribute(name)
  142 
  143 
  144 def CleanupVcproj(node):
  145   """For each sub node, we call recursively this function."""
  146   for sub_node in node.childNodes:
  147     AbsoluteNode(sub_node)
  148     CleanupVcproj(sub_node)
  149 
  150   # Normalize the node, and remove all extranous whitespaces.
  151   for sub_node in node.childNodes:
  152     if sub_node.nodeType == Node.TEXT_NODE:
  153       sub_node.data = sub_node.data.replace("\r", "")
  154       sub_node.data = sub_node.data.replace("\n", "")
  155       sub_node.data = sub_node.data.rstrip()
  156 
  157   # Fix all the semicolon separated attributes to be sorted, and we also
  158   # remove the dups.
  159   if node.attributes:
  160     for (name, value) in node.attributes.items():
  161       sorted_list = sorted(value.split(';'))
  162       unique_list = []
  163       for i in sorted_list:
  164         if not unique_list.count(i):
  165           unique_list.append(i)
  166       node.setAttribute(name, ';'.join(unique_list))
  167       if not value:
  168         node.removeAttribute(name)
  169 
  170   if node.childNodes:
  171     node.normalize()
  172 
  173   # For each node, take a copy, and remove it from the list.
  174   node_array = []
  175   while node.childNodes and node.childNodes[0]:
  176     # Take a copy of the node and remove it from the list.
  177     current = node.childNodes[0]
  178     node.removeChild(current)
  179 
  180     # If the child is a filter, we want to append all its children
  181     # to this same list.
  182     if current.nodeName == 'Filter':
  183       node_array.extend(FlattenFilter(current))
  184     else:
  185       node_array.append(current)
  186 
  187 
  188   # Sort the list.
  189   node_array.sort(CmpNode())
  190 
  191   # Insert the nodes in the correct order.
  192   for new_node in node_array:
  193     # But don't append empty tool node.
  194     if new_node.nodeName == 'Tool':
  195       if new_node.attributes and new_node.attributes.length == 1:
  196         # This one was empty.
  197         continue
  198     if new_node.nodeName == 'UserMacro':
  199       continue
  200     node.appendChild(new_node)
  201 
  202 
  203 def GetConfiguationNodes(vcproj):
  204   #TODO(nsylvain): Find a better way to navigate the xml.
  205   nodes = []
  206   for node in vcproj.childNodes:
  207     if node.nodeName == "Configurations":
  208       for sub_node in node.childNodes:
  209         if sub_node.nodeName == "Configuration":
  210           nodes.append(sub_node)
  211 
  212   return nodes
  213 
  214 
  215 def GetChildrenVsprops(filename):
  216   dom = parse(filename)
  217   if dom.documentElement.attributes:
  218     vsprops = dom.documentElement.getAttribute('InheritedPropertySheets')
  219     return FixFilenames(vsprops.split(';'), os.path.dirname(filename))
  220   return []
  221 
  222 def SeekToNode(node1, child2):
  223   # A text node does not have properties.
  224   if child2.nodeType == Node.TEXT_NODE:
  225     return None
  226 
  227   # Get the name of the current node.
  228   current_name = child2.getAttribute("Name")
  229   if not current_name:
  230     # There is no name. We don't know how to merge.
  231     return None
  232 
  233   # Look through all the nodes to find a match.
  234   for sub_node in node1.childNodes:
  235     if sub_node.nodeName == child2.nodeName:
  236       name = sub_node.getAttribute("Name")
  237       if name == current_name:
  238         return sub_node
  239 
  240   # No match. We give up.
  241   return None
  242 
  243 
  244 def MergeAttributes(node1, node2):
  245   # No attributes to merge?
  246   if not node2.attributes:
  247     return
  248 
  249   for (name, value2) in node2.attributes.items():
  250     # Don't merge the 'Name' attribute.
  251     if name == 'Name':
  252       continue
  253     value1 = node1.getAttribute(name)
  254     if value1:
  255       # The attribute exist in the main node. If it's equal, we leave it
  256       # untouched, otherwise we concatenate it.
  257       if value1 != value2:
  258         node1.setAttribute(name, ';'.join([value1, value2]))
  259     else:
  260       # The attribute does nto exist in the main node. We append this one.
  261       node1.setAttribute(name, value2)
  262 
  263     # If the attribute was a property sheet attributes, we remove it, since
  264     # they are useless.
  265     if name == 'InheritedPropertySheets':
  266       node1.removeAttribute(name)
  267 
  268 
  269 def MergeProperties(node1, node2):
  270   MergeAttributes(node1, node2)
  271   for child2 in node2.childNodes:
  272     child1 = SeekToNode(node1, child2)
  273     if child1:
  274       MergeProperties(child1, child2)
  275     else:
  276       node1.appendChild(child2.cloneNode(True))
  277 
  278 
  279 def main(argv):
  280   """Main function of this vcproj prettifier."""
  281   global ARGUMENTS
  282   ARGUMENTS = argv
  283 
  284   # check if we have exactly 1 parameter.
  285   if len(argv) < 2:
  286     print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
  287            '[key2=value2]' % argv[0])
  288     return 1
  289 
  290   # Parse the keys
  291   for i in range(2, len(argv)):
  292     (key, value) = argv[i].split('=')
  293     REPLACEMENTS[key] = value
  294 
  295   # Open the vcproj and parse the xml.
  296   dom = parse(argv[1])
  297 
  298   # First thing we need to do is find the Configuration Node and merge them
  299   # with the vsprops they include.
  300   for configuration_node in GetConfiguationNodes(dom.documentElement):
  301     # Get the property sheets associated with this configuration.
  302     vsprops = configuration_node.getAttribute('InheritedPropertySheets')
  303 
  304     # Fix the filenames to be absolute.
  305     vsprops_list = FixFilenames(vsprops.strip().split(';'),
  306                                 os.path.dirname(argv[1]))
  307 
  308     # Extend the list of vsprops with all vsprops contained in the current
  309     # vsprops.
  310     for current_vsprops in vsprops_list:
  311       vsprops_list.extend(GetChildrenVsprops(current_vsprops))
  312 
  313     # Now that we have all the vsprops, we need to merge them.
  314     for current_vsprops in vsprops_list:
  315       MergeProperties(configuration_node,
  316                       parse(current_vsprops).documentElement)
  317 
  318   # Now that everything is merged, we need to cleanup the xml.
  319   CleanupVcproj(dom.documentElement)
  320 
  321   # Finally, we use the prett xml function to print the vcproj back to the
  322   # user.
  323   #print dom.toprettyxml(newl="\n")
  324   PrettyPrintNode(dom.documentElement)
  325   return 0
  326 
  327 
  328 if __name__ == '__main__':
  329   sys.exit(main(sys.argv))