blob: aad661e357c50d4ce2b3825c0d02f938562ab9b7 [file] [log] [blame]
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
import sys
import idl_schema
import json_schema
from cpp_namespace_environment import CppNamespaceEnvironment
from model import Model, UnixName
def GenerateFilenames(full_namespace):
# Try to find the file defining the namespace. Eg. for
# nameSpace.sub_name_space.Type' the following heuristics looks for:
# 1. name_space_sub_name_space.json,
# 2. name_space_sub_name_space.idl,
# 3. sub_name_space.json,
# 4. sub_name_space.idl,
# 5. etc.
sub_namespaces = full_namespace.split('.')
filenames = [ ]
basename = None
for namespace in reversed(sub_namespaces):
if basename is not None:
basename = UnixName(namespace + '.' + basename)
else:
basename = UnixName(namespace)
for ext in ['json', 'idl']:
filenames.append('%s.%s' % (basename, ext))
return filenames
class SchemaLoader(object):
'''Resolves a type name into the namespace the type belongs to.
Properties:
- |root| path to the root directory.
- |path| path to the directory with the API header files, relative to the
root.
- |include_rules| List containing tuples with (path, cpp_namespace_pattern)
used when searching for types.
- |cpp_namespace_pattern| Default namespace pattern
'''
def __init__(self,
root,
path,
include_rules,
cpp_namespace_pattern):
self._root = root
self._include_rules = [(path, cpp_namespace_pattern)]
self._include_rules.extend(include_rules)
def ResolveNamespace(self, full_namespace):
filenames = GenerateFilenames(full_namespace)
for path, cpp_namespace in self._include_rules:
cpp_namespace_environment = None
if cpp_namespace:
cpp_namespace_environment = CppNamespaceEnvironment(cpp_namespace)
for filename in reversed(filenames):
filepath = os.path.join(path, filename);
if os.path.exists(os.path.join(self._root, filepath)):
return Model().AddNamespace(
self.LoadSchema(filepath)[0],
filepath,
environment=cpp_namespace_environment)
return None
def ResolveType(self, full_name, default_namespace):
name_parts = full_name.rsplit('.', 1)
if len(name_parts) == 1:
if full_name not in default_namespace.types:
return None
return default_namespace
full_namespace, type_name = full_name.rsplit('.', 1)
namespace = self.ResolveNamespace(full_namespace)
if namespace and type_name in namespace.types:
return namespace
return None
def LoadSchema(self, schema):
'''Load a schema definition. The schema parameter must be a file name
with the full path relative to the root.'''
_, schema_extension = os.path.splitext(schema)
schema_path = os.path.join(self._root, schema)
if schema_extension == '.json':
api_defs = json_schema.Load(schema_path)
elif schema_extension == '.idl':
api_defs = idl_schema.Load(schema_path)
else:
sys.exit('Did not recognize file extension %s for schema %s' %
(schema_extension, schema))
return api_defs