Skip to content

Commit fc76dc8

Browse files
committed
Specify and describe new indentation rules
1 parent ff90919 commit fc76dc8

File tree

3 files changed

+49
-54
lines changed

3 files changed

+49
-54
lines changed

docs/docs/internals/syntax.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ comment ::= ‘/*’ “any sequence of characters; nested comments ar
8383
8484
nl ::= “new line character”
8585
semi ::= ‘;’ | nl {nl}
86+
colonEol ::= ": at end of line that can start a tenmplate body"
8687
```
8788

8889
## Keywords
@@ -149,7 +150,7 @@ FunArgTypes ::= InfixType
149150
TypedFunParam ::= id ‘:’ Type
150151
MatchType ::= InfixType `match` ‘{’ TypeCaseClauses ‘}’
151152
InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2)
152-
RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds)
153+
RefinedType ::= WithType {[nl | colonEol] Refinement} RefinedTypeTree(t, ds)
153154
WithType ::= AnnotType {‘with’ AnnotType} (deprecated)
154155
AnnotType ::= SimpleType {Annotation} Annotated(t, annot)
155156
SimpleType ::= SimpleType TypeArgs AppliedTypeTree(t, args)
@@ -402,7 +403,8 @@ ConstrExpr ::= SelfInvocation
402403
| ‘{’ SelfInvocation {semi BlockStat} ‘}’
403404
SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs}
404405
405-
TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’ (self, stats)
406+
TemplateBody ::= [nl | colonEol]
407+
‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’ (self, stats)
406408
TemplateStat ::= Import
407409
| Export
408410
| {Annotation [nl]} {Modifier} Def
@@ -412,7 +414,8 @@ TemplateStat ::= Import
412414
SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _)
413415
| ‘this’ ‘:’ InfixType ‘=>’
414416
415-
EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
417+
EnumBody ::= [nl | colonEol]
418+
‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
416419
EnumStat ::= TemplateStat
417420
| {Annotation [nl]} {Modifier} EnumCase
418421
EnumCase ::= ‘case’ (id ClassConstr [‘extends’ ConstrApps]] | ids)
@@ -424,7 +427,7 @@ TopStat ::= Import
424427
| Packaging
425428
| PackageObject
426429
|
427-
Packaging ::= ‘package’ QualId [nl] ‘{’ TopStatSeq ‘}’ Package(qid, stats)
430+
Packaging ::= ‘package’ QualId [nl | colonEol] ‘{’ TopStatSeq ‘}’ Package(qid, stats)
428431
PackageObject ::= ‘package’ ‘object’ ObjectDef object with package in mods.
429432
430433
CompilationUnit ::= {‘package’ QualId semi} TopStatSeq Package(qid, stats)

docs/docs/reference/other-new-features/indentation-new.md

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ There are two rules:
5858
An indentation region can start
5959

6060
- after the condition of an `if-else`, or
61-
- after the leading parameter(s) of a given extension method clause, or
61+
- after a ": at end of line" token (see below)
6262
- after one of the following tokens:
6363
```
64-
= => <- : if then else while do try catch finally for yield match return
64+
= => <- if then else while do try catch finally for yield match return
6565
```
6666
If an `<indent>` is inserted, the indentation width of the token on the next line
6767
is pushed onto `IW`, which makes it the new current indentation width.
@@ -90,65 +90,57 @@ if x < 0
9090
Indentation tokens are only inserted in regions where newline statement separators are also inferred:
9191
at the toplevel, inside braces `{...}`, but not inside parentheses `(...)`, patterns or types.
9292

93-
### New Role of With
93+
### Optional Braces Around Template Bodies
9494

95-
To make bracews optional for constructs like class bodies, the syntax of the language is changed so that a class body or similar construct may optionally be prefixed with `with`. Since `with` can start an indentation region, this means that all of the following syntaxes are allowed and are equivalent:
96-
```scala
97-
trait A {
98-
def f: Any
99-
}
100-
class C(x: Int) extends A {
101-
def f = x
102-
}
103-
type T = A {
104-
def f: Int
105-
}
106-
```
107-
---
108-
```scala
109-
trait A: {
110-
def f: Int
111-
}
112-
class C(x: Int) extends A: {
113-
def f = x
114-
}
115-
type T = A: {
116-
def f: Int
117-
}
118-
```
119-
---
95+
The Scala grammar uses the term _template body_ for the definitions of a class, trait, object, given instance or extension that are normally enclosed in braces. The braces around a template body can also be omitted by means of the following rule:
96+
97+
If at the point where a template body can start there is a `:` that occurs at the end
98+
of a line, and that is followed by at least one indented statement, the recognized
99+
token is changed from ":" to ": at end of line". The latter token is one of the tokens
100+
that can start an indentation region. The Scala grammar is changed so an optional ": at end of line" is allowed in front of a template body.
101+
102+
Analogous rules apply for enum bodies, type refinements, definitions in an instance creation expressions, and local packages containing nested definitions.
103+
104+
With these new rules, the following constructs are all valid:
120105
```scala
121-
trait A
106+
trait A:
122107
def f: Int
123108

124-
class C(x: Int) extends A with
109+
class C(x: Int) extends A:
125110
def f = x
126111

127-
type T = A with
112+
object O:
113+
def f = 3
114+
115+
enum Color:
116+
case Red, Green, Blue
117+
118+
type T = A:
128119
def f: Int
129-
```
130120

131-
The syntax changes allowing this are as follows:
132-
```
133-
TemplateBody ::= [‘with’] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
134-
EnumBody ::= [‘with’] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
135-
Packaging ::= ‘package’ QualId [‘with’] ‘{’ TopStatSeq ‘}’
136-
RefinedType ::= AnnotType {[‘with’] Refinement}
137-
```
138-
It is assumed here that braces following a `with` can be transparently replaced by an
139-
indentation region.
121+
given [T] with Ord[T] as Ord[List[T]]:
122+
def compare(x: List[T], y: List[T]) = ???
140123

141-
With the new indentation rules, the previously allowed syntax
142-
```
143-
class A extends B with
144-
C
124+
extension on (xs: List[Int]):
125+
def second: Int = xs.tail.head
126+
127+
new A:
128+
def f = 3
129+
130+
package p:
131+
def a = 1
132+
package q:
133+
def b = 2
145134
```
146-
becomes illegal since `C` above would be terated as a nested statement inside `A`. More generally, a `with` that separates parent constructors cannot be at the end of a line. One has to write
135+
136+
The syntax changes allowing this are as follows:
147137
```
148-
class A extends B
149-
with C
138+
TemplateBody ::= [colonEol] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
139+
EnumBody ::= [colonEol] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
140+
Packaging ::= ‘package’ QualId [colonEol] ‘{’ TopStatSeq ‘}’
141+
RefinedType ::= AnnotType {[colonEol] Refinement}
150142
```
151-
instead (or replace the "`with`" by a "`,`"). When compiling in Scala-2 mode, a migration warning is issued for the illegal syntax and a (manual) rewrite is suggested.
143+
Here, `colonEol` stands for ": at end of line", as described above.
152144

153145
### Spaces vs Tabs
154146

docs/docs/reference/other-new-features/indentation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Optional Braces
44
---
55

66
**Note** The syntax described in this section is currently under revision.
7-
[Here is the new version which will be implemented in Dotty 0.20](./indentation-new.html).
7+
[Here is the new version which will be implemented in Dotty 0.22](./indentation-new.html).
88

99
As an experimental feature, Scala 3 treats indentation as significant and allows
1010
some occurrences of braces `{...}` to be optional.

0 commit comments

Comments
 (0)