CodeGenerator.pm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. #
  2. # WebKit IDL parser
  3. #
  4. # Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
  5. # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
  6. # Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  7. # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
  8. # Copyright (C) Research In Motion Limited 2010. All rights reserved.
  9. # Copyright (C) 2013 Samsung Electronics. All rights reserved.
  10. #
  11. # This library is free software; you can redistribute it and/or
  12. # modify it under the terms of the GNU Library General Public
  13. # License as published by the Free Software Foundation; either
  14. # version 2 of the License, or (at your option) any later version.
  15. #
  16. # This library is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. # Library General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU Library General Public License
  22. # along with this library; see the file COPYING.LIB. If not, write to
  23. # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  24. # Boston, MA 02110-1301, USA.
  25. #
  26. package CodeGenerator;
  27. use strict;
  28. use File::Find;
  29. my $useDocument = "";
  30. my $useGenerator = "";
  31. my $useOutputDir = "";
  32. my $useOutputHeadersDir = "";
  33. my $useDirectories = "";
  34. my $useLayerOnTop = 0;
  35. my $preprocessor;
  36. my $writeDependencies = 0;
  37. my $defines = "";
  38. my $targetIdlFilePath = "";
  39. my $codeGenerator = 0;
  40. my $verbose = 0;
  41. my %numericTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1,
  42. "unsigned int" => 1, "unsigned short" => 1,
  43. "unsigned long" => 1, "unsigned long long" => 1,
  44. "float" => 1, "double" => 1, "byte" => 1,
  45. "octet" => 1);
  46. my %primitiveTypeHash = ( "boolean" => 1, "void" => 1, "Date" => 1);
  47. my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1);
  48. # WebCore types used directly in IDL files.
  49. my %webCoreTypeHash = (
  50. "CompareHow" => 1,
  51. "SerializedScriptValue" => 1,
  52. "Dictionary" => 1
  53. );
  54. my %enumTypeHash = ();
  55. my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1);
  56. my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1,
  57. "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1,
  58. "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
  59. "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1,
  60. "SVGAnimatedPreserveAspectRatio" => 1,
  61. "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
  62. "SVGAnimatedTransformList" => 1);
  63. my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1,
  64. "onerror" => 1, "onload" => 1, "onmousedown" => 1,
  65. "onmouseenter" => 1, "onmouseleave" => 1,
  66. "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1,
  67. "onmouseup" => 1, "onresize" => 1, "onscroll" => 1,
  68. "onunload" => 1);
  69. my %svgTypeNeedingTearOff = (
  70. "SVGAngle" => "SVGPropertyTearOff<SVGAngle>",
  71. "SVGLength" => "SVGPropertyTearOff<SVGLength>",
  72. "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>",
  73. "SVGMatrix" => "SVGPropertyTearOff<SVGMatrix>",
  74. "SVGNumber" => "SVGPropertyTearOff<float>",
  75. "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>",
  76. "SVGPathSegList" => "SVGPathSegListPropertyTearOff",
  77. "SVGPoint" => "SVGPropertyTearOff<FloatPoint>",
  78. "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>",
  79. "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>",
  80. "SVGRect" => "SVGPropertyTearOff<FloatRect>",
  81. "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>",
  82. "SVGTransform" => "SVGPropertyTearOff<SVGTransform>",
  83. "SVGTransformList" => "SVGTransformListPropertyTearOff"
  84. );
  85. my %svgTypeWithWritablePropertiesNeedingTearOff = (
  86. "SVGPoint" => 1,
  87. "SVGMatrix" => 1
  88. );
  89. # Cache of IDL file pathnames.
  90. my $idlFiles;
  91. my $cachedInterfaces = {};
  92. # Default constructor
  93. sub new
  94. {
  95. my $object = shift;
  96. my $reference = { };
  97. $useDirectories = shift;
  98. $useGenerator = shift;
  99. $useOutputDir = shift;
  100. $useOutputHeadersDir = shift;
  101. $useLayerOnTop = shift;
  102. $preprocessor = shift;
  103. $writeDependencies = shift;
  104. $verbose = shift;
  105. $targetIdlFilePath = shift;
  106. bless($reference, $object);
  107. return $reference;
  108. }
  109. sub ProcessDocument
  110. {
  111. my $object = shift;
  112. $useDocument = shift;
  113. $defines = shift;
  114. my $ifaceName = "CodeGenerator" . $useGenerator;
  115. require $ifaceName . ".pm";
  116. %enumTypeHash = map { $_->name => $_->values } @{$useDocument->enumerations};
  117. # Dynamically load external code generation perl module
  118. $codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose, $targetIdlFilePath);
  119. unless (defined($codeGenerator)) {
  120. my $interfaces = $useDocument->interfaces;
  121. foreach my $interface (@$interfaces) {
  122. print "Skipping $useGenerator code generation for IDL interface \"" . $interface->name . "\".\n" if $verbose;
  123. }
  124. return;
  125. }
  126. my $interfaces = $useDocument->interfaces;
  127. foreach my $interface (@$interfaces) {
  128. print "Generating $useGenerator bindings code for IDL interface \"" . $interface->name . "\"...\n" if $verbose;
  129. $codeGenerator->GenerateInterface($interface, $defines);
  130. $codeGenerator->WriteData($interface, $useOutputDir, $useOutputHeadersDir);
  131. }
  132. }
  133. sub FileNamePrefix
  134. {
  135. my $object = shift;
  136. my $ifaceName = "CodeGenerator" . $useGenerator;
  137. require $ifaceName . ".pm";
  138. # Dynamically load external code generation perl module
  139. $codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose);
  140. return $codeGenerator->FileNamePrefix();
  141. }
  142. sub UpdateFile
  143. {
  144. my $object = shift;
  145. my $fileName = shift;
  146. my $contents = shift;
  147. open FH, "> $fileName" or die "Couldn't open $fileName: $!\n";
  148. print FH $contents;
  149. close FH;
  150. }
  151. sub ForAllParents
  152. {
  153. my $object = shift;
  154. my $interface = shift;
  155. my $beforeRecursion = shift;
  156. my $afterRecursion = shift;
  157. my $recurse;
  158. $recurse = sub {
  159. my $currentInterface = shift;
  160. for (@{$currentInterface->parents}) {
  161. my $interfaceName = $_;
  162. my $parentInterface = $object->ParseInterface($interfaceName);
  163. if ($beforeRecursion) {
  164. &$beforeRecursion($parentInterface) eq 'prune' and next;
  165. }
  166. &$recurse($parentInterface);
  167. &$afterRecursion($parentInterface) if $afterRecursion;
  168. }
  169. };
  170. &$recurse($interface);
  171. }
  172. sub AddMethodsConstantsAndAttributesFromParentInterfaces
  173. {
  174. # Add to $interface all of its inherited interface members, except for those
  175. # inherited through $interface's first listed parent. If an array reference
  176. # is passed in as $parents, the names of all ancestor interfaces visited
  177. # will be appended to the array. If $collectDirectParents is true, then
  178. # even the names of $interface's first listed parent and its ancestors will
  179. # be appended to $parents.
  180. my $object = shift;
  181. my $interface = shift;
  182. my $parents = shift;
  183. my $collectDirectParents = shift;
  184. my $first = 1;
  185. $object->ForAllParents($interface, sub {
  186. my $currentInterface = shift;
  187. if ($first) {
  188. # Ignore first parent class, already handled by the generation itself.
  189. $first = 0;
  190. if ($collectDirectParents) {
  191. # Just collect the names of the direct ancestor interfaces,
  192. # if necessary.
  193. push(@$parents, $currentInterface->name);
  194. $object->ForAllParents($currentInterface, sub {
  195. my $currentInterface = shift;
  196. push(@$parents, $currentInterface->name);
  197. }, undef);
  198. }
  199. # Prune the recursion here.
  200. return 'prune';
  201. }
  202. # Collect the name of this additional parent.
  203. push(@$parents, $currentInterface->name) if $parents;
  204. print " | |> -> Inheriting "
  205. . @{$currentInterface->constants} . " constants, "
  206. . @{$currentInterface->functions} . " functions, "
  207. . @{$currentInterface->attributes} . " attributes...\n | |>\n" if $verbose;
  208. # Add this parent's members to $interface.
  209. push(@{$interface->constants}, @{$currentInterface->constants});
  210. push(@{$interface->functions}, @{$currentInterface->functions});
  211. push(@{$interface->attributes}, @{$currentInterface->attributes});
  212. });
  213. }
  214. sub FindSuperMethod
  215. {
  216. my ($object, $interface, $functionName) = @_;
  217. my $indexer;
  218. $object->ForAllParents($interface, undef, sub {
  219. my $currentInterface = shift;
  220. foreach my $function (@{$currentInterface->functions}) {
  221. if ($function->signature->name eq $functionName) {
  222. $indexer = $function->signature;
  223. return 'prune';
  224. }
  225. }
  226. });
  227. return $indexer;
  228. }
  229. sub IDLFileForInterface
  230. {
  231. my $object = shift;
  232. my $interfaceName = shift;
  233. unless ($idlFiles) {
  234. my $sourceRoot = $ENV{SOURCE_ROOT};
  235. my @directories = map { $_ = "$sourceRoot/$_" if $sourceRoot && -d "$sourceRoot/$_"; $_ } @$useDirectories;
  236. push(@directories, ".");
  237. $idlFiles = { };
  238. my $wanted = sub {
  239. $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/;
  240. $File::Find::prune = 1 if /^\../;
  241. };
  242. find($wanted, @directories);
  243. }
  244. return $idlFiles->{$interfaceName};
  245. }
  246. sub ParseInterface
  247. {
  248. my $object = shift;
  249. my $interfaceName = shift;
  250. return undef if $interfaceName eq 'Object';
  251. if (exists $cachedInterfaces->{$interfaceName}) {
  252. return $cachedInterfaces->{$interfaceName};
  253. }
  254. # Step #1: Find the IDL file associated with 'interface'
  255. my $filename = $object->IDLFileForInterface($interfaceName)
  256. or die("Could NOT find IDL file for interface \"$interfaceName\"!\n");
  257. print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose;
  258. # Step #2: Parse the found IDL file (in quiet mode).
  259. my $parser = IDLParser->new(1);
  260. my $document = $parser->Parse($filename, $defines, $preprocessor);
  261. foreach my $interface (@{$document->interfaces}) {
  262. if ($interface->name eq $interfaceName) {
  263. $cachedInterfaces->{$interfaceName} = $interface;
  264. return $interface;
  265. }
  266. }
  267. die("Could NOT find interface definition for $interfaceName in $filename");
  268. }
  269. # Helpers for all CodeGenerator***.pm modules
  270. sub SkipIncludeHeader
  271. {
  272. my $object = shift;
  273. my $type = shift;
  274. return 1 if $object->IsPrimitiveType($type);
  275. # Special case: SVGPoint.h / SVGNumber.h do not exist.
  276. return 1 if $type eq "SVGPoint" or $type eq "SVGNumber";
  277. return 0;
  278. }
  279. sub IsConstructorTemplate
  280. {
  281. my $object = shift;
  282. my $interface = shift;
  283. my $template = shift;
  284. return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface->extendedAttributes->{"ConstructorTemplate"} eq $template;
  285. }
  286. sub IsNumericType
  287. {
  288. my $object = shift;
  289. my $type = shift;
  290. return 1 if $numericTypeHash{$type};
  291. return 0;
  292. }
  293. sub IsPrimitiveType
  294. {
  295. my $object = shift;
  296. my $type = shift;
  297. return 1 if $primitiveTypeHash{$type};
  298. return 1 if $numericTypeHash{$type};
  299. return 0;
  300. }
  301. sub IsStringType
  302. {
  303. my $object = shift;
  304. my $type = shift;
  305. return 1 if $stringTypeHash{$type};
  306. return 0;
  307. }
  308. sub IsEnumType
  309. {
  310. my $object = shift;
  311. my $type = shift;
  312. return 1 if exists $enumTypeHash{$type};
  313. return 0;
  314. }
  315. sub ValidEnumValues
  316. {
  317. my $object = shift;
  318. my $type = shift;
  319. return @{$enumTypeHash{$type}};
  320. }
  321. sub IsNonPointerType
  322. {
  323. my $object = shift;
  324. my $type = shift;
  325. return 1 if $nonPointerTypeHash{$type} or $primitiveTypeHash{$type} or $numericTypeHash{$type};
  326. return 0;
  327. }
  328. sub IsSVGTypeNeedingTearOff
  329. {
  330. my $object = shift;
  331. my $type = shift;
  332. return 1 if exists $svgTypeNeedingTearOff{$type};
  333. return 0;
  334. }
  335. sub IsSVGTypeWithWritablePropertiesNeedingTearOff
  336. {
  337. my $object = shift;
  338. my $type = shift;
  339. return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type};
  340. return 0;
  341. }
  342. sub IsTypedArrayType
  343. {
  344. my $object = shift;
  345. my $type = shift;
  346. return 1 if (($type eq "ArrayBuffer") or ($type eq "ArrayBufferView"));
  347. return 1 if (($type eq "Uint8Array") or ($type eq "Uint8ClampedArray") or ($type eq "Uint16Array") or ($type eq "Uint32Array"));
  348. return 1 if (($type eq "Int8Array") or ($type eq "Int16Array") or ($type eq "Int32Array"));
  349. return 1 if (($type eq "Float32Array") or ($type eq "Float64Array"));
  350. return 0;
  351. }
  352. sub IsRefPtrType
  353. {
  354. my $object = shift;
  355. my $type = shift;
  356. return 0 if $object->IsPrimitiveType($type);
  357. return 0 if $object->GetArrayType($type);
  358. return 0 if $object->GetSequenceType($type);
  359. return 0 if $type eq "DOMString";
  360. return 0 if $object->IsEnumType($type);
  361. return 1;
  362. }
  363. sub GetSVGTypeNeedingTearOff
  364. {
  365. my $object = shift;
  366. my $type = shift;
  367. return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type};
  368. return undef;
  369. }
  370. sub GetSVGWrappedTypeNeedingTearOff
  371. {
  372. my $object = shift;
  373. my $type = shift;
  374. my $svgTypeNeedingTearOff = $object->GetSVGTypeNeedingTearOff($type);
  375. return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff;
  376. if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) {
  377. $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//;
  378. } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) {
  379. $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//;
  380. } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) {
  381. $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//;
  382. } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) {
  383. $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//;
  384. }
  385. $svgTypeNeedingTearOff =~ s/>//;
  386. return $svgTypeNeedingTearOff;
  387. }
  388. sub IsSVGAnimatedType
  389. {
  390. my $object = shift;
  391. my $type = shift;
  392. return 1 if $svgAnimatedTypeHash{$type};
  393. return 0;
  394. }
  395. sub GetSequenceType
  396. {
  397. my $object = shift;
  398. my $type = shift;
  399. return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
  400. return "";
  401. }
  402. sub GetArrayType
  403. {
  404. my $object = shift;
  405. my $type = shift;
  406. return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
  407. return "";
  408. }
  409. sub AssertNotSequenceType
  410. {
  411. my $object = shift;
  412. my $type = shift;
  413. die "Sequences must not be used as the type of an attribute, constant or exception field." if $object->GetSequenceType($type);
  414. }
  415. # Uppercase the first letter while respecting WebKit style guidelines.
  416. # E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
  417. sub WK_ucfirst
  418. {
  419. my ($object, $param) = @_;
  420. my $ret = ucfirst($param);
  421. $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/;
  422. return $ret;
  423. }
  424. # Lowercase the first letter while respecting WebKit style guidelines.
  425. # URL becomes url, but SetURL becomes setURL.
  426. sub WK_lcfirst
  427. {
  428. my ($object, $param) = @_;
  429. my $ret = lcfirst($param);
  430. $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
  431. $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
  432. $ret =~ s/jS/js/ if $ret =~ /^jS/;
  433. $ret =~ s/xML/xml/ if $ret =~ /^xML/;
  434. $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
  435. $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
  436. # For HTML5 FileSystem API Flags attributes.
  437. # (create is widely used to instantiate an object and must be avoided.)
  438. $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
  439. $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
  440. return $ret;
  441. }
  442. # Return the C++ namespace that a given attribute name string is defined in.
  443. sub NamespaceForAttributeName
  444. {
  445. my ($object, $interfaceName, $attributeName) = @_;
  446. return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName};
  447. return "HTMLNames";
  448. }
  449. # Identifies overloaded functions and for each function adds an array with
  450. # links to its respective overloads (including itself).
  451. sub LinkOverloadedFunctions
  452. {
  453. my ($object, $interface) = @_;
  454. my %nameToFunctionsMap = ();
  455. foreach my $function (@{$interface->functions}) {
  456. my $name = $function->signature->name;
  457. $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name};
  458. push(@{$nameToFunctionsMap{$name}}, $function);
  459. $function->{overloads} = $nameToFunctionsMap{$name};
  460. $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
  461. }
  462. }
  463. sub AttributeNameForGetterAndSetter
  464. {
  465. my ($generator, $attribute) = @_;
  466. my $attributeName = $attribute->signature->name;
  467. if ($attribute->signature->extendedAttributes->{"ImplementedAs"}) {
  468. $attributeName = $attribute->signature->extendedAttributes->{"ImplementedAs"};
  469. }
  470. my $attributeType = $attribute->signature->type;
  471. # Avoid clash with C++ keyword.
  472. $attributeName = "_operator" if $attributeName eq "operator";
  473. # SVGAElement defines a non-virtual "String& target() const" method which clashes with "virtual String target() const" in Element.
  474. # To solve this issue the SVGAElement method was renamed to "svgTarget", take care of that when calling this method.
  475. $attributeName = "svgTarget" if $attributeName eq "target" and $attributeType eq "SVGAnimatedString";
  476. # SVG animated types need to use a special attribute name.
  477. # The rest of the special casing for SVG animated types is handled in the language-specific code generators.
  478. $attributeName .= "Animated" if $generator->IsSVGAnimatedType($attributeType);
  479. return $attributeName;
  480. }
  481. sub ContentAttributeName
  482. {
  483. my ($generator, $implIncludes, $interfaceName, $attribute) = @_;
  484. my $contentAttributeName = $attribute->signature->extendedAttributes->{"Reflect"};
  485. return undef if !$contentAttributeName;
  486. $contentAttributeName = lc $generator->AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING";
  487. my $namespace = $generator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
  488. $implIncludes->{"${namespace}.h"} = 1;
  489. return "WebCore::${namespace}::${contentAttributeName}Attr";
  490. }
  491. sub CanUseFastAttribute
  492. {
  493. my ($generator, $attribute) = @_;
  494. my $attributeType = $attribute->signature->type;
  495. # HTMLNames::styleAttr cannot be used with fast{Get,Has}Attribute but we do not [Reflect] the
  496. # style attribute.
  497. return !$generator->IsSVGAnimatedType($attributeType);
  498. }
  499. sub GetterExpression
  500. {
  501. my ($generator, $implIncludes, $interfaceName, $attribute) = @_;
  502. my $contentAttributeName = $generator->ContentAttributeName($implIncludes, $interfaceName, $attribute);
  503. if (!$contentAttributeName) {
  504. return ($generator->WK_lcfirst($generator->AttributeNameForGetterAndSetter($attribute)));
  505. }
  506. my $functionName;
  507. if ($attribute->signature->extendedAttributes->{"URL"}) {
  508. $functionName = "getURLAttribute";
  509. } elsif ($attribute->signature->type eq "boolean") {
  510. my $namespace = $generator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
  511. if ($generator->CanUseFastAttribute($attribute)) {
  512. $functionName = "fastHasAttribute";
  513. } else {
  514. $functionName = "hasAttribute";
  515. }
  516. } elsif ($attribute->signature->type eq "long") {
  517. $functionName = "getIntegralAttribute";
  518. } elsif ($attribute->signature->type eq "unsigned long") {
  519. $functionName = "getUnsignedIntegralAttribute";
  520. } else {
  521. if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") {
  522. $functionName = "getIdAttribute";
  523. $contentAttributeName = "";
  524. } elsif ($contentAttributeName eq "WebCore::HTMLNames::nameAttr") {
  525. $functionName = "getNameAttribute";
  526. $contentAttributeName = "";
  527. } elsif ($generator->CanUseFastAttribute($attribute)) {
  528. $functionName = "fastGetAttribute";
  529. } else {
  530. $functionName = "getAttribute";
  531. }
  532. }
  533. return ($functionName, $contentAttributeName);
  534. }
  535. sub SetterExpression
  536. {
  537. my ($generator, $implIncludes, $interfaceName, $attribute) = @_;
  538. my $contentAttributeName = $generator->ContentAttributeName($implIncludes, $interfaceName, $attribute);
  539. if (!$contentAttributeName) {
  540. return ("set" . $generator->WK_ucfirst($generator->AttributeNameForGetterAndSetter($attribute)));
  541. }
  542. my $functionName;
  543. if ($attribute->signature->type eq "boolean") {
  544. $functionName = "setBooleanAttribute";
  545. } elsif ($attribute->signature->type eq "long") {
  546. $functionName = "setIntegralAttribute";
  547. } elsif ($attribute->signature->type eq "unsigned long") {
  548. $functionName = "setUnsignedIntegralAttribute";
  549. } else {
  550. $functionName = "setAttribute";
  551. }
  552. return ($functionName, $contentAttributeName);
  553. }
  554. sub IsWrapperType
  555. {
  556. my $object = shift;
  557. my $type = shift;
  558. return 0 if $object->IsPrimitiveType($type);
  559. return 0 if $object->GetArrayType($type);
  560. return 0 if $object->GetSequenceType($type);
  561. return 0 if $object->IsEnumType($type);
  562. return 0 if $object->IsStringType($type);
  563. return 0 if $webCoreTypeHash{$type};
  564. return 0 if $type eq "any";
  565. return 1;
  566. }
  567. sub IsCallbackInterface
  568. {
  569. my $object = shift;
  570. my $type = shift;
  571. return 0 unless $object->IsWrapperType($type);
  572. my $idlFile = $object->IDLFileForInterface($type)
  573. or die("Could NOT find IDL file for interface \"$type\"!\n");
  574. open FILE, "<", $idlFile;
  575. my @lines = <FILE>;
  576. close FILE;
  577. my $fileContents = join('', @lines);
  578. return ($fileContents =~ /callback\s+interface\s+(\w+)/gs);
  579. }
  580. sub GenerateConditionalString
  581. {
  582. my $generator = shift;
  583. my $node = shift;
  584. my $conditional = $node->extendedAttributes->{"Conditional"};
  585. if ($conditional) {
  586. return $generator->GenerateConditionalStringFromAttributeValue($conditional);
  587. } else {
  588. return "";
  589. }
  590. }
  591. sub GenerateConstructorConditionalString
  592. {
  593. my $generator = shift;
  594. my $node = shift;
  595. my $conditional = $node->extendedAttributes->{"ConstructorConditional"};
  596. if ($conditional) {
  597. return $generator->GenerateConditionalStringFromAttributeValue($conditional);
  598. } else {
  599. return "";
  600. }
  601. }
  602. sub GenerateConditionalStringFromAttributeValue
  603. {
  604. my $generator = shift;
  605. my $conditional = shift;
  606. my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : ''));
  607. if ($operator) {
  608. # Avoid duplicated conditions.
  609. my %conditions;
  610. map { $conditions{$_} = 1 } split('\\' . $operator, $conditional);
  611. return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")";
  612. } else {
  613. return "ENABLE(" . $conditional . ")";
  614. }
  615. }
  616. sub GenerateCompileTimeCheckForEnumsIfNeeded
  617. {
  618. my ($generator, $interface) = @_;
  619. my $interfaceName = $interface->name;
  620. my @checks = ();
  621. # If necessary, check that all constants are available as enums with the same value.
  622. if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) {
  623. push(@checks, "\n");
  624. foreach my $constant (@{$interface->constants}) {
  625. my $reflect = $constant->extendedAttributes->{"Reflect"};
  626. my $name = $reflect ? $reflect : $constant->name;
  627. my $value = $constant->value;
  628. my $conditional = $constant->extendedAttributes->{"Conditional"};
  629. if ($conditional) {
  630. my $conditionalString = $generator->GenerateConditionalStringFromAttributeValue($conditional);
  631. push(@checks, "#if ${conditionalString}\n");
  632. }
  633. if ($constant->extendedAttributes->{"ImplementedBy"}) {
  634. push(@checks, "COMPILE_ASSERT($value == " . $constant->extendedAttributes->{"ImplementedBy"} . "::$name, ${interfaceName}Enum${name}IsWrongUseDoNotCheckConstants);\n");
  635. } else {
  636. push(@checks, "COMPILE_ASSERT($value == ${interfaceName}::$name, ${interfaceName}Enum${name}IsWrongUseDoNotCheckConstants);\n");
  637. }
  638. if ($conditional) {
  639. push(@checks, "#endif\n");
  640. }
  641. }
  642. push(@checks, "\n");
  643. }
  644. return @checks;
  645. }
  646. sub ExtendedAttributeContains
  647. {
  648. my $object = shift;
  649. my $callWith = shift;
  650. return 0 unless $callWith;
  651. my $keyword = shift;
  652. my @callWithKeywords = split /\s*\|\s*/, $callWith;
  653. return grep { $_ eq $keyword } @callWithKeywords;
  654. }
  655. # FIXME: This is backwards. We currently name the interface and the IDL files with the implementation name. We
  656. # should use the real interface name in the IDL files and then use ImplementedAs to map this to the implementation name.
  657. sub GetVisibleInterfaceName
  658. {
  659. my $object = shift;
  660. my $interface = shift;
  661. my $interfaceName = $interface->extendedAttributes->{"InterfaceName"};
  662. return $interfaceName ? $interfaceName : $interface->name;
  663. }
  664. sub InheritsInterface
  665. {
  666. my $object = shift;
  667. my $interface = shift;
  668. my $interfaceName = shift;
  669. my $found = 0;
  670. return 1 if $interfaceName eq $interface->name;
  671. $object->ForAllParents($interface, sub {
  672. my $currentInterface = shift;
  673. if ($currentInterface->name eq $interfaceName) {
  674. $found = 1;
  675. }
  676. return 1 if $found;
  677. }, 0);
  678. return $found;
  679. }
  680. sub InheritsExtendedAttribute
  681. {
  682. my $object = shift;
  683. my $interface = shift;
  684. my $extendedAttribute = shift;
  685. my $found = 0;
  686. return 1 if $interface->extendedAttributes->{$extendedAttribute};
  687. $object->ForAllParents($interface, sub {
  688. my $currentInterface = shift;
  689. if ($currentInterface->extendedAttributes->{$extendedAttribute}) {
  690. $found = 1;
  691. }
  692. return 1 if $found;
  693. }, 0);
  694. return $found;
  695. }
  696. 1;