summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Symbols.scala
blob: 79bf9e969ca92e81ab41d1984c1fa1c7eff2092b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
package scala
package reflect
package api

/**
 * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
 *
 *  This trait defines symbols and operations on them.
 *
 *  Symbols are used to establish bindings between a name and the entity it refers to, such as a class or a method.
 *  Anything you define and can give a name to in Scala has an associated symbol.
 *
 *  Symbols contain all available information about the declaration of an entity (class/object/trait etc.) or a
 *  member (vals/vars/defs etc.), and as such are an integral abstraction central to both runtime
 *  reflection and macros.
 *
 *  A symbol can provide a wealth of information ranging from the basic `name` method available on all symbols to
 *  other, more involved, concepts such as getting the `baseClasses` from `ClassSymbol`. Other common use cases of
 *  symbols include inspecting members' signatures, getting type parameters of a class, getting the parameter type
 *  of a method or finding out the type of a field.
 *
 *  Example usage of runtime reflection; getting a method's type signature:
 *  {{{
 *    scala> import scala.reflect.runtime.universe._
 *    import scala.reflect.runtime.universe._
 *
 *    scala> class C[T] { def test[U](x: T)(y: U): Int = ??? }
 *    defined class C
 *
 *    scala> val test = typeOf[C[Int]].member(TermName("test")).asMethod
 *    test: reflect.runtime.universe.MethodSymbol = method test
 *
 *    scala> test.info
 *    res0: reflect.runtime.universe.Type = [U](x: T)(y: U)scala.Int
 *  }}}
 *
 *  Symbols are organized in a hierarchy. For example, a symbol that represents a parameter of a method is owned by
 *  the corresponding method symbol, a method symbol is owned by its enclosing class, a class is owned by a
 *  containing package and so on.
 *
 *  Certain types of tree nodes, such as [[Trees#Ident Ident]] (references to identifiers) and
 *  [[Trees#Select Select]] (references to members) expose method [[Trees.SymTreeApi.symbol `symbol`]]
 *  to obtain the symbol that represents their declaration. During the typechecking phase, the compiler looks up the
 *  symbol based on the name and scope and sets the [[Trees.SymTreeApi.symbol `symbol` field]] of tree nodes.
 *
 *  For more information about `Symbol` usage and attached intricacies, see the [[http://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html Reflection Guide: Symbols]]
 *
 *  @group ReflectionAPI
 *
 *  @contentDiagram hideNodes "*Api"
 *
 *  @define SYMACCESSORS Class [[Symbol]] defines `isXXX` test methods such as `isPublic` or `isFinal`, `params` and
 *  `returnType` methods for method symbols, `baseClasses` for class symbols and so on. Some of these methods don't
 *  make sense for certain subclasses of `Symbol` and return `NoSymbol`, `Nil` or other empty values.
 *
 */
trait Symbols { self: Universe =>

  /** The type of symbols representing declarations.
   *  @group Symbols
   *  @template
   */
  type Symbol >: Null <: AnyRef with SymbolApi

  /** The type of type symbols representing type, class, and trait declarations,
   *  as well as type parameters.
   *  @group Symbols
   *  @template
   */
  type TypeSymbol >: Null <: TypeSymbolApi with Symbol

  /** The type of term symbols representing val, var, def, and object declarations as
   *  well as packages and value parameters.
   *  @group Symbols
   *  @template
   */
  type TermSymbol >: Null <: TermSymbolApi with Symbol

  /** The type of method symbols representing def declarations.
   *  @group Symbols
   *  @template
   */
  type MethodSymbol >: Null <: MethodSymbolApi with TermSymbol

  /** The type of module symbols representing object declarations.
   *  @group Symbols
   *  @template
   */
  type ModuleSymbol >: Null <: ModuleSymbolApi with TermSymbol

  /** The type of class symbols representing class and trait definitions.
   *  @group Symbols
   *  @template
   */
  type ClassSymbol >: Null <: ClassSymbolApi with TypeSymbol

