-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathFeature.scala
158 lines (129 loc) · 5.86 KB
/
Feature.scala
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
package dotty.tools
package dotc
package config
import core._
import Contexts._, Symbols._, Names._
import StdNames.nme
import Decorators.*
import util.{SrcPos, NoSourcePosition}
import SourceVersion._
import reporting.Message
import NameKinds.QualifiedName
object Feature:
def experimental(str: PreName): TermName =
QualifiedName(nme.experimental, str.toTermName)
private def deprecated(str: PreName): TermName =
QualifiedName(nme.deprecated, str.toTermName)
private val namedTypeArguments = experimental("namedTypeArguments")
private val genericNumberLiterals = experimental("genericNumberLiterals")
val scala2macros = experimental("macros")
val dependent = experimental("dependent")
val erasedDefinitions = experimental("erasedDefinitions")
val symbolLiterals = deprecated("symbolLiterals")
val fewerBraces = experimental("fewerBraces")
val saferExceptions = experimental("saferExceptions")
val pureFunctions = experimental("pureFunctions")
val captureChecking = experimental("captureChecking")
val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking)
/** Is `feature` enabled by by a command-line setting? The enabling setting is
*
* -language:<prefix>feature
*
* where <prefix> is the fully qualified name of `owner`, followed by a ".",
* but subtracting the prefix `scala.language.` at the front.
*/
def enabledBySetting(feature: TermName)(using Context): Boolean =
ctx.base.settings.language.value.contains(feature.toString)
/** Is `feature` enabled by by an import? This is the case if the feature
* is imported by a named import
*
* import owner.feature
*
* and there is no visible nested import that excludes the feature, as in
*
* import owner.{ feature => _ }
*/
def enabledByImport(feature: TermName)(using Context): Boolean =
//atPhase(typerPhase) {
val info = ctx.importInfo
info != null && info.featureImported(feature)
//}
/** Is `feature` enabled by either a command line setting or an import?
* @param feature The name of the feature
* @param owner The prefix symbol (nested in `scala.language`) where the
* feature is defined.
*/
def enabled(feature: TermName)(using Context): Boolean =
enabledBySetting(feature) || enabledByImport(feature)
/** Is auto-tupling enabled? */
def autoTuplingEnabled(using Context): Boolean = !enabled(nme.noAutoTupling)
def dynamicsEnabled(using Context): Boolean = enabled(nme.dynamics)
def dependentEnabled(using Context) = enabled(dependent)
def namedTypeArgsEnabled(using Context) = enabled(namedTypeArguments)
def genericNumberLiteralsEnabled(using Context) = enabled(genericNumberLiterals)
def scala2ExperimentalMacroEnabled(using Context) = enabled(scala2macros)
def pureFunsEnabled(using Context) =
enabledBySetting(pureFunctions)
|| ctx.compilationUnit.knowsPureFuns
|| ccEnabled
def ccEnabled(using Context) =
enabledBySetting(captureChecking)
|| ctx.compilationUnit.needsCaptureChecking
def pureFunsEnabledSomewhere(using Context) =
enabledBySetting(pureFunctions)
|| enabledBySetting(captureChecking)
|| ctx.run != null && ctx.run.nn.pureFunsImportEncountered
def sourceVersionSetting(using Context): SourceVersion =
SourceVersion.valueOf(ctx.settings.source.value)
def sourceVersion(using Context): SourceVersion =
ctx.compilationUnit.sourceVersion match
case Some(v) => v
case none => sourceVersionSetting
def migrateTo3(using Context): Boolean =
sourceVersion == `3.0-migration`
def fewerBracesEnabled(using Context) =
sourceVersion.isAtLeast(`3.3`) || enabled(fewerBraces)
/** If current source migrates to `version`, issue given warning message
* and return `true`, otherwise return `false`.
*/
def warnOnMigration(msg: Message, pos: SrcPos, version: SourceVersion)(using Context): Boolean =
if sourceVersion.isMigrating && sourceVersion.stable == version
|| (version == `3.0` || version == `3.1`) && migrateTo3
then
report.migrationWarning(msg, pos)
true
else
false
def checkExperimentalFeature(which: String, srcPos: SrcPos, note: => String = "")(using Context) =
if !isExperimentalEnabled then
report.error(i"Experimental $which may only be used with a nightly or snapshot version of the compiler$note", srcPos)
def checkExperimentalDef(sym: Symbol, srcPos: SrcPos)(using Context) =
if !isExperimentalEnabled then
val symMsg =
if sym.hasAnnotation(defn.ExperimentalAnnot) then
i"$sym is marked @experimental"
else if sym.owner.hasAnnotation(defn.ExperimentalAnnot) then
i"${sym.owner} is marked @experimental"
else
i"$sym inherits @experimental"
report.error(s"$symMsg and therefore may only be used in an experimental scope.", srcPos)
/** Check that experimental compiler options are only set for snapshot or nightly compiler versions. */
def checkExperimentalSettings(using Context): Unit =
for setting <- ctx.settings.language.value
if setting.startsWith("experimental.") && setting != "experimental.macros"
do checkExperimentalFeature(s"feature $setting", NoSourcePosition)
def isExperimentalEnabled(using Context): Boolean =
Properties.experimental && !ctx.settings.YnoExperimental.value
def handleGlobalLanguageImport(prefix: TermName, imported: Name)(using Context): Boolean =
val fullFeatureName = QualifiedName(prefix, imported.asTermName)
if fullFeatureName == pureFunctions then
ctx.compilationUnit.knowsPureFuns = true
if ctx.run != null then ctx.run.nn.pureFunsImportEncountered = true
true
else if fullFeatureName == captureChecking then
ctx.compilationUnit.needsCaptureChecking = true
if ctx.run != null then ctx.run.nn.pureFunsImportEncountered = true
true
else
false
end Feature