blob: b997b60da6abd0fe580986d515f5e4fb3699c404 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""This module provides shared functionality to provide Dart metadata for
DOM APIs.
"""
import copy
import json
import logging
import monitored
import os
import re
from generator import ConstantOutputOrder
from htmlrenamer import renamed_html_members, html_interface_renames
_logger = logging.getLogger('dartmetadata')
# Annotations to be placed on native members. The table is indexed by the IDL
# interface and member name, and by IDL return or field type name. Both are
# used to assemble the annotations:
#
# INTERFACE.MEMBER: annotations for member.
# +TYPE: add annotations only if there are member annotations.
# -TYPE: add annotations only if there are no member annotations.
# TYPE: add regardless of member annotations.
_dart2js_annotations = monitored.Dict(
'dartmetadata._dart2js_annotations',
{
'AnimationEffectTiming.duration': [
"@Returns('num|String|Null')",
],
'ArrayBufferView': [
"@Creates('TypedData')",
"@Returns('TypedData|Null')",
],
'CanvasRenderingContext2D.createImageData': [
"@Creates('ImageData|=Object')",
],
'CanvasRenderingContext2D.getImageData': [
"@Creates('ImageData|=Object')",
],
'CanvasRenderingContext2D.webkitGetImageDataHD': [
"@Creates('ImageData|=Object')",
],
'CanvasRenderingContext2D.fillStyle': [
"@Creates('String|CanvasGradient|CanvasPattern')",
"@Returns('String|CanvasGradient|CanvasPattern')",
],
'CanvasRenderingContext2D.strokeStyle': [
"@Creates('String|CanvasGradient|CanvasPattern')",
"@Returns('String|CanvasGradient|CanvasPattern')",
],
'CryptoKey.algorithm': [
"@Creates('Null')",
],
'CustomEvent._detail': [
"@Creates('Null')",
],
# Normally Window is never null, but starting from a <template> element in
# JavaScript, this will be null:
# template.content.ownerDocument.defaultView
'Document.window': [
"@Creates('Window|=Object|Null')",
"@Returns('Window|=Object|Null')",
],
'Document.getElementsByClassName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'Document.getElementsByName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'Document.getElementsByTagName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
# querysSelectorAll never returns `null`.
'Document.querySelectorAll': [
"@Creates('NodeList')",
"@Returns('NodeList')",
],
'DocumentFragment.querySelectorAll': [
"@Creates('NodeList')",
"@Returns('NodeList')",
],
'Element.querySelectorAll': [
"@Creates('NodeList')",
"@Returns('NodeList')",
],
'Element.getBoundingClientRect': [
"@Creates('_DomRect')",
"@Returns('_DomRect|Null')", # TODO(sra): Verify and remove Null.
],
'Element.getClientRects': [
"@Creates('DomRectList')",
"@Returns('DomRectList|Null')",
],
# Methods returning Window can return a local window, or a cross-frame
# window (=Object) that needs wrapping.
'Window': [
"@Creates('Window|=Object')",
"@Returns('Window|=Object')",
],
'Window.openDatabase': [
"@Creates('SqlDatabase')",
],
'Window.showModalDialog': [
"@Creates('Null')",
],
'Element.webkitGetRegionFlowRanges': [
"@Creates('JSExtendableArray')",
"@Returns('JSExtendableArray')",
],
'Element.getElementsByClassName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'Element.getElementsByName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'Element.getElementsByTagName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
"ErrorEvent.error": [
"@Creates('Null')", # Only returns values created elsewhere.
],
# To be in callback with the browser-created Event, we had to have called
# addEventListener on the target, so we avoid
'Event.currentTarget': [
"@Creates('Null')",
"@Returns('EventTarget|=Object|Null')",
],
# Only nodes in the DOM bubble and have target !== currentTarget.
'Event.target': [
"@Creates('Node')",
"@Returns('EventTarget|=Object')",
],
# TODO(sra): Investigate how ExtendableMessageEvent.data is different from
# MessageEvent.data. It might be necessary to put in a method to translate
# the JavaScript wire type into a Dart type.
'ExtendableMessageEvent.data': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
# TODO(sra): We could determine the following by parsing the compound IDL
# type.
'ExtendableMessageEvent.source': [
"@Creates('Client|ServiceWorker|MessagePort')",
"@Returns('Client|ServiceWorker|MessagePort|Null')",
],
'File.lastModifiedDate': [
"@Creates('Null')", # JS date object.
],
'FocusEvent.relatedTarget': [
"@Creates('Null')",
],
'Gamepad.buttons': [
"@Creates('JSExtendableArray|GamepadButton')",
"@Returns('JSExtendableArray')",
],
# Creates a GeolocationPosition or a GeolocationPositionError for a
# callback. See issue #45562.
'Geolocation.getCurrentPosition': [
"@Creates('Geoposition')",
"@Creates('PositionError')",
],
'Geolocation.watchPosition': [
"@Creates('Geoposition')",
"@Creates('PositionError')",
],
'HTMLCanvasElement.getContext': [
"@Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')",
"@Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')",
],
'HTMLInputElement.valueAsDate': [
"@Creates('Null')", # JS date object.
],
# Rather than have the result of an IDBRequest as a union over all possible
# results, we mark the result as instantiating any classes, and mark
# each operation with the classes that it could cause to be asynchronously
# instantiated.
'IDBRequest.result': ["@Creates('Null')"],
# The source is usually a participant in the operation that generated the
# IDBRequest.
'IDBRequest.source': ["@Creates('Null')"],
'IDBFactory.open': ["@Creates('Database')"],
'IDBFactory.webkitGetDatabaseNames': ["@Creates('DomStringList')"],
'IDBObjectStore.put': ["@_annotation_Creates_IDBKey"],
'IDBObjectStore.add': ["@_annotation_Creates_IDBKey"],
'IDBObjectStore.get': ["@annotation_Creates_SerializedScriptValue"],
'IDBObjectStore.openCursor': ["@Creates('Cursor')"],
'IDBIndex.get': ["@annotation_Creates_SerializedScriptValue"],
'IDBIndex.getKey': [
"@annotation_Creates_SerializedScriptValue",
# The source is the object store behind the index.
"@Creates('ObjectStore')",
],
'IDBIndex.openCursor': ["@Creates('Cursor')"],
'IDBIndex.openKeyCursor': ["@Creates('Cursor')"],
'IDBCursorWithValue.value': [
'@annotation_Creates_SerializedScriptValue',
'@annotation_Returns_SerializedScriptValue',
],
'IDBCursor.key': [
"@_annotation_Creates_IDBKey",
"@_annotation_Returns_IDBKey",
],
'IDBCursor.primaryKey': [
"@_annotation_Creates_IDBKey",
"@_annotation_Returns_IDBKey",
],
'IDBCursor.source': [
"@Creates('Null')",
"@Returns('ObjectStore|Index|Null')",
],
'IDBDatabase.version': [
"@Creates('int|String|Null')",
"@Returns('int|String|Null')",
],
'IDBIndex.keyPath': [
"@annotation_Creates_SerializedScriptValue",
],
'IDBKeyRange.lower': [
"@annotation_Creates_SerializedScriptValue",
],
'IDBKeyRange.upper': [
"@annotation_Creates_SerializedScriptValue",
],
'IDBObjectStore.keyPath': [
"@annotation_Creates_SerializedScriptValue",
],
'+IDBOpenDBRequest': [
"@Returns('Request')",
"@Creates('Request')",
],
'+IDBRequest': [
"@Returns('Request')",
"@Creates('Request')",
],
'IDBVersionChangeEvent.newVersion': [
"@Creates('int|String|Null')",
"@Returns('int|String|Null')",
],
'IDBVersionChangeEvent.oldVersion': [
"@Creates('int|String|Null')",
"@Returns('int|String|Null')",
],
'ImageData.data': [
"@Creates('NativeUint8ClampedList')",
"@Returns('NativeUint8ClampedList')",
],
'MediaStream.getAudioTracks': [
"@Creates('JSExtendableArray|MediaStreamTrack')",
"@Returns('JSExtendableArray')",
],
'MediaStream.getVideoTracks': [
"@Creates('JSExtendableArray|MediaStreamTrack')",
"@Returns('JSExtendableArray')",
],
'MessageEvent.data': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
'MessageEvent.ports': ["@Creates('JSExtendableArray')"],
'MessageEvent.source': [
"@Creates('Null')",
"@Returns('EventTarget|=Object')",
],
'Metadata.modificationTime': [
"@Creates('Null')", # JS date object.
],
'MouseEvent.relatedTarget': [
"@Creates('Node')",
"@Returns('EventTarget|=Object|Null')",
],
'Notification.data': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
'PopStateEvent.state': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
'RTCStatsReport.timestamp': [
"@Creates('Null')", # JS date object.
],
'SerializedScriptValue': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
'ServiceWorkerMessageEvent.data': [
"@annotation_Creates_SerializedScriptValue",
"@annotation_Returns_SerializedScriptValue",
],
'ServiceWorkerMessageEvent.source': [
"@Creates('Null')",
"@Returns('ServiceWorker|MessagePort')",
],
'ShadowRoot.getElementsByClassName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'ShadowRoot.getElementsByName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
'ShadowRoot.getElementsByTagName': [
"@Creates('NodeList|HtmlCollection')",
"@Returns('NodeList|HtmlCollection')",
],
# Touch targets are Elements in a Document, or the Document.
'Touch.target': [
"@Creates('Element|Document')",
"@Returns('Element|Document')",
],
'TrackEvent.track': [
"@Creates('Null')",
],
'VTTCue.line': [
"@Creates('Null')",
"@Returns('num|String')",
],
'VTTCue.position': [
"@Creates('Null')",
"@Returns('num|String')",
],
'WebGLRenderingContext.getBufferParameter': [
"@Creates('int|Null')",
"@Returns('int|Null')",
],
'WebGLRenderingContext.getFramebufferAttachmentParameter': [
"@Creates('int|Renderbuffer|Texture|Null')",
"@Returns('int|Renderbuffer|Texture|Null')",
],
'WebGLRenderingContext.getProgramParameter': [
"@Creates('int|bool|Null')",
"@Returns('int|bool|Null')",
],
'WebGLRenderingContext.getRenderbufferParameter': [
"@Creates('int|Null')",
"@Returns('int|Null')",
],
'WebGLRenderingContext.getShaderParameter': [
"@Creates('int|bool|Null')",
"@Returns('int|bool|Null')",
],
'WebGLRenderingContext.getTexParameter': [
"@Creates('int|Null')",
"@Returns('int|Null')",
],
'WebGLRenderingContext.getUniform': [
"@Creates('Null|num|String|bool|JSExtendableArray|"
"NativeFloat32List|NativeInt32List|NativeUint32List')",
"@Returns('Null|num|String|bool|JSExtendableArray|"
"NativeFloat32List|NativeInt32List|NativeUint32List')",
],
'WebGLRenderingContext.getVertexAttrib': [
"@Creates('Null|num|bool|NativeFloat32List|Buffer')",
"@Returns('Null|num|bool|NativeFloat32List|Buffer')",
],
'WebGLRenderingContext.getParameter': [
# Taken from http://www.khronos.org/registry/webgl/specs/latest/
# Section 5.14.3 Setting and getting state
"@Creates('Null|num|String|bool|JSExtendableArray|"
"NativeFloat32List|NativeInt32List|NativeUint32List|"
"Framebuffer|Renderbuffer|Texture')",
"@Returns('Null|num|String|bool|JSExtendableArray|"
"NativeFloat32List|NativeInt32List|NativeUint32List|"
"Framebuffer|Renderbuffer|Texture')",
],
'WebGLRenderingContext.getContextAttributes': [
"@Creates('ContextAttributes|Null')",
],
'XMLHttpRequest.response': [
"@Creates('NativeByteBuffer|Blob|Document|=Object|JSExtendableArray"
"|String|num')",
],
},
dart2jsOnly=True)
_blink_experimental_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
]
_indexed_db_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX, '15')",
"@SupportedBrowser(SupportedBrowser.IE, '10')",
]
_file_system_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
]
_all_but_ie9_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.IE, '10')",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
]
_history_annotations = _all_but_ie9_annotations
_no_ie_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
]
_performance_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.IE)",
]
_rtc_annotations = [ # Note: Firefox nightly builds also support this.
"@SupportedBrowser(SupportedBrowser.CHROME)",
]
_shadow_dom_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME, '26')",
]
_speech_recognition_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME, '25')",
]
_svg_annotations = _all_but_ie9_annotations
_web_sql_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
]
_webgl_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
]
_web_audio_annotations = _webgl_annotations
_webkit_experimental_annotations = [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
]
# Annotations to be placed on generated members.
# The table is indexed as:
# INTERFACE: annotations to be added to the interface declaration
# INTERFACE.MEMBER: annotation to be added to the member declaration
_annotations = monitored.Dict(
'dartmetadata._annotations',
{
'CSSHostRule':
_shadow_dom_annotations,
'WebKitCSSMatrix':
_webkit_experimental_annotations,
'Crypto':
_webkit_experimental_annotations,
'Database':
_web_sql_annotations,
'DatabaseSync':
_web_sql_annotations,
'ApplicationCache': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.IE, '10')",
"@SupportedBrowser(SupportedBrowser.OPERA)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'AudioBufferSourceNode':
_web_audio_annotations,
'AudioContext':
_web_audio_annotations,
'DOMFileSystem':
_file_system_annotations,
'DOMFileSystemSync':
_file_system_annotations,
'Window.indexedDB':
_indexed_db_annotations,
'Window.openDatabase':
_web_sql_annotations,
'Window.performance':
_performance_annotations,
'Window.webkitNotifications':
_webkit_experimental_annotations,
'Window.webkitRequestFileSystem':
_file_system_annotations,
'Window.webkitResolveLocalFileSystemURL':
_file_system_annotations,
'Element.createShadowRoot': [
"@SupportedBrowser(SupportedBrowser.CHROME, '25')",
],
'Element.ontransitionend':
_all_but_ie9_annotations,
# Placeholder to add experimental flag, implementation for this is
# pending in a separate CL.
'Element.webkitMatchesSelector': [],
'Event.clipboardData': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'FormData':
_all_but_ie9_annotations,
'HashChangeEvent': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'History.pushState':
_history_annotations,
'History.replaceState':
_history_annotations,
'HTMLContentElement':
_shadow_dom_annotations,
'HTMLDataListElement':
_all_but_ie9_annotations,
'HTMLDetailsElement':
_webkit_experimental_annotations,
'HTMLEmbedElement': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.IE)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'HTMLKeygenElement':
_webkit_experimental_annotations,
'HTMLMeterElement':
_no_ie_annotations,
'HTMLObjectElement': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.IE)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'HTMLOutputElement':
_no_ie_annotations,
'HTMLProgressElement':
_all_but_ie9_annotations,
'HTMLShadowElement':
_shadow_dom_annotations,
'HTMLTemplateElement':
_blink_experimental_annotations,
'HTMLTrackElement': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.IE, '10')",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'IDBFactory':
_indexed_db_annotations,
'IDBDatabase':
_indexed_db_annotations,
'MediaStream':
_rtc_annotations,
'MediaStreamEvent':
_rtc_annotations,
'MediaStreamTrack':
_rtc_annotations,
'MediaStreamTrackEvent':
_rtc_annotations,
'MediaSource': [
# TODO(alanknight): This works on Firefox 33 behind a flag and in Safari
# desktop, but not mobile. On theory that static false positives are worse
# than negatives, leave those out for now. Update once they're available.
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.IE, '11')",
],
'MutationObserver': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
'Performance':
_performance_annotations,
'PopStateEvent':
_history_annotations,
'RTCIceCandidate':
_rtc_annotations,
'RTCPeerConnection':
_rtc_annotations,
'RTCSessionDescription':
_rtc_annotations,
'ShadowRoot':
_shadow_dom_annotations,
'SpeechRecognition':
_speech_recognition_annotations,
'SpeechRecognitionAlternative':
_speech_recognition_annotations,
'SpeechRecognitionError':
_speech_recognition_annotations,
'SpeechRecognitionEvent':
_speech_recognition_annotations,
'SpeechRecognitionResult':
_speech_recognition_annotations,
'SVGAltGlyphElement':
_no_ie_annotations,
'SVGAnimateElement':
_no_ie_annotations,
'SVGAnimateMotionElement':
_no_ie_annotations,
'SVGAnimateTransformElement':
_no_ie_annotations,
'SVGFEBlendElement':
_svg_annotations,
'SVGFEColorMatrixElement':
_svg_annotations,
'SVGFEComponentTransferElement':
_svg_annotations,
'SVGFEConvolveMatrixElement':
_svg_annotations,
'SVGFEDiffuseLightingElement':
_svg_annotations,
'SVGFEDisplacementMapElement':
_svg_annotations,
'SVGFEDistantLightElement':
_svg_annotations,
'SVGFEFloodElement':
_svg_annotations,
'SVGFEFuncAElement':
_svg_annotations,
'SVGFEFuncBElement':
_svg_annotations,
'SVGFEFuncGElement':
_svg_annotations,
'SVGFEFuncRElement':
_svg_annotations,
'SVGFEGaussianBlurElement':
_svg_annotations,
'SVGFEImageElement':
_svg_annotations,
'SVGFEMergeElement':
_svg_annotations,
'SVGFEMergeNodeElement':
_svg_annotations,
'SVGFEMorphologyElement':
_svg_annotations,
'SVGFEOffsetElement':
_svg_annotations,
'SVGFEPointLightElement':
_svg_annotations,
'SVGFESpecularLightingElement':
_svg_annotations,
'SVGFESpotLightElement':
_svg_annotations,
'SVGFETileElement':
_svg_annotations,
'SVGFETurbulenceElement':
_svg_annotations,
'SVGFilterElement':
_svg_annotations,
'SVGForeignObjectElement':
_no_ie_annotations,
'SVGSetElement':
_no_ie_annotations,
'SQLTransaction':
_web_sql_annotations,
'SQLTransactionSync':
_web_sql_annotations,
'WebGLRenderingContext':
_webgl_annotations,
'WebSocket':
_all_but_ie9_annotations,
'Worker':
_all_but_ie9_annotations,
'XMLHttpRequest.overrideMimeType':
_no_ie_annotations,
'XMLHttpRequest.response':
_all_but_ie9_annotations,
'XMLHttpRequestEventTarget.onloadend':
_all_but_ie9_annotations,
'XMLHttpRequestEventTarget.onprogress':
_all_but_ie9_annotations,
'XSLTProcessor': [
"@SupportedBrowser(SupportedBrowser.CHROME)",
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
"@SupportedBrowser(SupportedBrowser.SAFARI)",
],
})
# TODO(blois): minimize noise and enable by default.
_monitor_type_metadata = False
class DartMetadata(object):
def __init__(self,
api_status_path,
doc_comments_path,
logging_level=logging.WARNING):
_logger.setLevel(logging_level)
self._api_status_path = api_status_path
status_file = open(self._api_status_path, 'r+')
self._types = json.load(status_file)
status_file.close()
comments_file = open(doc_comments_path, 'r+')
self._doc_comments = json.load(comments_file)
comments_file.close()
if _monitor_type_metadata:
monitored_interfaces = {}
for interface_id, interface_data in self._types.items():
monitored_interface = interface_data.copy()
monitored_interface['members'] = monitored.Dict(
'dartmetadata.%s' % interface_id, interface_data['members'])
monitored_interfaces[interface_id] = monitored_interface
self._monitored_types = monitored.Dict(
'dartmetadata._monitored_types', monitored_interfaces)
else:
self._monitored_types = self._types
def GetFormattedMetadata(self,
library_name,
interface,
member_id=None,
indentation=''):
""" Gets all comments and annotations for an interface or member.
"""
return self.FormatMetadata(
self.GetMetadata(library_name, interface, member_id), indentation)
def GetMetadata(self,
library_name,
interface,
member_name=None,
source_member_name=None):
""" Gets all comments and annotations for an interface or member.
Args:
source_member_name: If the member is dependent on a different member
then this is used to apply the support annotations from the other
member.
"""
annotations = self._GetComments(library_name, interface, member_name)
annotations = annotations + self._GetCommonAnnotations(
interface, member_name, source_member_name)
return annotations
def GetDart2JSMetadata(
self,
idl_type,
library_name,
interface,
member_name,
):
""" Gets all annotations for Dart2JS members- including annotations for
both dart2js and dartium.
"""
annotations = self.GetMetadata(library_name, interface, member_name)
ann2 = self._GetDart2JSSpecificAnnotations(idl_type, interface.id,
member_name)
if ann2:
if annotations:
annotations.extend(ann2)
else:
annotations = ann2
return annotations
def IsSuppressed(self, interface, member_name):
annotations = self._GetSupportLevelAnnotations(interface.id,
member_name)
return any(
annotation.startswith('@removed') for annotation in annotations)
def _GetCommonAnnotations(self,
interface,
member_name=None,
source_member_name=None):
annotations = []
if member_name:
key = '%s.%s' % (interface.id, member_name)
dom_name = '%s.%s' % (interface.javascript_binding_name,
member_name)
# DomName annotation is needed for dblclick ACX plugin analyzer.
if member_name == 'dblclickEvent' or member_name == 'ondblclick':
annotations.append("@DomName('" + dom_name + "')")
else:
key = interface.id
if key in _annotations:
annotations.extend(_annotations[key])
if (not member_name and
interface.javascript_binding_name.startswith('WebKit') and
interface.id not in html_interface_renames):
annotations.extend(_webkit_experimental_annotations)
if (member_name and member_name.startswith('webkit') and
key not in renamed_html_members):
annotations.extend(_webkit_experimental_annotations)
if source_member_name:
member_name = source_member_name
support_annotations = self._GetSupportLevelAnnotations(
interface.id, member_name)
for annotation in support_annotations:
if annotation not in annotations:
annotations.append(annotation)
return annotations
def _GetComments(self, library_name, interface, member_name=None):
""" Gets all comments for the interface or member and returns a list. """
# Add documentation from JSON.
comments = []
library_name = 'dart.dom.%s' % library_name
if library_name in self._doc_comments:
library_info = self._doc_comments[library_name]
if interface.id in library_info:
interface_info = library_info[interface.id]
if member_name:
if 'members' in interface_info and member_name in interface_info[
'members']:
comments = interface_info['members'][member_name]
elif 'comment' in interface_info:
comments = interface_info['comment']
if comments:
comments = ['\n'.join(comments)]
return comments
def AnyConversionAnnotations(self, idl_type, interface_name, member_name):
if (_annotations.get('%s.%s' % (interface_name, member_name)) or
self._GetDart2JSSpecificAnnotations(idl_type, interface_name,
member_name)):
return True
else:
return False
def FormatMetadata(self, metadata, indentation):
if metadata:
newline = '\n%s' % indentation
result = newline.join(metadata) + newline
return result
return ''
def _GetDart2JSSpecificAnnotations(self, idl_type, interface_name,
member_name):
""" Finds dart2js-specific annotations. This does not include ones shared with
dartium.
"""
ann1 = _dart2js_annotations.get("%s.%s" % (interface_name, member_name))
if ann1:
ann2 = _dart2js_annotations.get('+' + idl_type)
if ann2:
return ann2 + ann1
ann2 = _dart2js_annotations.get(idl_type)
if ann2:
return ann2 + ann1
return ann1
ann2 = _dart2js_annotations.get('-' + idl_type)
if ann2:
return ann2
ann2 = _dart2js_annotations.get(idl_type)
return ann2
def _GetSupportInfo(self, interface_id, member_id=None):
""" Looks up the interface or member in the DOM status list and returns the
support level for it.
"""
if interface_id in self._monitored_types:
type_info = self._monitored_types[interface_id]
else:
type_info = {
'members': {},
'support_level': 'untriaged',
}
self._types[interface_id] = type_info
if not member_id:
return type_info
members = type_info['members']
if member_id in members:
member_info = members[member_id]
else:
if member_id == interface_id:
member_info = {}
else:
member_info = {'support_level': 'untriaged'}
members[member_id] = member_info
return member_info
def _GetSupportLevelAnnotations(self, interface_id, member_id=None):
""" Gets annotations for API support status.
"""
support_info = self._GetSupportInfo(interface_id, member_id)
dart_action = support_info.get('dart_action')
support_level = support_info.get('support_level')
comment = support_info.get('comment')
annotations = []
# TODO(blois): should add an annotation for the comment, but keeping out
# to keep the initial diff a bit more localized.
#if comment:
# annotations.append('// %s' % comment)
if dart_action:
if dart_action == 'unstable':
annotations.append('@Unstable()')
elif dart_action == 'suppress':
if comment:
annotations.append('// %s' % comment)
anAnnotation = 'deprecated'
if member_id:
anAnnotation = 'removed'
annotations.append('@%s // %s' % (anAnnotation, support_level))
pass
elif dart_action == 'stable':
pass
else:
_logger.warn(
'Unknown dart_action - %s:%s' % (interface_id, member_id))
elif support_level == 'stable':
pass
elif support_level == 'deprecated':
if comment:
annotations.append('// %s' % comment)
annotations.append('@deprecated')
elif support_level is None:
pass
else:
_logger.warn(
'Unknown support_level - %s:%s' % (interface_id, member_id))
return annotations
def Flush(self):
json_file = open(self._api_status_path, 'w+')
json.dump(
self._types,
json_file,
indent=2,
separators=(',', ': '),
sort_keys=True)
json_file.close()