  /** A special "missing" symbol. Commonly used in the API to denote a default or empty value.
   *  @group Symbols
   *  @template
   */
  val NoSymbol: Symbol

  /** The API of symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   *  @groupname Basics        Symbol Basic Information
   *  @groupprio Basics        0
   *  @groupname Tests         Symbol Type Tests
   *  @groupprio Tests         1
   *  @groupname Conversions   Symbol Conversions
   *  @groupprio Conversions   2
   *  @groupname Constructors  New Symbol Constructors
   *  @groupprio Constructors  3
   *  @groupdesc Constructors  These methods construct new symbols owned by the current symbol.
   *  @groupname Helpers       Iteration Helpers
   *  @groupprio Helpers       4
   *  @groupdesc Helpers       These methods enable collections-like operations on symbols.
   *  @groupname Type          TypeSymbol Members
   *  @groupprio Type          -1
   *  @groupname Term          TermSymbol Members
   *  @groupprio Term          -1
   *  @groupname Class         Class Symbol Members
   *  @groupprio Class         -2
   *  @groupname Method        Method Symbol Members
   *  @groupprio Method        -2
   *  @groupname Module        Module Symbol Members
   *  @groupprio Module        -2
   */
  trait SymbolApi { this: Symbol =>

    /** The owner of this symbol. This is the symbol
     *  that directly contains the current symbol's definition.
     *  The `NoSymbol` symbol does not have an owner, and calling this method
     *  on one causes an internal error.
     *  The owner of the Scala root class [[scala.reflect.api.Mirror.RootClass]]
     *  and the Scala root object [[scala.reflect.api.Mirror.RootPackage]] is `NoSymbol`.
     *  Every other symbol has a chain of owners that ends in
     *  [[scala.reflect.api.Mirror.RootClass]].
     *
     *  @group Basics
     */
    def owner: Symbol

    /** The type of the symbol name.
     *  Can be either `TermName` or `TypeName` depending on whether this is a `TermSymbol` or a `TypeSymbol`.
     *
     *  Type name namespaces do not intersect with term name namespaces.
     *  This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`.
     *  @group Basics
     */
    type NameType >: Null <: Name

    /** The name of the symbol as a member of the `Name` type.
     *  @group Basics
     */
    def name: NameType

    /** The encoded full path name of this symbol, where outer names and inner names
     *  are separated by periods.
     *  @group Basics
     */
    def fullName: String

    /** Position of the tree. */
    def pos: Position

    /** Does this symbol represent the definition of a type?
     *  Note that every symbol is either a term or a type.
     *  So for every symbol `sym` (except for `NoSymbol`),
     *  either `sym.isTerm` is true or `sym.isType` is true.
     *
     *  @group Tests
     */
    def isType: Boolean = false

    /** This symbol cast to a TypeSymbol.
     *  @throws ScalaReflectionException if `isType` is false.
     *
     *  @group Conversions
     */
    def asType: TypeSymbol = throw new ScalaReflectionException(s"$this is not a type")

    /** Does this symbol represent the definition of a term?
     *  Note that every symbol is either a term or a type.
     *  So for every symbol `sym` (except for `NoSymbol`),
     *  either `sym.isTerm` is true or `sym.isType` is true.
     *
     *  @group Tests
     */
    def isTerm: Boolean = false

    /** This symbol cast to a TermSymbol.
     *  @throws ScalaReflectionException if `isTerm` is false.
     *
     *  @group Conversions
     */
    def asTerm: TermSymbol = throw new ScalaReflectionException(s"$this is not a term")

    /** Does this symbol represent the definition of a method?
     *  If yes, `isTerm` is also guaranteed to be true.
     *
     *  @group Tests
     */
    def isMethod: Boolean = false

    /** Does this method represent a constructor?
     *
     *  If `owner` is a class, then this is a vanilla JVM constructor.
     *  If `owner` is a trait, then this is a mixin constructor.
     *
     *  @group Method
     */
    def isConstructor: Boolean

