132 lines
3.8 KiB
Python
132 lines
3.8 KiB
Python
|
# vim:fileencoding=utf-8:noet
|
||
|
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||
|
|
||
|
import re
|
||
|
|
||
|
from powerline.lint.markedjson.error import MarkedError
|
||
|
from powerline.lint.markedjson import nodes
|
||
|
|
||
|
|
||
|
class ResolverError(MarkedError):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class BaseResolver:
|
||
|
DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str'
|
||
|
DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq'
|
||
|
DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map'
|
||
|
|
||
|
yaml_implicit_resolvers = {}
|
||
|
yaml_path_resolvers = {}
|
||
|
|
||
|
def __init__(self):
|
||
|
self.resolver_exact_paths = []
|
||
|
self.resolver_prefix_paths = []
|
||
|
|
||
|
@classmethod
|
||
|
def add_implicit_resolver(cls, tag, regexp, first):
|
||
|
if 'yaml_implicit_resolvers' not in cls.__dict__:
|
||
|
cls.yaml_implicit_resolvers = cls.yaml_implicit_resolvers.copy()
|
||
|
if first is None:
|
||
|
first = [None]
|
||
|
for ch in first:
|
||
|
cls.yaml_implicit_resolvers.setdefault(ch, []).append((tag, regexp))
|
||
|
|
||
|
def descend_resolver(self, current_node, current_index):
|
||
|
if not self.yaml_path_resolvers:
|
||
|
return
|
||
|
exact_paths = {}
|
||
|
prefix_paths = []
|
||
|
if current_node:
|
||
|
depth = len(self.resolver_prefix_paths)
|
||
|
for path, kind in self.resolver_prefix_paths[-1]:
|
||
|
if self.check_resolver_prefix(depth, path, kind, current_node, current_index):
|
||
|
if len(path) > depth:
|
||
|
prefix_paths.append((path, kind))
|
||
|
else:
|
||
|
exact_paths[kind] = self.yaml_path_resolvers[path, kind]
|
||
|
else:
|
||
|
for path, kind in self.yaml_path_resolvers:
|
||
|
if not path:
|
||
|
exact_paths[kind] = self.yaml_path_resolvers[path, kind]
|
||
|
else:
|
||
|
prefix_paths.append((path, kind))
|
||
|
self.resolver_exact_paths.append(exact_paths)
|
||
|
self.resolver_prefix_paths.append(prefix_paths)
|
||
|
|
||
|
def ascend_resolver(self):
|
||
|
if not self.yaml_path_resolvers:
|
||
|
return
|
||
|
self.resolver_exact_paths.pop()
|
||
|
self.resolver_prefix_paths.pop()
|
||
|
|
||
|
def check_resolver_prefix(self, depth, path, kind, current_node, current_index):
|
||
|
node_check, index_check = path[depth - 1]
|
||
|
if isinstance(node_check, str):
|
||
|
if current_node.tag != node_check:
|
||
|
return
|
||
|
elif node_check is not None:
|
||
|
if not isinstance(current_node, node_check):
|
||
|
return
|
||
|
if index_check is True and current_index is not None:
|
||
|
return
|
||
|
if ((index_check is False or index_check is None)
|
||
|
and current_index is None):
|
||
|
return
|
||
|
if isinstance(index_check, str):
|
||
|
if not (isinstance(current_index, nodes.ScalarNode) and index_check == current_index.value):
|
||
|
return
|
||
|
elif isinstance(index_check, int) and not isinstance(index_check, bool):
|
||
|
if index_check != current_index:
|
||
|
return
|
||
|
return True
|
||
|
|
||
|
def resolve(self, kind, value, implicit, mark=None):
|
||
|
if kind is nodes.ScalarNode and implicit[0]:
|
||
|
if value == '':
|
||
|
resolvers = self.yaml_implicit_resolvers.get('', [])
|
||
|
else:
|
||
|
resolvers = self.yaml_implicit_resolvers.get(value[0], [])
|
||
|
resolvers += self.yaml_implicit_resolvers.get(None, [])
|
||
|
for tag, regexp in resolvers:
|
||
|
if regexp.match(value):
|
||
|
return tag
|
||
|
else:
|
||
|
self.echoerr(
|
||
|
'While resolving plain scalar', None,
|
||
|
'expected floating-point value, integer, null or boolean, but got %r' % value,
|
||
|
mark
|
||
|
)
|
||
|
return self.DEFAULT_SCALAR_TAG
|
||
|
if kind is nodes.ScalarNode:
|
||
|
return self.DEFAULT_SCALAR_TAG
|
||
|
elif kind is nodes.SequenceNode:
|
||
|
return self.DEFAULT_SEQUENCE_TAG
|
||
|
elif kind is nodes.MappingNode:
|
||
|
return self.DEFAULT_MAPPING_TAG
|
||
|
|
||
|
|
||
|
class Resolver(BaseResolver):
|
||
|
pass
|
||
|
|
||
|
|
||
|
Resolver.add_implicit_resolver(
|
||
|
'tag:yaml.org,2002:bool',
|
||
|
re.compile(r'''^(?:true|false)$''', re.X),
|
||
|
list('yYnNtTfFoO'))
|
||
|
|
||
|
Resolver.add_implicit_resolver(
|
||
|
'tag:yaml.org,2002:float',
|
||
|
re.compile(r'^-?(?:0|[1-9]\d*)(?=[.eE])(?:\.\d+)?(?:[eE][-+]?\d+)?$', re.X),
|
||
|
list('-0123456789'))
|
||
|
|
||
|
Resolver.add_implicit_resolver(
|
||
|
'tag:yaml.org,2002:int',
|
||
|
re.compile(r'^(?:0|-?[1-9]\d*)$', re.X),
|
||
|
list('-0123456789'))
|
||
|
|
||
|
Resolver.add_implicit_resolver(
|
||
|
'tag:yaml.org,2002:null',
|
||
|
re.compile(r'^null$', re.X),
|
||
|
['n'])
|