mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Support custom derives for generated types (#34356)
* script: Derive more Default implementations for dictionaries. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Support arbitrary derives on generated enums. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Support arbitrary derives for generated dictionaries. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Support arbitrary derives for generated unions. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Derive more impls for generated dicts and unions. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Implement FromStr for generated enums. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * Fix clippy. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * crown: Allow returning unrooted values from Default::default. Signed-off-by: Josh Matthews <josh@joshmatthews.net> --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
3faed9b921
commit
c60e4afbee
10 changed files with 124 additions and 129 deletions
|
@ -527,3 +527,49 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
}
|
||||
|
||||
Dictionaries = {
|
||||
'GPUCanvasConfiguration': {
|
||||
'derives': ['Clone']
|
||||
},
|
||||
|
||||
'GPUExtent3DDict': {
|
||||
'derives': ["MallocSizeOf"],
|
||||
},
|
||||
|
||||
'GPUObjectDescriptorBase': {
|
||||
'derives': ['MallocSizeOf']
|
||||
},
|
||||
|
||||
'GPUTextureDescriptor': {
|
||||
'derives': ["MallocSizeOf"],
|
||||
},
|
||||
|
||||
'HeadersInit': {
|
||||
'derives': ["Clone"],
|
||||
},
|
||||
}
|
||||
|
||||
Enums = {
|
||||
'GPUFeatureName': {
|
||||
'derives': ['Hash', 'Eq']
|
||||
}
|
||||
}
|
||||
|
||||
Unions = {
|
||||
'ByteStringSequenceSequenceOrByteStringByteStringRecord': {
|
||||
'derives': ['Clone']
|
||||
},
|
||||
|
||||
'HTMLCanvasElementOrOffscreenCanvas': {
|
||||
'derives': ['Clone', 'MallocSizeOf']
|
||||
},
|
||||
|
||||
'RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict': {
|
||||
'derives': ['MallocSizeOf']
|
||||
},
|
||||
|
||||
'StringOrUnsignedLong': {
|
||||
'derives': ['Clone'],
|
||||
},
|
||||
}
|
|
@ -2649,7 +2649,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
|
|||
if name not in unionStructs:
|
||||
provider = descriptor or config.getDescriptorProvider()
|
||||
unionStructs[name] = CGList([
|
||||
CGUnionStruct(t, provider),
|
||||
CGUnionStruct(t, provider, config),
|
||||
CGUnionConversionStruct(t, provider)
|
||||
])
|
||||
|
||||
|
@ -4865,14 +4865,18 @@ def getEnumValueName(value):
|
|||
|
||||
|
||||
class CGEnum(CGThing):
|
||||
def __init__(self, enum):
|
||||
def __init__(self, enum, config):
|
||||
CGThing.__init__(self)
|
||||
|
||||
ident = enum.identifier.name
|
||||
enums = ",\n ".join(map(getEnumValueName, list(enum.values())))
|
||||
derives = ["Copy", "Clone", "Debug", "JSTraceable", "MallocSizeOf", "PartialEq"]
|
||||
enum_config = config.getEnumConfig(ident)
|
||||
extra_derives = enum_config.get('derives', [])
|
||||
derives = ', '.join(derives + extra_derives)
|
||||
decl = f"""
|
||||
#[repr(usize)]
|
||||
#[derive(Copy, Clone, Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[derive({derives})]
|
||||
pub enum {ident} {{
|
||||
{enums}
|
||||
}}
|
||||
|
@ -4907,6 +4911,18 @@ impl Default for super::{ident} {{
|
|||
}}
|
||||
}}
|
||||
|
||||
impl std::str::FromStr for super::{ident} {{
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {{
|
||||
pairs
|
||||
.iter()
|
||||
.find(|&&(key, _)| s == key)
|
||||
.map(|&(_, ev)| ev)
|
||||
.ok_or(())
|
||||
}}
|
||||
}}
|
||||
|
||||
impl ToJSValConvertible for super::{ident} {{
|
||||
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {{
|
||||
pairs[*self as usize].0.to_jsval(cx, rval);
|
||||
|
@ -5037,12 +5053,13 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
|
|||
|
||||
|
||||
class CGUnionStruct(CGThing):
|
||||
def __init__(self, type, descriptorProvider):
|
||||
def __init__(self, type, descriptorProvider, config):
|
||||
assert not type.nullable()
|
||||
assert not type.hasNullableType
|
||||
|
||||
CGThing.__init__(self)
|
||||
self.type = type
|
||||
self.derives = config.getUnionConfig(str(type)).get('derives', [])
|
||||
self.descriptorProvider = descriptorProvider
|
||||
|
||||
def membersNeedTracing(self):
|
||||
|
@ -5071,8 +5088,9 @@ class CGUnionStruct(CGThing):
|
|||
]
|
||||
joinedEnumValues = "\n".join(enumValues)
|
||||
joinedEnumConversions = "\n".join(enumConversions)
|
||||
derives = ["JSTraceable"] + self.derives
|
||||
return f"""
|
||||
#[derive(JSTraceable)]
|
||||
#[derive({", ".join(derives)})]
|
||||
pub enum {self.type} {{
|
||||
{joinedEnumValues}
|
||||
}}
|
||||
|
@ -6879,9 +6897,10 @@ class CGNonNamespacedEnum(CGThing):
|
|||
|
||||
|
||||
class CGDictionary(CGThing):
|
||||
def __init__(self, dictionary, descriptorProvider):
|
||||
def __init__(self, dictionary, descriptorProvider, config):
|
||||
self.dictionary = dictionary
|
||||
if all(CGDictionary(d, descriptorProvider).generatable for
|
||||
self.derives = config.getDictConfig(dictionary.identifier.name).get('derives', [])
|
||||
if all(CGDictionary(d, descriptorProvider, config).generatable for
|
||||
d in CGDictionary.getDictionaryDependencies(dictionary)):
|
||||
self.generatable = True
|
||||
else:
|
||||
|
@ -6915,12 +6934,40 @@ class CGDictionary(CGThing):
|
|||
memberDecls = [f" pub {self.makeMemberName(m[0].identifier.name)}: {self.getMemberType(m)},"
|
||||
for m in self.memberInfo]
|
||||
|
||||
derive = ["JSTraceable"]
|
||||
derive = ["JSTraceable"] + self.derives
|
||||
default = ""
|
||||
mustRoot = ""
|
||||
if self.membersNeedTracing():
|
||||
mustRoot = "#[crown::unrooted_must_root_lint::must_root]\n"
|
||||
if not self.hasRequiredFields(self.dictionary):
|
||||
derive += ["Default"]
|
||||
|
||||
# We can't unconditionally derive Default here, because union types can have unique
|
||||
# default values provided for each usage. Instead, whenever possible we re-use the empty()
|
||||
# method that is generated.
|
||||
if not self.hasRequiredFields(self.dictionary):
|
||||
if d.parent:
|
||||
inheritanceDefault = " parent: Default::default(),\n"
|
||||
else:
|
||||
inheritanceDefault = ""
|
||||
if not self.membersNeedTracing():
|
||||
impl = " Self::empty()\n"
|
||||
else:
|
||||
memberDefaults = [f" {self.makeMemberName(m[0].identifier.name)}: Default::default(),"
|
||||
for m in self.memberInfo]
|
||||
joinedDefaults = '\n'.join(memberDefaults)
|
||||
impl = (
|
||||
" Self {\n"
|
||||
f" {inheritanceDefault}{joinedDefaults}"
|
||||
" }\n"
|
||||
)
|
||||
|
||||
default = (
|
||||
f"impl Default for {self.makeClassName(d)} {{\n"
|
||||
" fn default() -> Self {\n"
|
||||
f"{impl}"
|
||||
" }\n"
|
||||
"}\n"
|
||||
)
|
||||
|
||||
joinedMemberDecls = '\n'.join(memberDecls)
|
||||
return (
|
||||
f"#[derive({', '.join(derive)})]\n"
|
||||
|
@ -6928,7 +6975,8 @@ class CGDictionary(CGThing):
|
|||
f"pub struct {self.makeClassName(d)} {{\n"
|
||||
f"{inheritance}"
|
||||
f"{joinedMemberDecls}\n"
|
||||
"}"
|
||||
"}\n"
|
||||
f"{default}"
|
||||
)
|
||||
|
||||
def impl(self):
|
||||
|
@ -7227,7 +7275,7 @@ class CGBindingRoot(CGThing):
|
|||
return
|
||||
|
||||
# Do codegen for all the enums.
|
||||
cgthings = [CGEnum(e) for e in enums]
|
||||
cgthings = [CGEnum(e, config) for e in enums]
|
||||
|
||||
# Do codegen for all the typedefs
|
||||
for t in typedefs:
|
||||
|
@ -7244,7 +7292,7 @@ class CGBindingRoot(CGThing):
|
|||
cgthings.append(CGGeneric(typeDefinition))
|
||||
|
||||
# Do codegen for all the dictionaries.
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider())
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(), config)
|
||||
for d in dictionaries])
|
||||
|
||||
# Do codegen for all the callbacks.
|
||||
|
@ -8145,7 +8193,10 @@ class GlobalGenRoots():
|
|||
descriptors = (set(toBindingModuleFile(d.name) for d in descriptors if d.maybeGetSuperModule() is None)
|
||||
| set(leafModule(d) for d in config.callbacks)
|
||||
| set(leafModule(d) for d in config.getDictionaries()))
|
||||
curr = CGList([CGGeneric(f"pub mod {name};\n") for name in sorted(descriptors)])
|
||||
curr = CGList([CGGeneric(
|
||||
"#[allow(clippy::derivable_impls)]\n"
|
||||
f"pub mod {name};\n"
|
||||
) for name in sorted(descriptors)])
|
||||
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
return curr
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ class Configuration:
|
|||
glbl = {}
|
||||
exec(compile(open(filename).read(), filename, 'exec'), glbl)
|
||||
config = glbl['DOMInterfaces']
|
||||
self.enumConfig = glbl['Enums']
|
||||
self.dictConfig = glbl['Dictionaries']
|
||||
self.unionConfig = glbl['Unions']
|
||||
|
||||
# Build descriptors for all the interfaces we have in the parse data.
|
||||
# This allows callers to specify a subset of interfaces by filtering
|
||||
|
@ -110,6 +113,9 @@ class Configuration:
|
|||
def getEnums(self, webIDLFile):
|
||||
return [e for e in self.enums if e.filename == webIDLFile]
|
||||
|
||||
def getEnumConfig(self, name):
|
||||
return self.enumConfig.get(name, {})
|
||||
|
||||
def getTypedefs(self, webIDLFile):
|
||||
return [e for e in self.typedefs if e.filename == webIDLFile]
|
||||
|
||||
|
@ -121,9 +127,15 @@ class Configuration:
|
|||
|
||||
return [x for x in items if x.filename == webIDLFile]
|
||||
|
||||
def getUnionConfig(self, name):
|
||||
return self.unionConfig.get(name, {})
|
||||
|
||||
def getDictionaries(self, webIDLFile=""):
|
||||
return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile)
|
||||
|
||||
def getDictConfig(self, name):
|
||||
return self.dictConfig.get(name, {})
|
||||
|
||||
def getCallbacks(self, webIDLFile=""):
|
||||
return self._filterForFile(self.callbacks, webIDLFile=webIDLFile)
|
||||
|
||||
|
|
|
@ -624,15 +624,6 @@ impl BluetoothUUID {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clone for StringOrUnsignedLong {
|
||||
fn clone(&self) -> StringOrUnsignedLong {
|
||||
match self {
|
||||
StringOrUnsignedLong::String(s) => StringOrUnsignedLong::String(s.clone()),
|
||||
&StringOrUnsignedLong::UnsignedLong(ul) => StringOrUnsignedLong::UnsignedLong(ul),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn canonical_uuid(alias: u32) -> UUID {
|
||||
UUID::from(format!("{:08x}", &alias) + BASE_UUID)
|
||||
}
|
||||
|
|
|
@ -753,9 +753,3 @@ fn inner_invoke(
|
|||
// Step 3.
|
||||
found
|
||||
}
|
||||
|
||||
impl Default for EventBinding::EventInit {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,9 +102,3 @@ impl ExtendableEventMethods<crate::DomTypeHolder> for ExtendableEvent {
|
|||
self.event.IsTrusted()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExtendableEventInit {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,60 +39,6 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers};
|
||||
use crate::dom::node::{document_from_node, Node, NodeDamage};
|
||||
|
||||
// TODO: make all this derivables available via new Bindings.conf option
|
||||
impl Clone for GPUCanvasConfiguration {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
alphaMode: self.alphaMode,
|
||||
device: self.device.clone(),
|
||||
format: self.format,
|
||||
usage: self.usage,
|
||||
viewFormats: self.viewFormats.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::HTMLCanvasElement(arg0) => Self::HTMLCanvasElement(arg0.clone()),
|
||||
Self::OffscreenCanvas(arg0) => Self::OffscreenCanvas(arg0.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl malloc_size_of::MallocSizeOf for GPUTextureDescriptor {
|
||||
fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
|
||||
let Self {
|
||||
parent,
|
||||
dimension,
|
||||
format,
|
||||
mipLevelCount,
|
||||
sampleCount,
|
||||
size,
|
||||
usage,
|
||||
viewFormats,
|
||||
} = self;
|
||||
parent.size_of(ops) +
|
||||
dimension.size_of(ops) +
|
||||
format.size_of(ops) +
|
||||
mipLevelCount.size_of(ops) +
|
||||
sampleCount.size_of(ops) +
|
||||
size.size_of(ops) +
|
||||
usage.size_of(ops) +
|
||||
viewFormats.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl malloc_size_of::MallocSizeOf for HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
|
||||
match self {
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.size_of(ops),
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.size_of(ops),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn size(&self) -> Size2D<u64> {
|
||||
match self {
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
// check-tidy: no specs after this line
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use indexmap::IndexSet;
|
||||
use js::rust::HandleObject;
|
||||
|
@ -13,7 +11,6 @@ use webgpu::wgt::Features;
|
|||
|
||||
use super::bindings::like::Setlike;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUFeatureNameValues::pairs;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
GPUFeatureName, GPUSupportedFeaturesMethods,
|
||||
};
|
||||
|
@ -24,16 +21,6 @@ use crate::dom::bindings::str::DOMString;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
// manual hash derived
|
||||
// TODO: allow derivables in bindings.conf
|
||||
impl std::hash::Hash for GPUFeatureName {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
core::mem::discriminant(self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for GPUFeatureName {}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUSupportedFeatures {
|
||||
reflector: Reflector,
|
||||
|
@ -152,19 +139,6 @@ pub fn gpu_to_wgt_feature(feature: GPUFeatureName) -> Option<Features> {
|
|||
}
|
||||
}
|
||||
|
||||
// this should be autogenerate by bindings
|
||||
impl FromStr for GPUFeatureName {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
pairs
|
||||
.iter()
|
||||
.find(|&&(key, _)| s == key)
|
||||
.map(|&(_, ev)| ev)
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
||||
#[allow(crown::unrooted_must_root)]
|
||||
impl Setlike for GPUSupportedFeatures {
|
||||
|
|
|
@ -857,16 +857,3 @@ impl From<NetTraitsRequestRedirect> for RequestRedirect {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for HeadersInit {
|
||||
fn clone(&self) -> HeadersInit {
|
||||
match self {
|
||||
HeadersInit::ByteStringSequenceSequence(b) => {
|
||||
HeadersInit::ByteStringSequenceSequence(b.clone())
|
||||
},
|
||||
HeadersInit::ByteStringByteStringRecord(m) => {
|
||||
HeadersInit::ByteStringByteStringRecord(m.clone())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -290,7 +290,7 @@ impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
|
|||
) {
|
||||
let in_new_function = match kind {
|
||||
visit::FnKind::ItemFn(n, _, _) | visit::FnKind::Method(n, _) => {
|
||||
n.as_str() == "new" || n.as_str().starts_with("new_")
|
||||
n.as_str() == "new" || n.as_str().starts_with("new_") || n.as_str() == "default"
|
||||
},
|
||||
visit::FnKind::Closure => return,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue