Skip to content

Commit d543f4d

Browse files
committed
Merge remote-tracking branch 'upstream/main' into en-migrate-main
2 parents 193c7a6 + fae7c09 commit d543f4d

File tree

118 files changed

+1345
-5993
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+1345
-5993
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ jobs:
111111

112112
- name: Cmd Tests
113113
run: |
114-
./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test;sjsCompilerTests/test ;sbt-test/scripted scala2-compat/* ;configureIDE ;stdlib-bootstrapped/test:run ;stdlib-bootstrapped-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test"
114+
./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test;sjsCompilerTests/test ;sbt-test/scripted scala2-compat/* ;stdlib-bootstrapped/test:run ;stdlib-bootstrapped-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test"
115115
./project/scripts/cmdTests
116116
./project/scripts/bootstrappedOnlyCmdTests
117117
@@ -447,7 +447,7 @@ jobs:
447447

448448
- name: Test
449449
run: |
450-
./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test;sjsCompilerTests/test ;sbt-test/scripted scala2-compat/* ;configureIDE ;stdlib-bootstrapped/test:run ;stdlib-bootstrapped-tasty-tests/test"
450+
./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test;sjsCompilerTests/test ;sbt-test/scripted scala2-compat/* ;stdlib-bootstrapped/test:run ;stdlib-bootstrapped-tasty-tests/test"
451451
./project/scripts/cmdTests
452452
./project/scripts/bootstrappedOnlyCmdTests
453453

.github/workflows/scaladoc.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
PR_NUMBER: ${{ github.event.pull_request.number }}
6969
with:
7070
inlineScript: |
71-
DOC_DEST=pr-${PR_NUMBER:-${GITHUB_REF##*/}}
71+
DOC_DEST=$(echo pr-${PR_NUMBER:-${GITHUB_REF##*/}} | tr -d -c "[-A-Za-z0-9]")
7272
echo uplading docs to https://scala3doc.virtuslab.com/$DOC_DEST
7373
az storage container create --name $DOC_DEST --account-name scala3docstorage --public-access container
7474
az storage blob upload-batch -s scaladoc/output -d $DOC_DEST --account-name scala3docstorage

.gitignore

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,6 @@ node_modules
3030
.metals/
3131
metals.sbt
3232

33-
# Scala-IDE specific
34-
.scala_dependencies
35-
.cache
36-
.cache-main
37-
.cache-tests
38-
.classpath
39-
.project
40-
.settings
41-
classes/
42-
*/bin/
43-
44-
# Dotty IDE
45-
/.dotty-ide-dev-port
46-
/.dotty-ide-artifact
47-
/.dotty-ide.json
48-
4933
# idea
5034
.idea
5135
.idea_modules
@@ -79,10 +63,6 @@ compiler/test/debug/Gen.jar
7963
compiler/before-pickling.txt
8064
compiler/after-pickling.txt
8165
bench/compile.txt
82-
*.dotty-ide-version
83-
84-
# The vscode app for testing
85-
vscode-dotty/.vscode-test
8666

8767
community-build/scala3-bootstrapped.version
8868
community-build/sbt-dotty-sbt

CONTRIBUTING.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ This is the process for committing code to the Scala project. There are of cours
1212
2. The ticket has been discussed and prioritized by the team.
1313
3. You should always perform your work in its own Git branch. The branch should be given a descriptive name that explains its intent. Some teams also like adding the ticket number and/or the [GitHub](http://github.com) user ID to the branch name, these details is up to each of the individual teams. (See below for more details on branch naming.)
1414
4. When the feature or fix is completed you should open a [Pull Request](https://help.github.com/articles/using-pull-requests) on GitHub.
15-
5. The Pull Request should be reviewed by other maintainers (as many as feasible/practical). Note that a reviewer can also be an outside contributor—members of Typesafe and independent contributors are encouraged to participate in the review process. It is not a closed process. Please try to avoid conflict of interest—the spirit of the review process is to evenly distribute the understanding of our code base across its maintainers as well as to load balance quality assurance. Assigning a review to a "sure win" reviewer is not a good long-term solution.
15+
5. The Pull Request should be reviewed by other maintainers (as many as feasible/practical). Note that a reviewer can also be an outside contributor—members of Typesafe or VirtusLab and independent contributors are encouraged to participate in the review process. It is not a closed process. Please try to avoid conflict of interest—the spirit of the review process is to evenly distribute the understanding of our code base across its maintainers as well as to load balance quality assurance. Assigning a review to a "sure win" reviewer is not a good long-term solution.
1616
6. After the review, you should resolve issues brought up by the reviewers as needed (pushing a new commit to address reviewers' comments), iterating until the reviewers give their thumbs up, the "LGTM" (acronym for "Looks Good To Me").
1717
7. Once the code has passed review the Pull Request can be merged into the distribution.
1818

1919
## Pull Request Requirements
2020

21-
First, please have a look at and follow the [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for guidelines on submitting a pull request to the dotty project. (the pull request policy is the same as for the Scala programming language)
22-
2321
In order for a Pull Request to be considered, it has to meet these requirements:
2422

2523
1. Live up to the current code standard:
@@ -39,7 +37,7 @@ All contributed code should come accompanied by documentation. Pull requests con
3937

4038
It is ok to work on a public feature branch in the GitHub repository. Something that can sometimes be useful for early feedback etc. If so, then it is preferable to name the branch accordingly. This can be done by either prefixing the name with ``wip-`` as in ‘Work In Progress’, or use hierarchical names like ``wip/..``, ``feature/..`` or ``topic/..``. Either way is fine as long as it is clear that it is work in progress and not ready for merge. This work can temporarily have a lower standard. However, to be merged into master it will have to go through the regular process outlined above, with Pull Request, review etc..
4139

42-
Also, to facilitate both well-formed commits and working together, the ``wip`` and ``feature``/``topic`` identifiers also have special meaning. Any branch labelled with ``wip`` is considered “git-unstable” and may be rebased and have its history rewritten. Any branch with ``feature``/``topic`` in the name is considered “stable” enough for others to depend on when a group is working on a feature.
40+
Also, to facilitate both well-formed commits and working together, the ``wip`` and ``feature``/``topic`` identifiers also have special meaning. Any branch labeled with ``wip`` is considered “git-unstable” and may be rebased and have its history rewritten. Any branch with ``feature``/``topic`` in the name is considered “stable” enough for others to depend on when a group is working on a feature.
4341

4442
## Creating Commits And Writing Commit Messages
4543

@@ -60,4 +58,3 @@ Example:
6058
- Details 1
6159
- Details 2
6260
- Details 3
63-

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ Dotty
33
[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amain)
44
[![Join the chat at https://discord.com/invite/scala](https://img.shields.io/discord/632150470000902164)](https://discord.com/invite/scala)
55

6-
* [Homepage](https://dotty.epfl.ch)
7-
* [Documentation](https://dotty.epfl.ch/docs)
6+
* [Documentation](https://docs.scala-lang.org/scala3/)
87

98
Try it out
109
==========
11-
To try it in your project see also the [Getting Started User Guide](https://dotty.epfl.ch/#getting-started).
10+
To try it in your project see also the [Getting Started User Guide](https://docs.scala-lang.org/scala3/getting-started.html).
1211

1312
Building a Local Distribution
1413
=============================
@@ -23,7 +22,7 @@ other more direct lines of communication such as email.
2322

2423
How to Contribute
2524
=================
26-
* [Getting Started as Contributor](https://dotty.epfl.ch/docs/contributing/getting-started.html)
25+
* [Getting Started as Contributor](https://docs.scala-lang.org/scala3/guides/contribution/contribution-intro.html)
2726
* [Issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
2827

2928
License

build.sbt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ val sjsJUnitTests = Build.sjsJUnitTests
3333
val sjsCompilerTests = Build.sjsCompilerTests
3434

3535
val `sbt-test` = Build.`sbt-test`
36-
val `vscode-dotty` = Build.`vscode-dotty`
3736

3837
inThisBuild(Build.thisBuildSettings)
3938
inScope(Global)(Build.globalSettings)

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,20 @@ import scala.annotation.internal.sharable
1616
object DesugarEnums {
1717
import untpd._
1818

19-
@sharable object CaseKind extends Enumeration {
20-
val Simple, Object, Class: Value = Value
21-
}
19+
enum CaseKind:
20+
case Simple, Object, Class
2221

23-
final case class EnumConstraints(minKind: CaseKind.Value, maxKind: CaseKind.Value, enumCases: List[(Int, RefTree)]):
24-
require(minKind <= maxKind && !(cached && enumCases.isEmpty))
22+
final case class EnumConstraints(minKind: CaseKind, maxKind: CaseKind, enumCases: List[(Int, RefTree)]):
23+
require(minKind.ordinal <= maxKind.ordinal && !(cached && enumCases.isEmpty))
2524
def requiresCreator = minKind == CaseKind.Simple
26-
def isEnumeration = maxKind < CaseKind.Class
27-
def cached = minKind < CaseKind.Class
25+
def isEnumeration = maxKind.ordinal < CaseKind.Class.ordinal
26+
def cached = minKind.ordinal < CaseKind.Class.ordinal
2827
end EnumConstraints
2928

3029
/** Attachment containing the number of enum cases, the smallest kind that was seen so far,
3130
* and a list of all the value cases with their ordinals.
3231
*/
33-
val EnumCaseCount: Property.Key[(Int, CaseKind.Value, CaseKind.Value, List[(Int, TermName)])] = Property.Key()
32+
val EnumCaseCount: Property.Key[(Int, CaseKind, CaseKind, List[(Int, TermName)])] = Property.Key()
3433

3534
/** Attachment signalling that when this definition is desugared, it should add any additional
3635
* lookup methods for enums.
@@ -249,11 +248,11 @@ object DesugarEnums {
249248
* - scaffolding containing the necessary definitions for singleton enum cases
250249
* unless that scaffolding was already generated by a previous call to `nextEnumKind`.
251250
*/
252-
def nextOrdinal(name: Name, kind: CaseKind.Value, definesLookups: Boolean)(using Context): (Int, List[Tree]) = {
251+
def nextOrdinal(name: Name, kind: CaseKind, definesLookups: Boolean)(using Context): (Int, List[Tree]) = {
253252
val (ordinal, seenMinKind, seenMaxKind, seenCases) =
254253
ctx.tree.removeAttachment(EnumCaseCount).getOrElse((0, CaseKind.Class, CaseKind.Simple, Nil))
255-
val minKind = if kind < seenMinKind then kind else seenMinKind
256-
val maxKind = if kind > seenMaxKind then kind else seenMaxKind
254+
val minKind = if kind.ordinal < seenMinKind.ordinal then kind else seenMinKind
255+
val maxKind = if kind.ordinal > seenMaxKind.ordinal then kind else seenMaxKind
257256
val cases = name match
258257
case name: TermName => (ordinal, name) :: seenCases
259258
case _ => seenCases

compiler/src/dotty/tools/dotc/config/CliCommand.scala

Lines changed: 73 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import scala.language.unsafeNulls
55

66
import Settings._
77
import core.Contexts._
8+
import printing.Highlighting
89

10+
import scala.util.chaining.given
911
import scala.PartialFunction.cond
1012

1113
trait CliCommand:
@@ -51,59 +53,31 @@ trait CliCommand:
5153
end distill
5254

5355
/** Creates a help message for a subset of options based on cond */
54-
protected def availableOptionsMsg(cond: Setting[?] => Boolean)(using settings: ConcreteSettings)(using SettingsState): String =
55-
val ss = (settings.allSettings filter cond).toList sortBy (_.name)
56-
val maxNameWidth = 30
57-
val nameWidths = ss.map(_.name.length).partition(_ < maxNameWidth)._1
58-
val width = if nameWidths.nonEmpty then nameWidths.max else maxNameWidth
59-
val terminalWidth = settings.pageWidth.value
60-
val (nameWidth, descriptionWidth) = {
61-
val w1 =
62-
if width < maxNameWidth then width
63-
else maxNameWidth
64-
val w2 =
65-
if terminalWidth < w1 + maxNameWidth then 0
66-
else terminalWidth - w1 - 1
67-
(w1, w2)
68-
}
69-
def formatName(name: String) =
70-
if name.length <= nameWidth then ("%-" + nameWidth + "s") format name
71-
else (name + "\n%-" + nameWidth + "s") format ""
72-
def formatDescription(text: String): String =
73-
if descriptionWidth == 0 then text
74-
else if text.length < descriptionWidth then text
75-
else {
76-
val inx = text.substring(0, descriptionWidth).lastIndexOf(" ")
77-
if inx < 0 then text
78-
else
79-
val str = text.substring(0, inx)
80-
s"${str}\n${formatName("")} ${formatDescription(text.substring(inx + 1))}"
81-
}
82-
def formatSetting(name: String, value: String) =
83-
if (value.nonEmpty)
84-
// the format here is helping to make empty padding and put the additional information exactly under the description.
85-
s"\n${formatName("")} $name: $value."
86-
else
87-
""
88-
def helpStr(s: Setting[?]) =
56+
protected def availableOptionsMsg(p: Setting[?] => Boolean)(using settings: ConcreteSettings)(using SettingsState): String =
57+
// result is (Option Name, descrption\ndefault: value\nchoices: x, y, z
58+
def help(s: Setting[?]): (String, String) =
59+
// For now, skip the default values that do not make sense for the end user, such as 'false' for the version command.
8960
def defaultValue = s.default match
9061
case _: Int | _: String => s.default.toString
91-
case _ =>
92-
// For now, skip the default values that do not make sense for the end user.
93-
// For example 'false' for the version command.
94-
""
95-
s"${formatName(s.name)} ${formatDescription(shortHelp(s))}${formatSetting("Default", defaultValue)}${formatSetting("Choices", s.legalChoices)}"
96-
ss.map(helpStr).mkString("", "\n", s"\n${formatName("@<file>")} ${formatDescription("A text file containing compiler arguments (options and source files).")}\n")
62+
case _ => ""
63+
val info = List(shortHelp(s), if defaultValue.nonEmpty then s"Default $defaultValue" else "", if s.legalChoices.nonEmpty then s"Choices ${s.legalChoices}" else "")
64+
(s.name, info.filter(_.nonEmpty).mkString("\n"))
65+
end help
66+
67+
val ss = settings.allSettings.filter(p).toList.sortBy(_.name)
68+
val formatter = Columnator("", "", maxField = 30)
69+
val fresh = ContextBase().initialCtx.fresh.setSettings(summon[SettingsState])
70+
formatter(List(ss.map(help) :+ ("@<file>", "A text file containing compiler arguments (options and source files).")))(using fresh)
9771
end availableOptionsMsg
9872

9973
protected def shortUsage: String = s"Usage: $cmdName <options> <source files>"
10074

10175
protected def createUsageMsg(label: String, shouldExplain: Boolean, cond: Setting[?] => Boolean)(using settings: ConcreteSettings)(using SettingsState): String =
10276
val prefix = List(
10377
Some(shortUsage),
104-
Some(explainAdvanced) filter (_ => shouldExplain),
78+
Some(explainAdvanced).filter(_ => shouldExplain),
10579
Some(label + " options include:")
106-
).flatten mkString "\n"
80+
).flatten.mkString("\n")
10781

10882
prefix + "\n" + availableOptionsMsg(cond)
10983

@@ -138,31 +112,10 @@ trait CliCommand:
138112
createUsageMsg("Possible private", shouldExplain = true, isPrivate)
139113

140114
/** Used for the formatted output of -Xshow-phases */
141-
protected def phasesMessage(using ctx: Context): String =
142-
115+
protected def phasesMessage(using Context): String =
143116
val phases = new Compiler().phases
144-
val nameLimit = 25
145-
val maxCol = ctx.settings.pageWidth.value
146-
val maxName = phases.flatten.map(_.phaseName.length).max
147-
val width = maxName.min(nameLimit)
148-
val maxDesc = maxCol - (width + 6)
149-
val fmt = s"%${width}.${width}s %.${maxDesc}s%n"
150-
151-
val sb = new StringBuilder
152-
sb ++= fmt.format("phase name", "description")
153-
sb ++= fmt.format("----------", "-----------")
154-
155-
phases.foreach {
156-
case List(single) =>
157-
sb ++= fmt.format(single.phaseName, single.description)
158-
case Nil => ()
159-
case more =>
160-
sb ++= fmt.format(s"{", "")
161-
more.foreach { mini => sb ++= fmt.format(mini.phaseName, mini.description) }
162-
sb ++= fmt.format(s"}", "")
163-
}
164-
sb.mkString
165-
117+
val formatter = Columnator("phase name", "description", maxField = 25)
118+
formatter(phases.map(mega => mega.map(p => (p.phaseName, p.description))))
166119

167120
/** Provide usage feedback on argument summary, assuming that all settings
168121
* are already applied in context.
@@ -190,3 +143,56 @@ trait CliCommand:
190143

191144
extension [T](setting: Setting[T])
192145
protected def value(using ss: SettingsState): T = setting.valueIn(ss)
146+
147+
extension (s: String)
148+
def padLeft(width: Int): String = String.format(s"%${width}s", s)
149+
150+
// Formatting for -help and -Vphases in two columns, handling long field1 and wrapping long field2
151+
class Columnator(heading1: String, heading2: String, maxField: Int, separation: Int = 2):
152+
def apply(texts: List[List[(String, String)]])(using Context): String = StringBuilder().tap(columnate(_, texts)).toString
153+
154+
private def columnate(sb: StringBuilder, texts: List[List[(String, String)]])(using Context): Unit =
155+
import Highlighting.*
156+
val colors = Seq(Green(_), Yellow(_), Magenta(_), Cyan(_), Red(_))
157+
val nocolor = texts.length == 1
158+
def color(index: Int): String => Highlight = if nocolor then NoColor(_) else colors(index % colors.length)
159+
val maxCol = ctx.settings.pageWidth.value
160+
val field1 = maxField.min(texts.flatten.map(_._1.length).filter(_ < maxField).max) // widest field under maxField
161+
val field2 = if field1 + separation + maxField < maxCol then maxCol - field1 - separation else 0 // skinny window -> terminal wrap
162+
val separator = " " * separation
163+
val EOL = "\n"
164+
def formatField1(text: String): String = if text.length <= field1 then text.padLeft(field1) else text + EOL + "".padLeft(field1)
165+
def formatField2(text: String): String =
166+
def loopOverField2(fld: String): List[String] =
167+
if field2 == 0 || fld.length <= field2 then List(fld)
168+
else
169+
fld.lastIndexOf(" ", field2) match
170+
case -1 => List(fld)
171+
case i => val (prefix, rest) = fld.splitAt(i) ; prefix :: loopOverField2(rest.trim)
172+
text.split("\n").toList.flatMap(loopOverField2).filter(_.nonEmpty).mkString(EOL + "".padLeft(field1) + separator)
173+
end formatField2
174+
def format(first: String, second: String, index: Int, colorPicker: Int => String => Highlight) =
175+
sb.append(colorPicker(index)(formatField1(first)).show)
176+
.append(separator)
177+
.append(formatField2(second))
178+
.append(EOL): Unit
179+
def fancy(first: String, second: String, index: Int) = format(first, second, index, color)
180+
def plain(first: String, second: String) = format(first, second, 0, _ => NoColor(_))
181+
182+
if heading1.nonEmpty then
183+
plain(heading1, heading2)
184+
plain("-" * heading1.length, "-" * heading2.length)
185+
186+
def emit(index: Int)(textPair: (String, String)): Unit = fancy(textPair._1, textPair._2, index)
187+
def group(index: Int)(body: Int => Unit): Unit =
188+
if !ctx.useColors then plain(s"{", "")
189+
body(index)
190+
if !ctx.useColors then plain(s"}", "")
191+
192+
texts.zipWithIndex.foreach { (text, index) =>
193+
text match
194+
case List(single) => emit(index)(single)
195+
case Nil =>
196+
case mega => group(index)(i => mega.foreach(emit(i)))
197+
}
198+
end Columnator

0 commit comments

Comments
 (0)