    /** This symbol cast to a MethodSymbol.
     *  @throws ScalaReflectionException if `isMethod` is false.
     *
     *  @group Conversions
     */
    def asMethod: MethodSymbol = {
      def overloadedMsg =
        "encapsulates multiple overloaded alternatives and cannot be treated as a method. "+
        "Consider invoking `<offending symbol>.asTerm.alternatives` and manually picking the required method"
      def vanillaMsg = "is not a method"
      val msg = if (isOverloadedMethod) overloadedMsg else vanillaMsg
      throw new ScalaReflectionException(s"$this $msg")
    }

    /** Used to provide a better error message for `asMethod`.
     *
     *  @group Tests
     */
    protected def isOverloadedMethod = false

    /** Does this symbol represent the definition of a module (i.e. it
     *  results from an object definition?).
     *  If yes, `isTerm` is also guaranteed to be true.
     *
     *  @group Tests
     */
    def isModule: Boolean = false

    /** This symbol cast to a ModuleSymbol defined by an object definition.
     *  @throws ScalaReflectionException if `isModule` is false.
     *
     *  @group Conversions
     */
    def asModule: ModuleSymbol = throw new ScalaReflectionException(s"$this is not a module")

    /** Does this symbol represent the definition of a class or trait?
     *  If yes, `isType` is also guaranteed to be true.
     *
     *  @group Tests
     */
    def isClass: Boolean = false

    /** Does this symbol represent the definition of a class implicitly associated
     *  with an object definition (module class in scala compiler parlance)?
     *  If yes, `isType` is also guaranteed to be true.
     *
     *  @group Tests
     */
    def isModuleClass: Boolean = false

    /** This symbol cast to a ClassSymbol representing a class or trait.
     *  @throws ScalaReflectionException if `isClass` is false.
     *
     *  @group Conversions
     */
    def asClass: ClassSymbol = throw new ScalaReflectionException(s"$this is not a class")

    /** Source file if this symbol is created during this compilation run,
     *  or a class file if this symbol is loaded from a *.class or *.jar.
     *
     *  The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
     *  It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
     *  and exposed as a part of scala.reflect.api.
     *
     *  @group Basics
     */
    @deprecated("use `pos.source.file` instead", "2.11.0")
    def associatedFile: scala.reflect.io.AbstractFile

    /** A list of annotations attached to this Symbol.
     *
     *  @group Basics
     */
    def annotations: List[Annotation]

    /** For a class: the module or case class factory with the same name in the same package.
     *  For a module: the class with the same name in the same package.
     *  For all others: NoSymbol.
     *
     *  This API may return unexpected results for module classes, packages and package classes.
     *  Use `companion` instead in order to get predictable results.
     *
     *  @group Basics
     */
    @deprecated("use `companion` instead, but beware of possible changes in behavior", "2.11.0")
    def companionSymbol: Symbol

    /** For a class: its companion object if exists.
     *  For a module or a module class: companion class of the module if exists.
     *  For a package or a package class: NoSymbol.
     *  For all others: NoSymbol.
     */
    def companion: Symbol

    /** @see [[infoIn]] */
    def typeSignatureIn(site: Type): Type

    /** The type signature of this symbol seen as a member of given type `site`.
     *
     *  @group Basics
     */
    def infoIn(site: Type): Type

    /** @see [[info]] */
    def typeSignature: Type

    /** The type signature of this symbol.
     *
     *  This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
     *  instantiation of a generic type. For example, signature
     *  of the method `def map[B](f: (A) ⇒ B): List[B]`, which refers to the type parameter `A` of the declaring class `List[A]`,
     *  will always feature `A`, regardless of whether `map` is loaded from the `List[_]` or from `List[Int]`. To get a signature
     *  with type parameters appropriately instantiated, one should use `infoIn`.
     *
     *  @group Basics
     */
    def info: Type

    /** @see [[overrides]] */
    @deprecated("use `overrides` instead", "2.11.0")
    def allOverriddenSymbols: List[Symbol]

