KJS

nodes2string.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 2002 Harri Porten ([email protected])
4  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
5  * Copyright (C) 2003 Apple Computer, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #include <ctype.h>
25 #include <stdio.h>
26 
27 #include "nodes.h"
28 #include "function.h"
29 #include "scriptfunction.h"
30 
31 #include <typeinfo>
32 
33 #define NOINLINE
34 #if defined(WTF_COMPILER_CWP)
35 #pragma auto_inline off
36 #elif defined(WTF_COMPILER_MSVC)
37 #pragma auto_inline(off)
38 #elif defined(WTF_COMPILER_GCC)
39 // #undef NOINLINE
40 // #define NOINLINE __attribute__ (noinline)
41 #endif
42 
43 // GCC cstring uses these automatically, but not all implementations do.
44 using std::strlen;
45 using std::strcpy;
46 using std::strncpy;
47 using std::memset;
48 using std::memcpy;
49 
50 namespace KJS
51 {
52 const bool kDontQuote = false, kQuote = true;
53 
54 /**
55  * A simple text streaming class that helps with code indentation.
56  */
57 class SourceStream
58 {
59 public:
60  enum eEndl { Endl };
61  enum eIndent { Indent };
62  enum eUnindent { Unindent };
63 
64  static const int kBufSize = 2048;
65  typedef unsigned short UTF16;
66  SourceStream() : indent(0), bufUsed(0), reindentLine(0), reindenting(false) {}
67  const UString &toString()
68  {
69  flush();
70  return str;
71  }
72  SourceStream &operator<<(const Identifier &s) NOINLINE;
73  SourceStream &operator<<(const UString &s) NOINLINE;
74  SourceStream &operator<<(const char *s) NOINLINE;
75  SourceStream &operator<<(char s) NOINLINE;
76  SourceStream &operator<<(eEndl) NOINLINE;
77  SourceStream &operator<<(const Node *n) NOINLINE;
78  SourceStream &operator<<(const StatementNode *n) NOINLINE;
79  SourceStream &operator<<(Operator op) NOINLINE;
80  inline SourceStream &operator<<(eIndent)
81  {
82  indent += 2;
83  return *this;
84  }
85  inline SourceStream &operator<<(eUnindent)
86  {
87  indent -= 2;
88  return *this;
89  }
90  SourceStream &append(const Node *expr1, const char *sep, const Node *expr2) NOINLINE;
91  SourceStream &append(const RefPtr<Node> &expr1, const char *sep, const RefPtr<Node> &expr2) NOINLINE;
92  SourceStream &append(const UTF16 *src, int srcLen) NOINLINE;
93  SourceStream &append(const UString &inStr, bool quote) NOINLINE;
94  template <typename T>
95  inline SourceStream &operator<<(const RefPtr<T> &n)
96  {
97  return this->operator<<(n.get());
98  }
99 
100  void setReindenting(int baseLine)
101  {
102  reindenting = true;
103  reindentLine = baseLine;
104  }
105 private:
106  UString str;
107  int indent;
108  int bufUsed;
109  UTF16 buffer[kBufSize];
110  void flush() NOINLINE;
111  void put(UTF16 ch)
112  {
113  buffer[bufUsed++] = ch;
114  }
115  void put(char ch)
116  {
117  buffer[bufUsed++] = static_cast<unsigned char>(ch);
118  }
119 
120  int reindentLine;
121  bool reindenting;
122 };
123 }
124 
125 using namespace KJS;
126 
127 SourceStream &SourceStream::operator<<(Operator op)
128 {
129  assert(op == OpPlusPlus || op == OpMinusMinus);
130  return *this << ((op == OpPlusPlus) ? "++" : "--");
131 }
132 
133 void SourceStream::flush()
134 {
135  if (bufUsed) {
136  str.append(UString(reinterpret_cast<const UChar *>(buffer), bufUsed));
137  bufUsed = 0;
138  }
139 }
140 
141 SourceStream &SourceStream::operator<<(char c)
142 {
143  if (bufUsed == kBufSize) {
144  flush();
145  }
146  put(c);
147  return *this;
148 }
149 
150 SourceStream &SourceStream::operator<<(const char *s)
151 {
152  assert(strlen(s) < 100);
153  if (bufUsed > kBufSize - 100) {
154  flush();
155  }
156 
157  unsigned char ch;
158  int i = bufUsed;
159  --s;
160  for (UTF16 *dst = &buffer[i] - 1; (ch = *++s) != 0; ++i) {
161  *++dst = ch;
162  }
163  bufUsed = i;
164 
165  return *this;
166 }
167 
168 SourceStream &SourceStream::operator<<(const UString &s)
169 {
170  return append(&s.data()->uc, s.size());
171 }
172 
173 SourceStream &SourceStream::operator<<(const Identifier &s)
174 {
175  return append(s.ustring(), kDontQuote);
176 }
177 
178 SourceStream &SourceStream::operator<<(const StatementNode *n)
179 {
180  if (n) {
181  // Update debug info with new line numbers if needed.
182  // Note that streamTo will output endLine first thing,
183  // so we want the next line in the debug info
184  int firstLine = reindentLine + 1;
185  n->streamTo(*this);
186  if (reindenting) {
187  n->setLoc(firstLine, reindentLine - 1);
188  }
189  }
190  return *this;
191 }
192 
193 SourceStream &SourceStream::operator<<(const Node *n)
194 {
195  if (n) {
196  n->streamTo(*this);
197  }
198  return *this;
199 }
200 
201 SourceStream &SourceStream::operator<<(eEndl)
202 {
203  if (bufUsed > kBufSize - 1 - indent) {
204  flush();
205  }
206  put('\n');
207  ++reindentLine;
208 
209  if (indent > 0) {
210  UTF16 *dst = &buffer[bufUsed];
211  for (int i = indent; i > 0; --i) {
212  *dst++ = ' ';
213  }
214  bufUsed += indent;
215  }
216 
217  return *this;
218 }
219 
220 SourceStream &SourceStream::append(const Node *expr1, const char *sep, const Node *expr2)
221 {
222  return *this << expr1 << sep << expr2;
223 }
224 
225 SourceStream &
226 SourceStream::append(const RefPtr<Node> &expr1, const char *sep, const RefPtr<Node> &expr2)
227 {
228  return *this << expr1 << sep << expr2;
229 }
230 
231 SourceStream &SourceStream::append(const UTF16 *src, int srcLen)
232 {
233  if (kBufSize - bufUsed < srcLen) {
234  flush();
235  }
236  if (kBufSize - bufUsed < srcLen) {
237  str.append(UString(reinterpret_cast<const UChar *>(src), srcLen));
238  } else {
239  UTF16 *dst = &buffer[bufUsed];
240  bufUsed += srcLen;
241 // while (--srcLen >= 0)
242  while (srcLen-- > 0) {
243  *dst++ = *src++;
244  }
245  }
246 
247  return *this;
248 }
249 
250 // Append a quoted string
251 SourceStream &SourceStream::append(const UString &inStr, bool quote)
252 {
253  if (quote) {
254  *this << '"';
255  }
256  const UTF16 *src = &inStr.data()->uc;
257  const size_t size = inStr.size();
258  for (size_t i = 0; i < size; ++i) {
259  if (bufUsed >= kBufSize - 8) {
260  flush();
261  }
262  UTF16 c = *src++, esc = '\\';
263  switch (c) {
264  case '\"': break;
265  case '\n': c = 'n'; break;
266  case '\r': c = 'r'; break;
267  case '\t': c = 't'; break;
268  case '\\': break;
269  default:
270  if (c >= 128 || !isprint(c)) { // ### FIXME: use Unicode tables
271  char hexValue[8];
272  int len = sprintf(hexValue, (c < 256) ? "\\x%02X" : "\\u%04X", c);
273  UTF16 *dst = &buffer[bufUsed];
274  bufUsed += len;
275  for (int j = 0; j < len; ++j) {
276  dst[j] = hexValue[j];
277  }
278  continue;
279  }
280  esc = 0; // don't escape
281  break;
282  }
283  if (esc) {
284  put(esc);
285  }
286  put(c);
287  }
288 
289  if (quote) {
290  *this << '"';
291  }
292  return *this;
293 }
294 
295 UString FunctionImp::toSource() const
296 {
297  SourceStream str;
298  str << "function ";
299  str.append(functionName().ustring(), kDontQuote) << '(';
300  const FunctionBodyNode *body = this->body.get();
301  const int numParams = body->numParams();
302  for (int i = 0; i < numParams; ++i) {
303  if (i > 0) {
304  str << ", ";
305  }
306  str << body->paramName(i).ustring();
307  }
308  str << ") ";
309  body->streamTo(str);
310 
311  return str.toString();
312 }
313 
314 UString Node::toString() const
315 {
316  SourceStream str;
317  streamTo(str);
318 
319  return str.toString();
320 }
321 
322 UString Node::reindent(int baseLine) const
323 {
324  SourceStream str;
325  str.setReindenting(baseLine);
326 
327  streamTo(str);
328 
329  return str.toString();
330 }
331 
332 void NullNode::streamTo(SourceStream &s) const
333 {
334  s << "null";
335 }
336 
337 void BooleanNode::streamTo(SourceStream &s) const
338 {
339  s << (value() ? "true" : "false");
340 }
341 
342 void NumberNode::streamTo(SourceStream &s) const
343 {
344  s << UString::from(value());
345 }
346 
347 void StringNode::streamTo(SourceStream &s) const
348 {
349  s.append(value(), kQuote);
350 }
351 
352 void RegExpNode::streamTo(SourceStream &s) const
353 {
354  s << '/' << pattern << '/' << flags;
355 }
356 
357 void ThisNode::streamTo(SourceStream &s) const
358 {
359  s << "this";
360 }
361 
362 void VarAccessNode::streamTo(SourceStream &s) const
363 {
364  s << ident;
365 }
366 
367 void GroupNode::streamTo(SourceStream &s) const
368 {
369  s << '(' << group << ')';
370 }
371 
372 void ElementNode::streamTo(SourceStream &s) const
373 {
374  for (const ElementNode *n = this; n; n = n->next.get()) {
375  for (int i = 0; i < n->elision; i++) {
376  s << ',';
377  }
378  s << n->node;
379  if (n->next) {
380  s << ',';
381  }
382  }
383 }
384 
385 void ArrayNode::streamTo(SourceStream &s) const
386 {
387  s << '[' << element;
388  for (int i = 0; i < elision; i++) {
389  s << ',';
390  }
391  // Parser consumes one elision comma if there's array elements
392  // present in the expression.
393  if (opt && element) {
394  s << ',';
395  }
396  s << ']';
397 }
398 
399 void ObjectLiteralNode::streamTo(SourceStream &s) const
400 {
401  if (list) {
402  s << "{ " << list << " }";
403  } else {
404  s << "{ }";
405  }
406 }
407 
408 void PropertyListNode::streamTo(SourceStream &s) const
409 {
410  s << node;
411 
412  for (const PropertyListNode *n = next.get(); n; n = n->next.get()) {
413  s << ", " << n->node;
414  }
415 }
416 
417 void PropertyNode::streamTo(SourceStream &s) const
418 {
419  switch (type) {
420  case Constant:
421  s << name << ": " << assign;
422  break;
423  case Getter:
424  case Setter: {
425  const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
426  if (type == Getter) {
427  s << "get ";
428  } else {
429  s << "set ";
430  }
431 
432  s << name << '(' << func->param << ')' << func->body;
433  break;
434  }
435  }
436 }
437 
438 void PropertyNameNode::streamTo(SourceStream &s) const
439 {
440  s.append(str.ustring(), kQuote);
441 }
442 
443 void BracketAccessorNode::streamTo(SourceStream &s) const
444 {
445  s.append(expr1, "[", expr2) << ']';
446 }
447 
448 void DotAccessorNode::streamTo(SourceStream &s) const
449 {
450  s << expr << '.' << ident;
451 }
452 
453 void ArgumentListNode::streamTo(SourceStream &s) const
454 {
455  s << expr;
456  for (ArgumentListNode *n = next.get(); n; n = n->next.get()) {
457  s << ", " << n->expr;
458  }
459 }
460 
461 void ArgumentsNode::streamTo(SourceStream &s) const
462 {
463  s << '(' << list << ')';
464 }
465 
466 void NewExprNode::streamTo(SourceStream &s) const
467 {
468  s << "new " << expr << args;
469 }
470 
471 void FunctionCallValueNode::streamTo(SourceStream &s) const
472 {
473  s << expr << args;
474 }
475 
476 void FunctionCallReferenceNode::streamTo(SourceStream &s) const
477 {
478  s << expr << args;
479 }
480 
481 void PostfixNode::streamTo(SourceStream &s) const
482 {
483  s << m_loc << m_oper;
484 }
485 
486 void DeleteReferenceNode::streamTo(SourceStream &s) const
487 {
488  s << "delete " << loc;
489 }
490 
491 void DeleteValueNode::streamTo(SourceStream &s) const
492 {
493  s << "delete " << m_expr;
494 }
495 
496 void VoidNode::streamTo(SourceStream &s) const
497 {
498  s << "void " << expr;
499 }
500 
501 void TypeOfValueNode::streamTo(SourceStream &s) const
502 {
503  s << "typeof " << m_expr;
504 }
505 
506 void TypeOfVarNode::streamTo(SourceStream &s) const
507 {
508  s << "typeof " << loc;
509 }
510 
511 void PrefixNode::streamTo(SourceStream &s) const
512 {
513  s << m_oper << m_loc;
514 }
515 
516 void UnaryPlusNode::streamTo(SourceStream &s) const
517 {
518  s << "+ " << expr;
519 }
520 
521 void NegateNode::streamTo(SourceStream &s) const
522 {
523  s << "- " << expr;
524 }
525 
526 void BitwiseNotNode::streamTo(SourceStream &s) const
527 {
528  s << '~' << expr;
529 }
530 
531 void LogicalNotNode::streamTo(SourceStream &s) const
532 {
533  s << '!' << expr;
534 }
535 
536 void BinaryOperatorNode::streamTo(SourceStream &s) const
537 {
538  const char *opStr;
539  switch (oper) {
540  case OpMult:
541  opStr = " * ";
542  break;
543  case OpDiv:
544  opStr = " / ";
545  break;
546  case OpMod:
547  opStr = " % ";
548  break;
549  case OpPlus:
550  opStr = " + ";
551  break;
552  case OpMinus:
553  opStr = " - ";
554  break;
555  case OpLShift:
556  opStr = " << ";
557  break;
558  case OpRShift:
559  opStr = " >> ";
560  break;
561  case OpURShift:
562  opStr = " >>> ";
563  break;
564  case OpLess:
565  opStr = " < ";
566  break;
567  case OpGreaterEq:
568  opStr = " >= ";
569  break;
570  case OpGreater:
571  opStr = " > ";
572  break;
573  case OpLessEq:
574  opStr = " <= ";
575  break;
576  case OpIn:
577  opStr = " in ";
578  break;
579  case OpInstanceOf:
580  opStr = " instanceof ";
581  break;
582  case OpEqEq:
583  opStr = " == ";
584  break;
585  case OpNotEq:
586  opStr = " != ";
587  break;
588  case OpStrEq:
589  opStr = " === ";
590  break;
591  case OpStrNEq:
592  opStr = " !== ";
593  break;
594  case OpBitAnd:
595  opStr = " & ";
596  break;
597  case OpBitXOr:
598  opStr = " ^ ";
599  break;
600  case OpBitOr:
601  opStr = " | ";
602  break;
603  default:
604  assert(!"Unhandled case in BinaryOperatorNode::streamTo()");
605  opStr = " ??? ";
606  break;
607  }
608  s.append(expr1, opStr, expr2);
609 }
610 
611 void BinaryLogicalNode::streamTo(SourceStream &s) const
612 {
613  s.append(expr1, (oper == OpAnd ? " && " : " || "), expr2);
614 }
615 
616 void ConditionalNode::streamTo(SourceStream &s) const
617 {
618  s << logical << " ? ";
619  s.append(expr1, " : ", expr2);
620 }
621 
622 static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
623 {
624  const char *opStr;
625  switch (oper) {
626  case OpEqual:
627  opStr = " = ";
628  break;
629  case OpMultEq:
630  opStr = " *= ";
631  break;
632  case OpDivEq:
633  opStr = " /= ";
634  break;
635  case OpPlusEq:
636  opStr = " += ";
637  break;
638  case OpMinusEq:
639  opStr = " -= ";
640  break;
641  case OpLShift:
642  opStr = " <<= ";
643  break;
644  case OpRShift:
645  opStr = " >>= ";
646  break;
647  case OpURShift:
648  opStr = " >>>= ";
649  break;
650  case OpAndEq:
651  opStr = " &= ";
652  break;
653  case OpXOrEq:
654  opStr = " ^= ";
655  break;
656  case OpOrEq:
657  opStr = " |= ";
658  break;
659  case OpModEq:
660  opStr = " %= ";
661  break;
662  default:
663  opStr = " ?= ";
664  }
665  s << opStr;
666 }
667 
668 void AssignNode::streamTo(SourceStream &s) const
669 {
670  s << m_loc;
671  streamAssignmentOperatorTo(s, m_oper);
672  s << m_right;
673 // s.append(m_ident, opStr, m_right);
674 }
675 
676 void CommaNode::streamTo(SourceStream &s) const
677 {
678  s.append(expr1, ", ", expr2);
679 }
680 
681 void AssignExprNode::streamTo(SourceStream &s) const
682 {
683  s << " = " << expr;
684 }
685 
686 void VarDeclNode::streamTo(SourceStream &s) const
687 {
688  s << ident << init;
689 }
690 
691 void VarDeclListNode::streamTo(SourceStream &s) const
692 {
693  s << "var " << var;
694  for (VarDeclListNode *n = next.get(); n; n = n->next.get()) {
695  s << ", " << n->var;
696  }
697 }
698 
699 void VarStatementNode::streamTo(SourceStream &s) const
700 {
701  s << SourceStream::Endl << next << ';';
702 }
703 
704 void BlockNode::streamTo(SourceStream &s) const
705 {
706  s << SourceStream::Endl << '{' << SourceStream::Indent
707  << source << SourceStream::Unindent << SourceStream::Endl << '}';
708 }
709 
710 void ProgramNode::streamTo(SourceStream &s) const
711 {
712  // we don't want braces here, unlike in the above
713  s << source << SourceStream::Endl;
714 }
715 
716 void EmptyStatementNode::streamTo(SourceStream &s) const
717 {
718  s << SourceStream::Endl << ';';
719 }
720 
721 void ExprStatementNode::streamTo(SourceStream &s) const
722 {
723  s << SourceStream::Endl << expr << ';';
724 }
725 
726 void IfNode::streamTo(SourceStream &s) const
727 {
728  s << SourceStream::Endl << "if (" << expr << ')' << SourceStream::Indent
729  << statement1 << SourceStream::Unindent;
730  if (statement2)
731  s << SourceStream::Endl << "else" << SourceStream::Indent
732  << statement2 << SourceStream::Unindent;
733 }
734 
735 void DoWhileNode::streamTo(SourceStream &s) const
736 {
737  s << SourceStream::Endl << "do " << SourceStream::Indent
738  << statement << SourceStream::Unindent << SourceStream::Endl
739  << "while (" << expr << ");";
740 }
741 
742 void WhileNode::streamTo(SourceStream &s) const
743 {
744  s << SourceStream::Endl << "while (" << expr << ')' << SourceStream::Indent
745  << statement << SourceStream::Unindent;
746 }
747 
748 void ForNode::streamTo(SourceStream &s) const
749 {
750  s << SourceStream::Endl << "for ("
751  << expr1
752  << "; " << expr2
753  << "; " << expr3
754  << ')' << SourceStream::Indent << statement << SourceStream::Unindent;
755 }
756 
757 void ForInNode::streamTo(SourceStream &s) const
758 {
759  s << SourceStream::Endl << "for (";
760  if (varDecl) {
761  s << "var " << varDecl;
762  } else {
763  s << lexpr;
764  }
765 
766  s << " in " << expr << ')' << SourceStream::Indent
767  << statement << SourceStream::Unindent;
768 }
769 
770 void ContinueNode::streamTo(SourceStream &s) const
771 {
772  s << SourceStream::Endl << "continue";
773  if (!ident.isNull()) {
774  s << ' ' << ident;
775  }
776  s << ';';
777 }
778 
779 void BreakNode::streamTo(SourceStream &s) const
780 {
781  s << SourceStream::Endl << "break";
782  if (!ident.isNull()) {
783  s << ' ' << ident;
784  }
785  s << ';';
786 }
787 
788 void ReturnNode::streamTo(SourceStream &s) const
789 {
790  s << SourceStream::Endl << "return";
791  if (value) {
792  s << ' ' << value;
793  }
794  s << ';';
795 }
796 
797 void WithNode::streamTo(SourceStream &s) const
798 {
799  s << SourceStream::Endl << "with (" << expr << ") "
800  << statement;
801 }
802 
803 void CaseClauseNode::streamTo(SourceStream &s) const
804 {
805  s << SourceStream::Endl;
806  if (expr) {
807  s << "case " << expr;
808  } else {
809  s << "default";
810  }
811  s << ':' << SourceStream::Indent;
812  if (source) {
813  s << source;
814  }
815  s << SourceStream::Unindent;
816 }
817 
818 void ClauseListNode::streamTo(SourceStream &s) const
819 {
820  for (const ClauseListNode *n = this; n; n = n->getNext()) {
821  s << n->getClause();
822  }
823 }
824 
825 void CaseBlockNode::streamTo(SourceStream &s) const
826 {
827  for (const ClauseListNode *n = list1.get(); n; n = n->getNext()) {
828  s << n->getClause();
829  }
830  if (def) {
831  s << def;
832  }
833  for (const ClauseListNode *n = list2.get(); n; n = n->getNext()) {
834  s << n->getClause();
835  }
836 }
837 
838 void SwitchNode::streamTo(SourceStream &s) const
839 {
840  s << SourceStream::Endl << "switch (" << expr << ") {"
841  << SourceStream::Indent << block << SourceStream::Unindent
842  << SourceStream::Endl << '}';
843 }
844 
845 void LabelNode::streamTo(SourceStream &s) const
846 {
847  s << SourceStream::Endl << label << ':' << SourceStream::Indent
848  << statement << SourceStream::Unindent;
849 }
850 
851 void ThrowNode::streamTo(SourceStream &s) const
852 {
853  s << SourceStream::Endl << "throw " << expr << ';';
854 }
855 
856 void TryNode::streamTo(SourceStream &s) const
857 {
858  s << SourceStream::Endl << "try " << tryBlock;
859  if (catchBlock) {
860  s << SourceStream::Endl << "catch (" << exceptionIdent << ')' << catchBlock;
861  }
862  if (finallyBlock) {
863  s << SourceStream::Endl << "finally " << finallyBlock;
864  }
865 }
866 
867 void ParameterNode::streamTo(SourceStream &s) const
868 {
869  s << id;
870  for (ParameterNode *n = next.get(); n; n = n->next.get()) {
871  s << ", " << n->id;
872  }
873 }
874 
875 void FuncDeclNode::streamTo(SourceStream &s) const
876 {
877  s << SourceStream::Endl << "function " << ident << '(' << param << ')' << body;
878 }
879 
880 void FuncExprNode::streamTo(SourceStream &s) const
881 {
882  s << "function " << ident << '(' << param << ')' << body;
883 }
884 
885 void SourceElementsNode::streamTo(SourceStream &s) const
886 {
887  for (const SourceElementsNode *n = this; n; n = n->next.get()) {
888  s << n->node;
889  }
890 }
891 
892 void PackageNameNode::streamTo(SourceStream &s) const
893 {
894  if (names) {
895  s << names << '.';
896  }
897  s << id;
898 }
899 
900 void ImportStatement::streamTo(SourceStream &s) const
901 {
902  s << SourceStream::Endl << "import ";
903  if (!al.isEmpty()) {
904  s << al << " = ";
905  }
906  s << name << (wld ? ".*;" : ";");
907 }
908 
const UString & ustring() const
returns a UString of the identifier
Definition: identifier.h:58
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
This AST node corresponds to the function body or top-level code in the AST, but is used to keep trac...
Definition: nodes.h:1276
QString pattern(Mode mode=Reading)
int size() const
Definition: ustring.h:420
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
char * toString(const T &value)
Represents an Identifier for a Javascript object.
Definition: identifier.h:36
Unicode character.
Definition: ustring.h:70
void init(KXmlGuiWindow *window, KgDifficulty *difficulty=nullptr)
const UChar * data() const
Definition: ustring.h:391
QString label(StandardShortcut id)
static UString from(int i)
Constructs a string from an int.
Definition: ustring.cpp:559
QTextStream & flush(QTextStream &stream)
const char * name(StandardAction id)
virtual bool put(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName, const QVariant &value)
QAction * next(const QObject *recvr, const char *slot, QObject *parent)
Unicode string class.
Definition: ustring.h:153
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:10:39 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.