OLD | NEW |
| (Empty) |
1 # Copyright (c) 2011 Google Inc. All rights reserved. | |
2 # | |
3 # Redistribution and use in source and binary forms, with or without | |
4 # modification, are permitted provided that the following conditions are | |
5 # met: | |
6 # | |
7 # * Redistributions of source code must retain the above copyright | |
8 # notice, this list of conditions and the following disclaimer. | |
9 # * Redistributions in binary form must reproduce the above | |
10 # copyright notice, this list of conditions and the following disclaimer | |
11 # in the documentation and/or other materials provided with the | |
12 # distribution. | |
13 # * Neither the name of Google Inc. nor the names of its | |
14 # contributors may be used to endorse or promote products derived from | |
15 # this software without specific prior written permission. | |
16 # | |
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | |
29 import re | |
30 | |
31 | |
32 class _Intersection(object): | |
33 def __init__(self, *tokens): | |
34 self._tokens = tokens | |
35 | |
36 def matches(self, tokens): | |
37 for token in self._tokens: | |
38 if token not in tokens and (token + 's') not in tokens: | |
39 return False | |
40 return True | |
41 | |
42 | |
43 class _Area(object): | |
44 def __init__(self, name, tokens=None): | |
45 self._name = name | |
46 self._tokens = tokens if tokens else [self._name_to_token(name)] | |
47 | |
48 def _name_to_token(self, word): | |
49 token = word.lower() | |
50 return token[:-1] if word[-1] == 's' else token | |
51 | |
52 def matches(self, tokens): | |
53 # FIXME: Support pluraization properly | |
54 for token in self._tokens: | |
55 if isinstance(token, _Intersection): | |
56 if token.matches(tokens): | |
57 return True | |
58 elif token in tokens or (token + 's') in tokens: | |
59 return True | |
60 return False | |
61 | |
62 def name(self): | |
63 return self._name | |
64 | |
65 def tokens(self): | |
66 return self._tokens | |
67 | |
68 contribution_areas = [ | |
69 _Area('ARM JIT', ['arm']), | |
70 # FIXME: 'Accelerated compositing / GPU acceleration' | |
71 _Area('Accessibility'), | |
72 _Area('Android port', ['android']), | |
73 _Area('Animation', ['animation', 'animator']), | |
74 _Area('Apple\'s Windows port', ['win', 'windows']), # FIXME: need to exclud
e chromium... | |
75 _Area('Autotools Build', ['autotools']), | |
76 _Area('Basic types and data structures (WTF)', ['wtf']), | |
77 # FIXME: 'Bidirectional text' | |
78 # FIXME: 'Build/test infrastructure (stuff under Tools/Scripts)' | |
79 _Area('CMake Build', ['cmakelist']), | |
80 _Area('CSS (Cascading Style Sheets)', ['css']), | |
81 _Area('CSS Transforms', [_Intersection('css', 'transforms')]), | |
82 _Area('CSS/SVG Filters', [_Intersection('css', 'filters'), _Intersection('sv
g', 'filters')]), | |
83 _Area('CURL HTTP Backend', ['CURL']), | |
84 _Area('Resource Cache', [_Intersection('loader', 'cache')]), | |
85 _Area('Memory Cache', [_Intersection('graphics', 'cache')]), | |
86 _Area('Cairo'), | |
87 _Area('Canvas'), | |
88 _Area('Chromium Linux', [_Intersection('chromium', 'linux')]), | |
89 # FIXME: 'Commit Queue' | |
90 _Area('Core DOM', ['dom']), | |
91 _Area('Core Graphics', ['cg']), | |
92 _Area('Bindings'), | |
93 _Area('DOM Storage', ['storage']), | |
94 _Area('Drag and Drop', ['drag']), | |
95 _Area('DumpRenderTree'), | |
96 _Area('EFL', ['efl']), | |
97 _Area('Editing / Selection', ['editing']), | |
98 _Area('Event Handling', ['event']), | |
99 _Area('FastMalloc'), | |
100 _Area('File API', ['fileapi']), | |
101 _Area('Fonts'), | |
102 _Area('Forms'), | |
103 # FIXME: 'Frame Flattening' | |
104 _Area('Frame Loader'), | |
105 # FIXME: 'General' Maybe auto-detect people contributing to all subdirectories? | |
106 _Area('Geolocation API', ['geolocation']), | |
107 _Area('Graphics', ['graphics']), | |
108 _Area('HTML', ['html']), | |
109 _Area('HTML Parser', [_Intersection('html', 'parser')]), # FIXME: matches h
tml/track/WebVTTParser.cpp | |
110 _Area('HTML5 Media Support', ['media']), | |
111 _Area('History', ['history']), | |
112 # FIXME: 'Hit testing' | |
113 _Area('Image Decoder', ['imagedecoder']), | |
114 # FIXME: 'Input methods' | |
115 _Area('JSC Bindings', [_Intersection('bindings', 'js')]), | |
116 _Area('JavaScriptCore'), | |
117 _Area('JavaScriptCore Regular Expressions', [_Intersection('JavaScriptCore',
'regexp')]), | |
118 # FIXME: 'Layout tests' but what does it mean to say you're an expert on layout
tests? Maybe worked on tools? | |
119 _Area('Loader', ['loader']), | |
120 _Area('MathML'), | |
121 _Area('Memory Use / Leaks', ['leaks']), # Probably need more tokens | |
122 _Area('MessagePorts'), | |
123 _Area('Network', [_Intersection('platform', 'network')]), | |
124 _Area('new-run-webkit-tests', ['layout_tests']), | |
125 _Area('OpenVG graphics backend', ['openvg']), | |
126 # FIXME: 'Performance' | |
127 _Area('Plug-ins', ['plugins']), | |
128 _Area('Printing', ['printing', 'print']), | |
129 _Area('Rendering'), | |
130 _Area('SVG (Scalable Vector Graphics)', ['svg']), | |
131 _Area('Scrollbars', ['scroll']), | |
132 _Area('Security'), # Probably need more tokens | |
133 # FIXME: 'Shadow DOM' | |
134 _Area('Skia'), | |
135 _Area('Soup Network Backend', ['soup']), | |
136 # FIXME: 'Spell Checking' just need tokens | |
137 _Area('Tables', ['htmltable', 'rendertable']), | |
138 # FIXME: 'Text Encoding' | |
139 # FIXME: 'Text Layout' | |
140 _Area('The Chromium Port', ['chromium']), | |
141 _Area('The EFLWebKit Port', ['efl']), | |
142 _Area('The WebKitGTK+ Port', ['gtk']), | |
143 _Area('The Haiku Port', ['haiku']), | |
144 _Area('The QtWebKit Port', ['qt']), | |
145 _Area('The WinCE Port', ['wince']), | |
146 _Area('The WinCairo Port', ['cairo']), | |
147 _Area('The wxWebKit Port', ['wx']), | |
148 _Area('Threading', ['thread']), | |
149 _Area('Tools'), | |
150 _Area('Touch Support', ['touch']), | |
151 _Area('Transforms', ['transforms']), # There's also CSS transforms | |
152 _Area('Transitions', ['transitions']), # This only matches transition event
s at the moment | |
153 _Area('URL Parsing', ['KURL']), # Probably need more tokens | |
154 _Area('V8', ['v8']), | |
155 _Area('V8 Bindings', [_Intersection('bindings', 'v8')]), | |
156 _Area('Web Inspector / Developer Tools', ['inspector']), | |
157 _Area('Web Timing', ['PerformanceNavigation', 'PerformanceTiming']), # more
tokens? | |
158 _Area('WebCore Icon Database', ['icon']), | |
159 _Area('WebGL', ['webgl']), | |
160 _Area('WebKit Websites', ['websites']), | |
161 _Area('WebKit2'), | |
162 _Area('WebSQL Databases', [_Intersection('storage', 'database')]), | |
163 _Area('WebSockets'), | |
164 _Area('Workers'), | |
165 _Area('XML'), | |
166 _Area('XMLHttpRequest'), | |
167 _Area('XSLT'), | |
168 _Area('XSSAuditor'), | |
169 _Area('WebKit API Tests', ['TestWebKitAPI']), | |
170 _Area('webkit-patch', [_Intersection('webkitpy', 'commands')]), | |
171 ] | |
172 | |
173 | |
174 class ContributionAreas(object): | |
175 def __init__(self, filesystem, table=contribution_areas): | |
176 self._filesystem = filesystem | |
177 self._contribution_areas = table | |
178 | |
179 def names(self): | |
180 return [area.name() for area in self._contribution_areas] | |
181 | |
182 def _split_path(self, path): | |
183 result = [] | |
184 while path and len(path): | |
185 next_path, tail = self._filesystem.split(path) | |
186 if path == next_path: | |
187 break | |
188 if tail and len(tail): | |
189 result.append(tail) | |
190 path = next_path | |
191 return result | |
192 | |
193 def _split_camelcase(self, name, transform=lambda x: x): | |
194 result = [] | |
195 while name and len(name): | |
196 m = re.match('^([A-Z][a-z0-9]+)|([A-Z0-9]+(?=([A-Z][a-z0-9]|\.|$)))'
, name) | |
197 if m: | |
198 result.append(transform(m.group(0))) | |
199 name = name[m.end():] | |
200 else: | |
201 return result | |
202 return result | |
203 | |
204 def areas_for_touched_files(self, touched_files): | |
205 areas = set() | |
206 for file_path in touched_files: | |
207 split_file_path = self._split_path(file_path) | |
208 tokenized_file_path = None | |
209 tokenized_file_path = sum([self._split_camelcase(token, lambda x: x.
lower()) for token in split_file_path], []) | |
210 for area in self._contribution_areas: | |
211 if area.matches(split_file_path) or area.matches(tokenized_file_
path): | |
212 areas.add(area.name()) | |
213 return areas | |
OLD | NEW |