    /** Returns all symbols overridden by this symbol.
     *
     *  @group Basics
     */
    def overrides: List[Symbol]

    /** The overloaded alternatives of this symbol.
     *
     *  @group Basics
     */
    def alternatives: List[Symbol]

    /******************* tests *******************/

    /** Does this symbol represent a synthetic (i.e. a compiler-generated) entity?
     *  Examples of synthetic entities are accessors for vals and vars.
     *
     *  @group Tests
     */
    def isSynthetic: Boolean

    /** Does this symbol represent an implementation artifact that isn't meant for public use?
     *  Examples of such artifacts are erasure bridges and outer fields.
     *
     *  @group Tests
     */
    def isImplementationArtifact: Boolean

    /** Does this symbol represent a declaration or definition written in a source file as `private[this]`
     *  or generated in tree/symbol form with the combination of flags LOCAL and PRIVATE?
     *  If yes, `isPrivate` is guaranteed to be true.
     *
     *  @group Tests
     */
    def isPrivateThis: Boolean

    /** Does this symbol represent a private declaration or definition?
     *  If yes, `privateWithin` might tell more about this symbol's visibility scope.
     *
     *  @group Tests
     */
    def isPrivate: Boolean

    /** Does this symbol represent a declaration or definition written in a source file as `protected[this]`
     *  or generated in tree/symbol form with the combination of flags LOCAL and PROTECTED?
     *  If yes, `isProtected` is guaranteed to be true,
     *
     *  @group Tests
     */
    def isProtectedThis: Boolean

    /** Does this symbol represent a protected declaration or definition?
     *  If yes, `privateWithin` might tell more about this symbol's visibility scope.
     *
     *  @group Tests
     */
    def isProtected: Boolean

    /** Does this symbol represent a public declaration or definition?
     *
     *  @group Tests
     */
    def isPublic: Boolean

    /**
     *  Set when symbol has a modifier of the form private[X] or protected[X], NoSymbol otherwise.
     *
     *  Access level encoding: there are three scala flags (PRIVATE, PROTECTED,
     *  and LOCAL) which combine with value privateWithin (the "foo" in private[foo])
     *  to define from where an entity can be accessed.  The meanings are as follows:
     *
     *  PRIVATE     access restricted to class only.
     *  PROTECTED   access restricted to class and subclasses only.
     *  LOCAL       can only be set in conjunction with PRIVATE or PROTECTED.
     *              Further restricts access to the same object instance.
     *
     *  In addition, privateWithin can be used to set a visibility barrier.
     *  When set, everything contained in the named enclosing package or class
     *  has access.  It is incompatible with PRIVATE or LOCAL, but is additive
     *  with PROTECTED (i.e. if either the flags or privateWithin allow access,
     *  then it is allowed.)
     *
     *  The java access levels translate as follows:
     *
     *  java private:     isPrivate                  && (privateWithin == NoSymbol)
     *  java package:     !isPrivate && !isProtected && (privateWithin == enclosingPackage)
     *  java protected:   isProtected                && (privateWithin == enclosingPackage)
     *  java public:      !isPrivate && !isProtected && (privateWithin == NoSymbol)
     *
     *  @group Tests
     */
    def privateWithin: Symbol

    /** Does this symbol represent the definition of a package?
     *  Known issues: [[https://issues.scala-lang.org/browse/SI-6732]].
     *
     *  @group Tests
     */
    def isPackage: Boolean

    /** Does this symbol represent a package class?
     *  If yes, `isClass` is also guaranteed to be true.
     *
     *  @group Tests
     */
    def isPackageClass: Boolean

    /** Is this symbol static (i.e. with no outer instance)?
     *  Q: When exactly is a sym marked as STATIC?
     *  A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
     *  http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
     *
     *  @group Tests
     */
    def isStatic: Boolean

    /** Is this symbol final?
     *
     *  @group Tests
     */
    def isFinal: Boolean

    /** Is this symbol abstract (i.e. an abstract class, an abstract method, value or type member)?
     *
     *  @group Tests
     */
    def isAbstract: Boolean

    /** Is this symbol labelled as "abstract override"?
     *
     *  @group Tests
     */
    def isAbstractOverride: Boolean

    /** Is this symbol a macro?
     *
     *  @group Tests
     */
    def isMacro: Boolean

    /** Is this symbol a parameter (either a method parameter or a type parameter)?
     *
     *  @group Tests
     */
    def isParameter: Boolean

    /** Is this symbol a specialized type parameter or a generated specialized member?
     *
     *  @group Tests
     */
    def isSpecialized: Boolean

    /** Is this symbol defined by Java?
     *
     *  @group Tests
     */
    def isJava: Boolean

    /** Does this symbol represent an implicit value, definition, class or parameter?
     *
     *  @group Tests
     */
    def isImplicit: Boolean

    /** Does this symbol represent a java enum class or a java enum value?
      *
      *  @group Tests
      */
    def isJavaEnum: Boolean

    /** Does this symbol represent a java annotation interface?
      *
      *  @group Tests
      */
    def isJavaAnnotation: Boolean

    /******************* helpers *******************/

    /** Provides an alternate if symbol is a NoSymbol.
     *
     *  @group Helpers
     */
    def orElse(alt: => Symbol): Symbol

    /** Filters the underlying alternatives (or a single-element list
     *  composed of the symbol itself if the symbol is not overloaded).
     *  Returns an overloaded symbol is there are multiple matches.
     *  Returns a NoSymbol if there are no matches.
     *
     *  @group Helpers
     */
    def filter(cond: Symbol => Boolean): Symbol

    /** If this is a NoSymbol, returns NoSymbol, otherwise
     *  returns the result of applying `f` to this symbol.
     *
     *  @group Helpers
     */
    def map(f: Symbol => Symbol): Symbol

    /** Does the same as `filter`, but crashes if there are multiple matches.
     *
     *  @group Helpers
     */
    def suchThat(cond: Symbol => Boolean): Symbol
  }

  /** The API of term symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   */
  trait TermSymbolApi extends SymbolApi { this: TermSymbol =>
    /** Term symbols have their names of type `TermName`.
     */
    final type NameType = TermName

    final override def isTerm = true
    final override def asTerm = this

    /** Is this symbol introduced as `val`?
     *
     *  @group Term
     */
    def isVal: Boolean

    /** Does this symbol denote a stable value?
     *
     *  @group Term
     */
    def isStable: Boolean

    /** Is this symbol introduced as `var`?
     *
     *  @group Term
     */
    def isVar: Boolean

    /** Does this symbol represent a getter or a setter?
     *
     *  @group Term
     */
    def isAccessor: Boolean

    /** Does this symbol represent a getter of a field?
     *  If yes, `isMethod` is also guaranteed to be true.
     *
     *  @group Term
     */
    def isGetter: Boolean

    /** Does this symbol represent a setter of a field?
     *  If yes, `isMethod` is also guaranteed to be true.
     *
     *  @group Term
     */
    def isSetter: Boolean

    /** Does this symbol represent an overloaded method?
     *  If yes, `isMethod` is false, and the list of the enclosed alternatives can be found out via `alternatives`.
     *
     *  @group Term
     */
    def isOverloaded   : Boolean

    /** Does this symbol represent a lazy value?
     *
     *  @group Term
     */
    def isLazy: Boolean

    /** Used to provide a better error message for `asMethod` */
    override protected def isOverloadedMethod = alternatives exists (_.isMethod)

    /** Backing field for an accessor method, NoSymbol for all other term symbols.
     *
     *  @group Term
     */
    def accessed: Symbol

    /** Getter method for a backing field of a val or a val, NoSymbol for all other term symbols.
     *
     *  @group Term
     */
    def getter: Symbol

    /** Setter method for a backing field of a val or a val, NoSymbol for all other term symbols.
     *
     *  @group Term
     */
    def setter: Symbol

    /** Does this symbol represent a field of a class
     *  that was generated from a parameter of that class?
     *
     *  @group Term
     */
    def isParamAccessor: Boolean

    /** Does this symbol represent a field of a case class
     *  that corresponds to a parameter in the first parameter list of the
     *  primary constructor of that class?
     *
     *  @group Term
     */
    def isCaseAccessor: Boolean

    /** Does this symbol represent a parameter with a default value?
     *
     *  @group Term
     */
    def isParamWithDefault: Boolean

    /** Does this symbol represent a by-name parameter?
     *
     *  @group Term
     */
    def isByNameParam: Boolean
  }

  /** The API of type symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   */
  trait TypeSymbolApi extends SymbolApi { this: TypeSymbol =>
    /** Type symbols have their names of type `TypeName`.
     */
    final type NameType = TypeName

    /** The type constructor corresponding to this type symbol.
     *  This is different from `toType` in that type parameters
     *  are part of results of `toType`, but not of `toTypeConstructor`.
     *
     *  Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
     *  `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`.
     *
     *  @group Type
     */
    def toTypeConstructor: Type

    /** A type reference that refers to this type symbol seen
     *  as a member of given type `site`.
     *
     *  @group Type
     */
    def toTypeIn(site: Type): Type

    /**  A type reference that refers to this type symbol.
      *  Note if symbol is a member of a class, one almost always is interested
      *  in `asTypeIn` with a site type instead.
      *
      *  Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
      *  `C`. Then `C.toType` is the type `C[T]`.
      *
      *  By contrast, `C.info` would be a type signature of form
      *  `PolyType(ClassInfoType(...))` that describes type parameters, value
      *  parameters, parent types, and members of `C`.
     *
     *  @group Type
     */
    def toType: Type

    final override def isType = true
    final override def asType = this

    /** Is the type parameter represented by this symbol contravariant?
     *
     *  @group Type
     */
    def isContravariant : Boolean

    /** Is the type parameter represented by this symbol contravariant?
     *
     *  @group Type
     */
    def isCovariant     : Boolean

    /** Does this symbol represent the definition of a type alias?
     *
     *  @group Type
     */
    def isAliasType    : Boolean

    /** Does this symbol represent the definition of an abstract type?
     *
     *  @group Type
     */
    @deprecated("use isAbstract instead", "2.11.0")
    def isAbstractType : Boolean

    /** Does this symbol represent an existentially bound type?
     *
     *  @group Type
     */
    def isExistential  : Boolean

    /** For a polymorphic type, its type parameters, the empty list for all other types.
     *
     *  @group Type
     */
    def typeParams: List[Symbol]
  }

  /** The API of method symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   */
  trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol =>
    final override def isMethod = true
    final override def asMethod = this

    /** Does this symbol denote the primary constructor of its enclosing class?
     *
     *  @group Method
     */
    def isPrimaryConstructor: Boolean

    /** For a polymorphic method, its type parameters, the empty list for all other methods
     *
     *  @group Method
     */
    def typeParams: List[Symbol]

    /** @see [[paramLists]]
     *
     * The name ending with "ss" indicates that the result type is a list of lists. */
    @deprecated("use `paramLists` instead", "2.11.0")
    def paramss: List[List[Symbol]]

    /** All parameter lists of the method.
     *
     *  Can be used to distinguish nullary methods and methods with empty parameter lists.
     *  For a nullary method, returns the empty list (i.e. `List()`).
     *  For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`).
     *
     *  @group Method
     */
    def paramLists: List[List[Symbol]]

    /** Does this method support variable length argument lists?
     *
     *  @group Method
     */
    def isVarargs: Boolean

    /** The return type of the method.
     *
     *  @group Method
     */
    def returnType: Type

    /** Exceptions that this method is known to throw.
     *  For Scala methods, the list is calculated from [[throws]] annotations present on a method.
     *  For Java methods, the list is calculated from `throws` clauses attached to the method and stored in bytecode.
     *
     *  @group Method
     */
    def exceptions: List[Symbol]
  }

  /** The API of module symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   */
  trait ModuleSymbolApi extends TermSymbolApi { this: ModuleSymbol =>
    /** The class implicitly associated with the object definition.
     *  One can go back from a module class to the associated module symbol
     *  by inspecting its `selfType.termSymbol`.
     *
     *  @group Module
     */
    def moduleClass: Symbol // needed for tree traversals
    // when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life

    final override def isModule = true
    final override def asModule = this
  }

  /** The API of class symbols.
   *  The main source of information about symbols is the [[Symbols]] page.
   *
   *  $SYMACCESSORS
   *  @group API
   */
  trait ClassSymbolApi extends TypeSymbolApi { this: ClassSymbol =>
    final override def isClass = true
    final override def asClass = this

    /** Does this symbol represent the definition of a primitive class?
     *  Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
     *  [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
     *
     *  @group Class
     */
    def isPrimitive: Boolean

    /** Does this symbol represent the definition of a numeric value class?
     *  Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
     *  [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
     *
     *  @group Class
     */
    def isNumeric: Boolean

    /** Does this symbol represent the definition of a custom value class?
     *  Namely, is AnyVal among its parent classes?
     *
     *  @group Class
     */
    def isDerivedValueClass: Boolean

    /** Does this symbol represent a trait?
     *
     *  @group Class
     */
    def isTrait: Boolean

    /** Does this symbol represent an abstract class?
     *
     *  @group Class
     */
    @deprecated("use isAbstract instead", "2.11.0")
    def isAbstractClass: Boolean

    /** Does this symbol represent a case class?
     *
     *  @group Class
     */
    def isCaseClass: Boolean

    /** Does this symbol represent a sealed class?
     *
     *  @group Class
     */
    def isSealed: Boolean

    /** If this is a sealed class, its known direct subclasses.
     *  Otherwise, the empty set.
     *
     *  @group Class
     */
    def knownDirectSubclasses: Set[Symbol]

    /** The list of all base classes of this type (including its own typeSymbol)
     *  in linearization order, starting with the class itself and ending
     *  in class Any.
     *
     *  @group Class
     */
    def baseClasses: List[Symbol]

    /** The module corresponding to this module class,
     *  or NoSymbol if this symbol is not a module class.
     *
     *  @group Class
     */
    def module: Symbol

    /** If this symbol is a class or trait, its self type, otherwise the type
     *  of the symbol itself.
     *
     *  @group Class
     */
    def selfType: Type

    /** The type `C.this`, where `C` is the current class
     *
     *  @group Class
     */
    def thisPrefix: Type

    /** The type `C.super[M]`, where `C` is the current class and `M` is supertpe.
     *
     *  @group Class
     */
    def superPrefix(supertpe: Type): Type

    /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait.
     *
     *  @group Class
     */
    def typeParams: List[Symbol]

    /** For a Scala class or module class, the primary constructor of the class.
     *  For a Scala trait, its mixin constructor.
     *  For a Scala package class, NoSymbol.
     *  For a Java class, NoSymbol.
     *
     *  Known issues: Due to SI-8367, primaryConstructor may return unexpected results
     *  when called for Java classes (for some vague definition of a "Java class", which apparently
     *  not only includes javac-produced classfiles, but also consists of classes defined in
     *  Scala programs under the java.lang package). What's even worse, for some Java classes
     *  we can't even guarantee stability of the return value - depending on your classloader configuration
     *  and/or JDK version you might get different primaryConstructor for the same ClassSymbol.
     *  We have logged these issues at SI-8193.
     *
     *  @group Class
     */
    // TODO: SI-8193 I think we should only return a non-empty symbol if called for Scala classes
    // returning something for traits and module classes is outright confusing
    // This, however, will require some refactoring in the compiler, so I'll leave it for later
    // as at the moment we don't have time or risk tolerance for that
    def primaryConstructor: Symbol
  }
}