├── .github └── workflows │ └── CI.yaml ├── .gitignore ├── .scalafmt.conf ├── README.md ├── build.sbt ├── documentation └── docs │ └── index.md ├── dotty-docs └── docs │ ├── .gitignore │ ├── _layouts │ ├── base.html │ ├── blog-page.html │ ├── doc-page.html │ ├── index.html │ ├── main.html │ └── search.html │ ├── blog │ ├── _posts │ │ ├── 2015-10-23-dotty-compiler-bootstraps.md │ │ ├── 2016-01-02-new-year-resolutions.md │ │ ├── 2016-02-03-essence-of-scala.md │ │ ├── 2016-02-17-scaling-dot-soundness.md │ │ ├── 2016-05-05-multiversal-equality.md │ │ ├── 2016-12-05-implicit-function-types.md │ │ ├── 2017-05-31-first-dotty-milestone-release.md │ │ ├── 2017-07-12-second-dotty-milestone-release.md │ │ ├── 2017-09-07-third-dotty-milestone-release.md │ │ ├── 2017-10-16-fourth-dotty-milestone-release.md │ │ ├── 2017-12-01-fifth-dotty-milestone-release.md │ │ ├── 2018-03-05-seventh-dotty-milestone-release.md │ │ ├── 2018-04-27-eighth-dotty-milestone-release.md │ │ ├── 2018-07-06-ninth-dotty-milestone-release.md │ │ ├── 2018-10-10-10th-dotty-milestone-release.md │ │ ├── 2018-11-30-11th-dotty-milestone-release.md │ │ ├── 2019-01-21-12th-dotty-milestone-release.md │ │ ├── 2019-03-05-13th-dotty-milestone-release.md │ │ ├── 2019-04-15-14th-dotty-milestone-release.md │ │ ├── 2019-05-23-15th-dotty-milestone-release.md │ │ ├── 2019-06-11-16th-dotty-milestone-release.md │ │ ├── 2019-07-25-17th-dotty-milestone-release.md │ │ ├── 2019-08-30-18th-dotty-milestone-release.md │ │ ├── 2019-09-23-19th-dotty-milestone-release.md │ │ ├── 2019-11-04-20th-dotty-milestone-release.md │ │ ├── 2019-12-20-21th-dotty-milestone-release.md │ │ ├── 2020-02-05-22nd-dotty-milestone-release.md │ │ ├── 2020-03-18-23rd-dotty-milestone-release.md │ │ ├── 2020-04-29-24th-dotty-milestone-release.md │ │ ├── 2020-06-22-25th-dotty-milestone-release.md │ │ └── 2020-07-27-26th-dotty-milestone-release.md │ └── index.html │ ├── css │ ├── bootstrap.min.css │ ├── color-brewer.css │ ├── dottydoc.css │ ├── frontpage.css │ ├── search.css │ ├── sidebar.css │ └── toolbar.css │ ├── docs │ ├── contributing │ │ ├── checklist.sh │ │ ├── contribute-knowledge.md │ │ ├── debug-tests.md │ │ ├── debugging.md │ │ ├── getting-started.md │ │ ├── procedures │ │ │ ├── release.md │ │ │ └── vulpix.md │ │ ├── scala2-vs-scala3.md │ │ ├── testing.md │ │ ├── tools │ │ │ ├── mill.md │ │ │ └── scalafix.md │ │ └── workflow.md │ ├── index.md │ ├── internals │ │ ├── backend.md │ │ ├── classpaths.md │ │ ├── contexts.md │ │ ├── core-data-structures.md │ │ ├── debug-macros.md │ │ ├── dotc-scalac.md │ │ ├── dotty-internals-1-notes.md │ │ ├── explicit-nulls.md │ │ ├── higher-kinded-v2.md │ │ ├── overall-structure.md │ │ ├── periods.md │ │ ├── syntax-3.1.md │ │ ├── syntax.md │ │ └── type-system.md │ ├── reference │ │ ├── changed-features │ │ │ ├── compiler-plugins.md │ │ │ ├── eta-expansion-spec.md │ │ │ ├── eta-expansion.md │ │ │ ├── implicit-conversions-spec.md │ │ │ ├── implicit-conversions.md │ │ │ ├── implicit-resolution.md │ │ │ ├── interpolation-escapes.md │ │ │ ├── lazy-vals-init.md │ │ │ ├── main-functions.md │ │ │ ├── match-syntax.md │ │ │ ├── numeric-literals.md │ │ │ ├── operators.md │ │ │ ├── overload-resolution.md │ │ │ ├── pattern-bindings.md │ │ │ ├── pattern-matching.md │ │ │ ├── structural-types-spec.md │ │ │ ├── structural-types.md │ │ │ ├── type-checking.md │ │ │ ├── type-inference.md │ │ │ ├── vararg-patterns.md │ │ │ └── wildcards.md │ │ ├── contextual │ │ │ ├── by-name-context-parameters.md │ │ │ ├── context-bounds.md │ │ │ ├── context-functions-spec.md │ │ │ ├── context-functions.md │ │ │ ├── conversions.md │ │ │ ├── delegates.md │ │ │ ├── derivation-macro.md │ │ │ ├── derivation.md │ │ │ ├── extension-methods.md │ │ │ ├── given-clauses.md │ │ │ ├── given-imports.md │ │ │ ├── givens.md │ │ │ ├── implicit-by-name-parameters.md │ │ │ ├── implicit-function-types-spec.md │ │ │ ├── implicit-function-types.md │ │ │ ├── import-delegate.md │ │ │ ├── import-implied.md │ │ │ ├── inferable-by-name-parameters.md │ │ │ ├── inferable-params.md │ │ │ ├── instance-defs.md │ │ │ ├── motivation.md │ │ │ ├── multiversal-equality.md │ │ │ ├── query-types-spec.md │ │ │ ├── query-types.md │ │ │ ├── relationship-implicits.md │ │ │ ├── type-classes.md │ │ │ └── using-clauses.md │ │ ├── dropped-features │ │ │ ├── auto-apply.md │ │ │ ├── class-shadowing-spec.md │ │ │ ├── class-shadowing.md │ │ │ ├── delayed-init.md │ │ │ ├── do-while.md │ │ │ ├── early-initializers.md │ │ │ ├── existential-types.md │ │ │ ├── limit22.md │ │ │ ├── macros.md │ │ │ ├── nonlocal-returns.md │ │ │ ├── package-objects.md │ │ │ ├── procedure-syntax.md │ │ │ ├── symlits.md │ │ │ ├── this-qualifier.md │ │ │ ├── type-projection.md │ │ │ ├── weak-conformance-spec.md │ │ │ ├── weak-conformance.md │ │ │ └── xml.md │ │ ├── enums │ │ │ ├── adts.md │ │ │ ├── desugarEnums.md │ │ │ └── enums.md │ │ ├── features-classification.md │ │ ├── metaprogramming │ │ │ ├── erased-terms-spec.md │ │ │ ├── erased-terms.md │ │ │ ├── inline.md │ │ │ ├── macros-spec.md │ │ │ ├── macros.md │ │ │ ├── simple-smp.md │ │ │ ├── staging.md │ │ │ ├── tasty-inspect.md │ │ │ ├── tasty-reflect.md │ │ │ └── toc.md │ │ ├── new-types │ │ │ ├── dependent-function-types-spec.md │ │ │ ├── dependent-function-types.md │ │ │ ├── implicit-function-types-spec.md │ │ │ ├── intersection-types-spec.md │ │ │ ├── intersection-types.md │ │ │ ├── match-types.md │ │ │ ├── type-lambdas-spec.md │ │ │ ├── type-lambdas.md │ │ │ ├── union-types-spec.md │ │ │ └── union-types.md │ │ ├── other-new-features │ │ │ ├── control-syntax.md │ │ │ ├── creator-applications.md │ │ │ ├── explicit-nulls.md │ │ │ ├── export.md │ │ │ ├── implicit-by-name-parameters.md │ │ │ ├── indentation.md │ │ │ ├── kind-polymorphism.md │ │ │ ├── named-typeargs-spec.md │ │ │ ├── named-typeargs.md │ │ │ ├── opaques-details.md │ │ │ ├── opaques.md │ │ │ ├── open-classes.md │ │ │ ├── parameter-untupling-spec.md │ │ │ ├── parameter-untupling.md │ │ │ ├── quoted-pattern-spec.md │ │ │ ├── safe-initialization.md │ │ │ ├── super-traits.md │ │ │ ├── threadUnsafe-annotation.md │ │ │ ├── trait-parameters.md │ │ │ └── tupled-function.md │ │ ├── overview.md │ │ └── soft-modifier.md │ ├── release-notes │ │ ├── 0.1.2.md │ │ └── syntax-changes-0.22.md │ ├── resources │ │ └── talks.md │ └── usage │ │ ├── cbt-projects.md │ │ ├── dottydoc.md │ │ ├── getting-started.md │ │ ├── ide-support.md │ │ ├── language-versions.md │ │ ├── sbt-projects.md │ │ ├── version-numbers.md │ │ ├── worksheet-mode-implementation-details.md │ │ └── worksheet-mode.md │ ├── images │ ├── aggelos.jpg │ ├── allan.jpg │ ├── anatolii.png │ ├── dotty-ide │ │ ├── decompiler.png │ │ ├── documentation-hover.png │ │ └── signature-help.png │ ├── dotty-logo-white.svg │ ├── dotty-logo.svg │ ├── explicit-nulls │ │ └── explicit-nulls-type-hierarchy.png │ ├── favicon.png │ ├── felix.jpg │ ├── fengyun.jpg │ ├── github-logo.svg │ ├── martin.jpg │ ├── nico.jpg │ ├── olivier.jpg │ ├── others │ │ └── scala-days-logo.png │ ├── petrashko.jpg │ ├── preview.png │ ├── scala-logo copy.svg │ ├── scala-logo-white.svg │ ├── scala-logo.svg │ ├── smarter.jpg │ └── worksheets │ │ ├── config-autorun.png │ │ ├── worksheet-demo.gif │ │ ├── worksheet-help.png │ │ └── worksheet-run.png │ ├── index.html │ ├── js │ ├── api-search.js │ ├── bootstrap.min.js │ ├── highlight.pack.js │ ├── jquery.min.js │ ├── sidebar.js │ └── toolbar.js │ └── sidebar.yml ├── example-project ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── project │ ├── build.properties │ └── plugins.sbt └── src │ └── main │ └── scala │ ├── AutoParamTupling.scala │ ├── ContextQueries.scala │ ├── Conversion.scala │ ├── EnumTypes.scala │ ├── ImpliedInstances.scala │ ├── IntersectionTypes.scala │ ├── Main.scala │ ├── MultiversalEquality.scala │ ├── NamedTypeArguments.scala │ ├── PatternMatching.scala │ ├── StructuralTypes.scala │ ├── TraitParams.scala │ ├── TypeLambdas.scala │ └── UnionTypes.scala ├── project ├── ExampleProject.scala ├── build.properties ├── plugins.sbt └── protoplugin.scala └── src ├── main ├── resources │ ├── META-INF │ │ └── services │ │ │ └── org.jetbrains.dokka.plugability.DokkaPlugin │ └── dotty_res │ │ ├── fonts │ │ ├── dotty-icons.ttf │ │ └── dotty-icons.woff │ │ ├── hljs │ │ ├── LICENSE │ │ └── highlight.pack.js │ │ ├── images │ │ ├── dotty-logo-white.svg │ │ └── scala_logo.svg │ │ ├── scripts │ │ ├── common │ │ │ ├── component.js │ │ │ └── utils.js │ │ ├── components │ │ │ ├── DocumentableList.js │ │ │ ├── Filter.js │ │ │ ├── FilterBar.js │ │ │ ├── FilterGroup.js │ │ │ └── Input.js │ │ ├── diagram.js │ │ ├── hljs-scala3.js │ │ └── ux.js │ │ └── styles │ │ ├── diagram.css │ │ ├── dotty-icons.css │ │ ├── filter-bar.css │ │ ├── nord-light.css │ │ ├── scalastyle.css │ │ └── search-bar.css └── scala │ ├── dotty │ ├── dokka │ │ ├── DottyDokkaConfig.scala │ │ ├── DottyDokkaPlugin.scala │ │ ├── Main.scala │ │ ├── ScalaModuleCreator.scala │ │ ├── model │ │ │ ├── api │ │ │ │ ├── api.scala │ │ │ │ └── internalExtensions.scala │ │ │ ├── extras.scala │ │ │ └── scalaModel.scala │ │ ├── preprocessors │ │ │ ├── ScalaEmbeddedResourceApppender.scala │ │ │ └── ScalaResourceInstaller.scala │ │ ├── tasty │ │ │ ├── BasicSupport.scala │ │ │ ├── ClassLikeSupport.scala │ │ │ ├── PackageSupport.scala │ │ │ ├── ScalaDocSupport.scala │ │ │ ├── SyntheticSupport.scala │ │ │ ├── TastyParser.scala │ │ │ ├── TypesSupport.scala │ │ │ └── comments │ │ │ │ ├── BaseConverter.scala │ │ │ │ ├── Cleaner.scala │ │ │ │ ├── CommentRegex.scala │ │ │ │ ├── Comments.scala │ │ │ │ ├── Emitter.scala │ │ │ │ ├── MarkdownConverter.scala │ │ │ │ ├── MarkdownParser.scala │ │ │ │ ├── MemberLookup.scala │ │ │ │ ├── Preparser.scala │ │ │ │ ├── Queries.scala │ │ │ │ ├── package.scala │ │ │ │ └── wiki │ │ │ │ ├── Converter.scala │ │ │ │ ├── Entities.scala │ │ │ │ └── Parser.scala │ │ ├── transformers │ │ │ ├── ImplicitMembersExtensionTransformer.scala │ │ │ ├── InheritanceInformationTransformer.scala │ │ │ ├── PackageHierarchyTransformer.scala │ │ │ ├── ScalaCommentToContentConverter.scala │ │ │ └── ScalaSourceLinksTransformer.scala │ │ ├── translators │ │ │ ├── FilterAttributes.scala │ │ │ ├── ScalaContentBuilder.scala │ │ │ ├── ScalaDocumentableToPageTranslator.scala │ │ │ ├── ScalaPageCreator.scala │ │ │ ├── ScalaSignatureProvider.scala │ │ │ └── ScalaSignatureUtils.scala │ │ └── utils.scala │ ├── renderers │ │ ├── DotDiagramBuilder.scala │ │ └── ScalaHtmlRenderer.scala │ └── tools │ │ └── dottydoc │ │ └── Main.scala │ ├── example │ ├── Documentation2.scala │ ├── Inheritance.scala │ └── level2 │ │ ├── Documentation.scala │ │ ├── SameLevelTypeLinking.scala │ │ └── level3 │ │ └── level4 │ │ └── ClassLevel4.scala │ └── tests │ ├── FilterTest.scala │ ├── annotations.scala │ ├── annotationsExample.scala │ ├── classModifiers.scala │ ├── classSignatureTestSource.scala │ ├── companionObjectSignatures.scala │ ├── enumSignatures.scala │ ├── extensionMethodSignatures.scala │ ├── fieldsSignatures.scala │ ├── genericMethods.scala │ ├── genericSignatures.scala │ ├── givenSignatures.scala │ ├── implicitClasslikes.scala │ ├── implicitConversions │ ├── A.scala │ ├── B.scala │ └── classesWithConversions.scala │ ├── implicitMembers.scala │ ├── markdown-tests.scala │ ├── mergedPackage1.scala │ ├── mergedPackage2.scala │ ├── mergedPackage3.scala │ ├── methodsAndConstructors.scala │ ├── modifiersSignatureTestSource.scala │ ├── nested.scala │ ├── objectSignatures.scala │ ├── opaqueTypes.scala │ ├── package.scala │ ├── packageObjectSymbolSignatures.scala │ ├── packageSymbolSignatures.scala │ ├── signatureTestSource.scala │ ├── structuralTypes.scala │ ├── tests.scala │ ├── traitSignatures.scala │ ├── typeLambdas.scala │ ├── typesSignatures.scala │ ├── visibility.scala │ └── wiki-tests.scala └── test └── scala └── dotty └── dokka ├── DottyTestRunner.scala ├── MultipleFileTest.scala ├── SignatureTests.scala ├── SingleFileTest.scala ├── TestUtils.scala └── tasty └── comments ├── CommentParserTest.scala ├── MarkdownConverterTests.scala ├── MemberLookupTests.scala └── QueryParserTests.scala /.github/workflows/CI.yaml: -------------------------------------------------------------------------------- 1 | name: CI for dotty-dokka 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 20 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: git fetch --prune --unshallow --tags 15 | 16 | - name: Cache Coursier 17 | uses: actions/cache@v1 18 | with: 19 | path: ~/.cache/coursier 20 | key: sbt-coursier-cache 21 | - name: Cache SBT 22 | uses: actions/cache@v1 23 | with: 24 | path: ~/.sbt 25 | key: sbt-${{ hashFiles('**/build.sbt') }} 26 | 27 | - name: Set up JDK 11 28 | uses: actions/setup-java@v1 29 | with: 30 | java-version: 11 31 | 32 | - name: Compile and test 33 | run: sbt compile test 34 | 35 | - name: Locally publish self 36 | run: sbt publishLocal 37 | 38 | - name: Generate test documentation 39 | run: sbt generateSelfDocumentation 40 | 41 | - name: Generate documentation for dotty library 42 | run: sbt generateDottyLibDocumentation 43 | 44 | - name: Generate documentation with SBT plugin 45 | run: sbt example-project/doc 46 | 47 | - name: Configure AWS Credentials 48 | uses: aws-actions/configure-aws-credentials@v1 49 | with: 50 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 51 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 52 | aws-region: eu-central-1 53 | 54 | - name: Publish all 55 | run: | 56 | dest=s3://scala3doc/$([ $GITHUB_REF = "master" ] && echo master || echo pr-$(echo $GITHUB_REF | cut '-d/' -f3)) 57 | aws s3 rm $dest 58 | aws s3 sync output $dest 59 | 60 | - name: Update gh-pages 61 | run: | 62 | if [ $GITHUB_REF = "refs/heads/master" ]; then 63 | git config --global user.email "$(git log -1 --format=%ae)" 64 | git config --global user.name "$(git log -1 --format=%an)" 65 | git subtree add --prefix=our-site origin gh-pages 66 | rm -r our-site/* 67 | cp -r output/self/* our-site 68 | git add our-site 69 | git commit -m "$(git log -1 --pretty=%B)" 70 | git subtree push --prefix=our-site origin gh-pages 71 | fi 72 | 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | libs/ 4 | 5 | # sbt specific 6 | .cache 7 | .history 8 | .lib/ 9 | dist/* 10 | target/ 11 | lib_managed/ 12 | src_managed/ 13 | project/boot/ 14 | project/plugins/project/ 15 | 16 | # Scala-IDE specific 17 | .scala_dependencies 18 | .worksheet 19 | .bsp 20 | 21 | # Intellij 22 | .idea 23 | 24 | #integration tests dir 25 | /test-ws 26 | 27 | # to test deploy 28 | private-* 29 | repo 30 | 31 | .metals 32 | metals.sbt 33 | .bloop 34 | .dotty-ide* 35 | 36 | # custom things 37 | output 38 | 39 | .vscode 40 | 41 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "2.6.3" 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scala3doc 2 | 3 | Scala3doc is not longer maintained here, this repository is used to track remaining issues in development phase of the tool. 4 | 5 | Code and documentation can be found [here](https://github.com/lampepfl/dotty/tree/master/scaladoc). 6 | -------------------------------------------------------------------------------- /documentation/docs/index.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /dotty-docs/docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Jekyll specific ignores 2 | vendor/ 3 | .bundle/ 4 | Gemfile.lock 5 | _site/ 6 | .sass-cache/ 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/_layouts/base.html: -------------------------------------------------------------------------------- 1 | --- 2 | extraCSS: 3 | - css/bootstrap.min.css 4 | - css/dottydoc.css 5 | - css/color-brewer.css 6 | extraJS: 7 | - js/jquery.min.js 8 | - js/highlight.pack.js 9 | - js/bootstrap.min.js 10 | --- 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{ content }} 19 | 20 | -------------------------------------------------------------------------------- /dotty-docs/docs/_layouts/blog-page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: main 3 | --- 4 |
5 |
6 |

{{ page.title }}

7 | 17 | {% if page.subTitle %} 18 |
19 | {{ page.subTitle }} 20 |
21 | {% endif %} 22 |
23 | 24 | {{ content }} 25 | 26 | {% if page.author and page.authorImg %} 27 |
28 | 34 | {% endif %} 35 |
36 | -------------------------------------------------------------------------------- /dotty-docs/docs/_layouts/doc-page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: main 3 | --- 4 |
5 |
6 |

{{ page.title }}

7 | 13 |
14 | {{ content }} 15 |
16 | -------------------------------------------------------------------------------- /dotty-docs/docs/_layouts/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: main 3 | --- 4 |

{{ content }}

5 | -------------------------------------------------------------------------------- /dotty-docs/docs/_layouts/main.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | --- 4 |
5 | {{ content }} 6 |
7 | 12 | 13 | -------------------------------------------------------------------------------- /dotty-docs/docs/blog/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: main 3 | title: Blog 4 | --- 5 |
6 |

{{ page.title }}

7 | 8 | 32 |
33 | -------------------------------------------------------------------------------- /dotty-docs/docs/css/color-brewer.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Colorbrewer theme 4 | Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock 5 | Ported by Fabrício Tavares de Oliveira 6 | 7 | */ 8 | 9 | .hljs { 10 | background: transparent; 11 | } 12 | 13 | .hljs, 14 | .hljs-subst { 15 | color: #000; 16 | } 17 | 18 | .hljs-string, 19 | .hljs-meta, 20 | .hljs-symbol, 21 | .hljs-template-tag, 22 | .hljs-template-variable, 23 | .hljs-addition { 24 | color: #756bb1; 25 | } 26 | 27 | .hljs-comment, 28 | .hljs-quote { 29 | color: #636363; 30 | } 31 | 32 | .hljs-number, 33 | .hljs-regexp, 34 | .hljs-literal, 35 | .hljs-bullet, 36 | .hljs-link { 37 | color: #31a354; 38 | } 39 | 40 | .hljs-deletion, 41 | .hljs-variable { 42 | color: #88f; 43 | } 44 | 45 | .hljs-keyword, 46 | .hljs-selector-tag, 47 | .hljs-title, 48 | .hljs-section, 49 | .hljs-built_in, 50 | .hljs-doctag, 51 | .hljs-type, 52 | .hljs-tag, 53 | .hljs-name, 54 | .hljs-selector-id, 55 | .hljs-selector-class, 56 | .hljs-strong { 57 | color: #3182bd; 58 | } 59 | 60 | .hljs-emphasis { 61 | font-style: italic; 62 | } 63 | 64 | .hljs-attribute { 65 | color: #e6550d; 66 | } 67 | -------------------------------------------------------------------------------- /dotty-docs/docs/css/search.css: -------------------------------------------------------------------------------- 1 | ul { 2 | list-style: none; 3 | padding: 0; 4 | } 5 | 6 | ul li { 7 | margin-bottom: 5px; 8 | font-family: var(--font-family-sans-serif); 9 | } 10 | 11 | h3 { 12 | padding-top: .5rem; 13 | } 14 | h4 { 15 | display: inline-block; 16 | font-size: 1.25rem; 17 | } 18 | 19 | .package-name a { 20 | color: inherit; 21 | } 22 | 23 | .entity-kinds { 24 | display: inline; 25 | } 26 | 27 | .member-result { 28 | padding-left: 1em; 29 | font-family: var(--font-family-monospace); 30 | } 31 | 32 | @media(min-width: 768px) { 33 | .tab-content > .tab-pane { 34 | display: block; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dotty-docs/docs/css/toolbar.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 50px; 3 | } 4 | 5 | nav.navbar { 6 | height: 50px; 7 | line-height: 1; 8 | font-size: 24px; 9 | font-family: var(--font-family-toolbar-details); 10 | background-color: var(--toolbar); 11 | box-shadow: 0 0 6px; 12 | } 13 | nav.navbar-dark * { 14 | color: var(--toolbar-entry); 15 | transition: color .2s ease-out; 16 | } 17 | 18 | nav.navbar-dark a:hover *, nav.navbar-dark a:focus * { 19 | color: var(--toolbar-active); 20 | } 21 | nav.navbar a:hover { 22 | text-decoration: none; 23 | } 24 | nav.navbar a { 25 | cursor: pointer; 26 | } 27 | 28 | .navbar-brand { 29 | margin-right: auto; 30 | margin-left: auto; 31 | font-size: inherit; 32 | display: flex; 33 | align-items: center; 34 | } 35 | 36 | .navbar-brand .project-logo { 37 | display: none; 38 | height: 40px; 39 | margin-right: 7px; 40 | } 41 | 42 | .navbar-brand .project-details * { 43 | margin: 0; 44 | line-height: inherit; 45 | } 46 | .navbar-brand .project-details h1 { 47 | font-size: 1em; 48 | font-family: var(--font-family-toolbar-main); 49 | font-weight: var(--font-weight-toolbar-main); 50 | } 51 | .navbar-brand .project-details h2 { 52 | font-size: 0.5em; 53 | margin-top: 2px; 54 | font-weight: var(--font-weight-toolbar-details); 55 | } 56 | 57 | #search-api-input { 58 | color: initial; 59 | width: 10em; 60 | } 61 | #searchbar { 62 | display: none; 63 | } 64 | #searchbar.shown { 65 | display: initial; 66 | margin-left: auto; 67 | margin-right: auto; 68 | } 69 | #searchbar.shown + .navbar-brand { 70 | display: none; 71 | } 72 | 73 | #search-icon { 74 | margin-left: .5em; 75 | } 76 | 77 | @media (min-width: 420px) { 78 | .navbar-brand .project-logo { 79 | display: inline; 80 | } 81 | } 82 | 83 | @media (min-width: 768px) { 84 | #search-icon, #searchbar.shown { 85 | margin-left: 1em; 86 | margin-right: initial; 87 | } 88 | #searchbar.shown + .navbar-brand { 89 | display: flex; 90 | } 91 | } 92 | 93 | @media (min-width: 1200px) { 94 | #searchbar.shown { 95 | position: absolute; 96 | margin-left: 4em; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/contribute-knowledge.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Contributing Knowledge 4 | --- 5 | 6 | # Contribute Internals-related Knowledge 7 | If you know anything useful at all about Dotty, feel free to log this knowledge: 8 | 9 | - [📜Log the Knowledge](https://github.com/lampepfl/dotty-knowledge/issues/new) 10 | - [🎓More about Logging the Knowledge](https://github.com/lampepfl/dotty-knowledge/blob/master/README.md) 11 | 12 | In short, no need to make it pretty, particularly human-readable or give it a particular structure. Just dump the knowledge you have and we'll take it from there. -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Getting Started 4 | --- 5 | 6 | 7 | 8 | Requirements 9 | ------------ 10 | Make sure that you are using macOS or Linux (or WSL on Windows) with Java 8 or newer. You can determine which version of the JDK is the 11 | default by typing `java -version` in a Terminal window. 12 | 13 | Compiling and Running 14 | --------------------- 15 | Start by cloning the repository: 16 | 17 | ```bash 18 | $ git clone https://github.com/lampepfl/dotty.git 19 | $ cd dotty 20 | $ sbt managedSources # Needed for IDE import to succeed 21 | ``` 22 | 23 | Dotty provides a standard sbt build: compiling, running and starting a repl can 24 | all be done from within sbt: 25 | 26 | ```bash 27 | $ sbt 28 | > dotc tests/pos/HelloWorld.scala 29 | > dotr HelloWorld 30 | hello world 31 | ``` 32 | 33 | There are also bash scripts that can be used in the same way. Assuming that you have cloned the Dotty repo locally, append 34 | the following line on your `.bash_profile`: 35 | 36 | ```shell 37 | $ export PATH=$HOME/dotty/bin:$PATH 38 | ``` 39 | 40 | and you will be able to run the corresponding commands directly from your console: 41 | 42 | ```shell 43 | # Compile code using Dotty 44 | $ dotc tests/pos/HelloWorld.scala 45 | 46 | # Run it with the proper classpath 47 | $ dotr HelloWorld 48 | ``` 49 | 50 | 51 | Starting a REPL 52 | --------------- 53 | ```bash 54 | $ sbt 55 | > repl 56 | Welcome to Scala.next (pre-alpha) (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101). 57 | Type in expressions to have them evaluated. 58 | Type :help for more information. 59 | scala> 60 | ``` 61 | 62 | or via bash: 63 | 64 | ```bash 65 | $ dotr 66 | ``` 67 | 68 | 69 | Generating Documentation 70 | ------------------------- 71 | To generate this page and other static page docs, run 72 | ```bash 73 | $ sbt 74 | > genDocs 75 | ``` 76 | 77 | Before contributing to Dotty, we invite you to consult the 78 | [Dotty Developer Guidelines](https://github.com/lampepfl/dotty/blob/master/CONTRIBUTING.md). 79 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/procedures/vulpix.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Test Vulpix Framework 4 | --- 5 | 6 | # Test Vulpix Framework 7 | If you are modifying the Vulpix framework and need a playground with dummy tests to try out your modifications, do the following. 8 | 9 | Create the directory structure for the playground: 10 | 11 | ```bash 12 | mkdir -pv tests/playground/run tests/playground/neg 13 | echo "stuff" > tests/playground/neg/Sample.scala 14 | echo 'object Test { def main(args: Array[String]): Unit = {println("Hi")} }' > tests/playground/run/Sample.scala 15 | ``` 16 | 17 | In `CompilationTests.scala`: 18 | 19 | ```scala 20 | @Test def exampleNeg: Unit = { 21 | implicit val testGroup: TestGroup = TestGroup("exampleNeg") 22 | compileFilesInDir("tests/playground/neg", defaultOptions).checkExpectedErrors() 23 | } 24 | 25 | @Test def exampleRun: Unit = { 26 | implicit val testGroup: TestGroup = TestGroup("exampleRun") 27 | compileFilesInDir("tests/playground/run", defaultOptions).checkRuns() 28 | } 29 | ``` 30 | 31 | SBT: 32 | 33 | ```scala 34 | testOnly dotty.tools.dotc.CompilationTests -- *example* 35 | ``` 36 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/scala2-vs-scala3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Divergences between Scala 2 and Dotty 4 | --- 5 | 6 | # Divergences between Scala 2 and Dotty 7 | The following issues encountered when compiling Scala 2 code as-is under Dotty: 8 | 9 | ## Scalafix candidates 10 | - If a method is defined `toSet()`, it cannot be called `toSet`. 11 | - “result type of implicit definition needs to be given explicitly” 12 | - There are no `'Symbol`s in Scala 3, you must construct symbols via `new Symbol("foo")` instead of old `'foo` 13 | 14 | ## Trivial 15 | - Scala 2.13 libraries cannot be used from Dotty because the dotty-library is compiled against the 2.12 standard library which is not binary-compatible with the 2.13 one. We can't be compatible with both at the same time. 16 | - To use Scala 2.12 dependencies from SBT with Dotty, use `withDottyCompat` as documented [here](https://github.com/lampepfl/dotty-example-project#getting-your-project-to-compile-with-dotty). 17 | - Feature warnings about implicits `scala.language.implicitConversions` are output by default, unlike in Scala 2. This creates noise. Unclear how to turn off. 18 | 19 | Implicit conversions must be applied explicitly: 20 | 21 | ```scala 22 | implicit def IterablePath[T](s: Iterable[T])(implicit conv: T => RelPath): RelPath = { 23 | s.foldLeft(rel){_ / conv(_)} 24 | } 25 | ``` 26 | 27 | Stronger compile time guarantees on variance. Scala 2 does not assert variance on default parameters to parameters of the function value type. E.g. in geny: 28 | 29 | ```scala 30 | # Dotty 31 | def count(f: A => Boolean = (a: A) => true): Int = 32 | | ^^^^^^^^^^^^^^ 33 | |covariant type A occurs in contravariant position in type => A => Boolean of method count$default$1 34 | ``` 35 | 36 | Fix: 37 | ```scala 38 | # Dotty 39 | def count[B >: A](f: B => Boolean = (_: B) => true): Int = 40 | ``` 41 | 42 | ## Tricky 43 | - Scala 3 macros are completely different from Scala 2 ones, requires a migration strategy of its own 44 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/tools/mill.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Basic Operations with Mill 4 | --- 5 | 6 | Here's an example of how to test a project that uses mill: 7 | 8 | ```bash 9 | mill utest.jvm[2.12.8].test 10 | ``` 11 | 12 | - `utest.jvm` - the name of the compiled module (obtain from `build.sc`) 13 | - `2.12.8` – Scala cross-compile version 14 | - `test` – task to run on the module specified with the specified Scala version 15 | 16 | To get mill of the most recent version, first, find it in https://github.com/lihaoyi/mill/releases (e.g. `0.4.2-1-020e28`). Copy the download link and substitute it in the following command instead of `https://github.com/lihaoyi/mill/releases/download/0.4.1/0.4.1`: 17 | 18 | ```bash 19 | # From http://www.lihaoyi.com/mill/ 20 | sudo sh -c '(echo "#!/usr/bin/env sh" && curl -L https://github.com/lihaoyi/mill/releases/download/0.4.1/0.4.1) > /usr/local/bin/mill && chmod +x /usr/local/bin/mill' 21 | ``` 22 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/contributing/tools/scalafix.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Working with Scalafix 4 | --- 5 | 6 | # Working with Scalafix 7 | 8 | First, create a new rule as follows (command from https://scalacenter.github.io/scalafix/docs/developers/setup.html): 9 | 10 | ```bash 11 | sbt new scalacenter/scalafix.g8 --repo="Repository Name" 12 | ``` 13 | 14 | To run the rule against some codebase: 15 | 16 | ```bash 17 | scalafix -r file:scalafix/rules/src/main/scala/fix/YourRule.scala your/code/base/ 18 | ``` 19 | 20 | Where `YourRule.scala` is the rule you developed and `your/code/base` is the code base you are running the rule against. 21 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Dotty Documentation" 4 | --- 5 | 6 | Dotty is the project name for technologies that are considered for inclusion in Scala 3. Scala has 7 | pioneered the fusion of object-oriented and functional programming in a typed setting. Scala 3 will 8 | be a big step towards realizing the full potential of these ideas. Its main objectives are to 9 | 10 | - become more opinionated by promoting programming idioms we found to work well, 11 | - simplify where possible, 12 | - eliminate inconsistencies and surprising behaviors, 13 | - build on strong foundations to ensure the design hangs well together, 14 | - consolidate language constructs to improve the language’s consistency, safety, ergonomics, and performance. 15 | 16 | In this documentation you will find information on how to use the Dotty compiler on your machine, 17 | navigate through the code, setup Dotty with your favorite IDE and more! 18 | 19 | Table of Contents 20 | ================= 21 | {% assign titles = sidebar.titles %} 22 | {% include "table-of-contents" %} 23 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/internals/contexts.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Contexts 4 | --- 5 | 6 | The `Context` contains the state of the compiler, for example 7 | 8 | * `settings` 9 | * `freshNames` (`FreshNameCreator`) 10 | * `period` (run and phase id) 11 | * `compilationUnit` 12 | * `phase` 13 | * `tree` (current tree) 14 | * `typer` (current typer) 15 | * `mode` (type checking mode) 16 | * `typerState` (for example undetermined type variables) 17 | * ... 18 | 19 | ### Contexts in the typer ### 20 | The type checker passes contexts through all methods and adapts fields where 21 | necessary, e.g. 22 | 23 | ```scala 24 | case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.withNewScope) 25 | ``` 26 | 27 | A number of fields in the context are typer-specific (`mode`, `typerState`). 28 | 29 | ### In other phases ### 30 | Other phases need a context for many things, for example to access the 31 | denotation of a symbols (depends on the period). However they typically don't 32 | need to modify / extend the context while traversing the AST. For these phases 33 | the context can be simply an implicit class parameter that is then available in 34 | all members. 35 | 36 | **Careful**: beware of memory leaks. Don't hold on to contexts in long lived 37 | objects. 38 | 39 | ### Using contexts ### 40 | Nested contexts should be named `ctx` to enable implicit shadowing: 41 | 42 | ```scala 43 | scala> class A 44 | 45 | scala> def foo(implicit a: A) { def bar(implicit b: A) { println(implicitly[A]) } } 46 | :8: error: ambiguous implicit values: 47 | both value a of type A 48 | and value b of type A 49 | match expected type A 50 | def foo(implicit a: A) { def bar(implicit b: A) { println(implicitly[A]) } } 51 | 52 | scala> def foo(implicit a: A) { def bar(implicit a: A) { println(implicitly[A]) } } 53 | foo: (implicit a: A)Unit 54 | ``` 55 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/eta-expansion.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Automatic Eta Expansion" 4 | --- 5 | 6 | The conversion of _methods_ into _functions_ has been improved and happens automatically for methods with one or more parameters. 7 | 8 | ```scala 9 | def m(x: Boolean, y: String)(z: Int): List[Int] 10 | val f1 = m 11 | val f2 = m(true, "abc") 12 | ``` 13 | 14 | This creates two function values: 15 | ```scala 16 | f1: (Boolean, String) => Int => List[Int] 17 | f2: Int => List[Int] 18 | ``` 19 | 20 | The syntax `m _` is no longer needed and will be deprecated in the future. 21 | 22 | ## Automatic eta-expansion and nullary methods 23 | 24 | Automatic eta expansion does not apply to "nullary" methods that take an empty parameter list. 25 | 26 | ```scala 27 | def next(): T 28 | ``` 29 | 30 | Given a simple reference to `next` does not auto-convert to a function. 31 | One has to write explicitly `() => next()` to achieve that 32 | Once again since the `_` is going to be deprecated it's better to write it this way 33 | rather than `next _`. 34 | 35 | The reason for excluding nullary methods from automatic eta expansion 36 | is that Scala implicitly inserts the `()` argument, which would 37 | conflict with eta expansion. Automatic `()` insertion is 38 | [limited](../dropped-features/auto-apply.md) in Dotty, but the fundamental ambiguity 39 | remains. 40 | 41 | [More details](eta-expansion-spec.md) 42 | 43 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/implicit-conversions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Implicit Conversions" 4 | --- 5 | 6 | An _implicit conversion_, also called _view_, is a conversion that 7 | is applied by the compiler in several situations: 8 | 9 | 1. When an expression `e` of type `T` is encountered, but the compiler 10 | needs an expression of type `S`. 11 | 1. When an expression `e.m` where `e` has type `T` but `T` defines no 12 | member `m` is encountered. 13 | 14 | In those cases, the compiler looks in the implicit scope for a 15 | conversion that can convert an expression of type `T` to an expression 16 | of type `S` (or to a type that defines a member `m` in the second 17 | case). 18 | 19 | This conversion can be either: 20 | 21 | 1. An `implicit def` of type `T => S` or `(=> T) => S` 22 | 1. An implicit value of type `scala.Conversion[T, S]` 23 | 24 | Defining an implicit conversion will emit a warning unless the import 25 | `scala.language.implicitConversions` is in scope, or the flag 26 | `-language:implicitConversions` is given to the compiler. 27 | 28 | ## Examples 29 | 30 | The first example is taken from `scala.Predef`. Thanks to this 31 | implicit conversion, it is possible to pass a `scala.Int` to a Java 32 | method that expects a `java.lang.Integer` 33 | 34 | ```scala 35 | import scala.language.implicitConversions 36 | implicit def int2Integer(x: Int): java.lang.Integer = 37 | x.asInstanceOf[java.lang.Integer] 38 | ``` 39 | 40 | The second example shows how to use `Conversion` to define an 41 | `Ordering` for an arbitrary type, given existing `Ordering`s for other 42 | types: 43 | 44 | ```scala 45 | import scala.language.implicitConversions 46 | implicit def ordT[T, S]( 47 | implicit conv: Conversion[T, S], 48 | ordS: Ordering[S] 49 | ): Ordering[T] = { 50 | // `ordS` compares values of type `S`, but we can convert from `T` to `S` 51 | (x: T, y: T) => ordS.compare(x, y) 52 | } 53 | 54 | class A(val x: Int) // The type for which we want an `Ordering` 55 | 56 | // Convert `A` to a type for which an `Ordering` is available: 57 | implicit val AToInt: Conversion[A, Int] = _.x 58 | 59 | implicitly[Ordering[Int]] // Ok, exists in the standard library 60 | implicitly[Ordering[A]] // Ok, will use the implicit conversion from 61 | // `A` to `Int` and the `Ordering` for `Int`. 62 | ``` 63 | 64 | [More details](implicit-conversions-spec.md) 65 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/interpolation-escapes.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Escapes in interpolations 4 | --- 5 | 6 | In Scala 2 there was no straightforward way to represent a single quote character `"` in a single quoted interpolation. A \ character can't be used for that because interpolators themselves decide how to handle escaping, so the parser doesn't know whether the " should be escaped or used as a terminator. 7 | 8 | In Dotty, you can use the `$` meta character of interpolations to escape a `"` character. 9 | 10 | ```scala 11 | val inventor = "Thomas Edison" 12 | val interpolation = s"as $inventor said: $"The three great essentials to achieve anything worth while are: Hard work, Stick-to-itiveness, and Common sense.$"" 13 | ``` 14 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/lazy-vals-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Lazy Vals initialization 4 | --- 5 | 6 | Dotty implements [Version 6](https://docs.scala-lang.org/sips/improved-lazy-val-initialization.html#version-6---no-synchronization-on-this-and-concurrent-initialization-of-fields) 7 | of the [SIP-20] improved lazy vals initialization proposal. 8 | 9 | ## Motivation 10 | 11 | The newly proposed lazy val initialization mechanism aims to eliminate the acquisition of resources 12 | during the execution of the lazy val initializer block, thus reducing the possibility of a deadlock. 13 | The concrete deadlock scenarios that the new lazy val initialization scheme eliminates are 14 | summarized in the [SIP-20] document. 15 | 16 | ## Implementation 17 | 18 | Given a lazy field of the form: 19 | 20 | ```scala 21 | class Foo { 22 | lazy val bar = 23 | } 24 | ``` 25 | 26 | The Dotty compiler will generate code equivalent to: 27 | 28 | ```scala 29 | class Foo { 30 | import dotty.runtime.LazyVals 31 | var value_0: Int = _ 32 | var bitmap: Long = 0L 33 | val bitmap_offset: Long = LazyVals.getOffset(classOf[LazyCell], "bitmap") 34 | 35 | def bar(): Int = { 36 | while (true) { 37 | val flag = LazyVals.get(this, bitmap_offset) 38 | val state = LazyVals.STATE(flag, ) 39 | 40 | if (state == ) { 41 | return value_0 42 | } else if (state == ) { 43 | if (LazyVals.CAS(this, bitmap_offset, flag, , )) { 44 | try { 45 | val result = 46 | value_0 = result 47 | LazyVals.setFlag(this, bitmap_offset, , ) 48 | return result 49 | } 50 | catch { 51 | case ex => 52 | LazyVals.setFlag(this, bitmap_offset, , ) 53 | throw ex 54 | } 55 | } 56 | } else /* if (state == || state == ) */ { 57 | LazyVals.wait4Notification(this, bitmap_offset, flag, ) 58 | } 59 | } 60 | } 61 | } 62 | ``` 63 | 64 | The state of the lazy val `` is represented with 4 values: 0, 1, 2 and 3. The state 0 65 | represents a non-initialized lazy val. The state 1 represents a lazy val that is currently being 66 | initialized by some thread. The state 2 denotes that there are concurrent readers of the lazy val. 67 | The state 3 represents a lazy val that has been initialized. `` is the id of the lazy 68 | val. This id grows with the number of volatile lazy vals defined in the class. 69 | 70 | ## Note on recursive lazy vals 71 | 72 | Ideally recursive lazy vals should be flagged as an error. The current behavior for 73 | recursive lazy vals is undefined (initialization may result in a deadlock). 74 | 75 | ## Reference 76 | 77 | * [SIP-20] 78 | 79 | [SIP-20]: https://docs.scala-lang.org/sips/improved-lazy-val-initialization.html 80 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/match-syntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Match Expressions 4 | --- 5 | 6 | The syntactical precedence of match expressions has been changed. 7 | `match` is still a keyword, but it is used like an alphabetical operator. This has several consequences: 8 | 9 | 1. `match` expressions can be chained: 10 | 11 | ```scala 12 | xs match { 13 | case Nil => "empty" 14 | case x :: xs1 => "nonempty" 15 | } match { 16 | case "empty" => 0 17 | case "nonempty" => 1 18 | } 19 | 20 | 2. `match` may follow a period: 21 | 22 | ```scala 23 | if xs.match { 24 | case Nil => false 25 | case _ => true 26 | } 27 | then "nonempty" 28 | else "empty" 29 | 30 | 3. The scrutinee of a match expression must be an `InfixExpr`. Previously the scrutinee could be followed by a type ascription `: T`, but this is no longer supported. So `x : T match { ... }` now has to be 31 | written `(x: T) match { ... }`. 32 | 33 | ## Syntax 34 | 35 | The new syntax of match expressions is as follows. 36 | ``` 37 | InfixExpr ::= ... 38 | | InfixExpr MatchClause 39 | SimpleExpr ::= ... 40 | | SimpleExpr ‘.’ MatchClause 41 | MatchClause ::= ‘match’ ‘{’ CaseClauses ‘}’ 42 | ``` 43 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/type-checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Changes in Type Checking" 4 | --- 5 | 6 | [//]: # todo: fill in 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/type-inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Changes in Type Inference" 4 | --- 5 | 6 | [//]: # todo: fill in 7 | 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/vararg-patterns.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Vararg Patterns" 4 | --- 5 | 6 | The syntax of vararg patterns has changed. In the new syntax one writes varargs in patterns exactly 7 | like one writes them in expressions, using a `: _*` type annotation: 8 | 9 | ```scala 10 | xs match { 11 | case List(1, 2, xs: _*) => println(xs) // binds xs 12 | case List(1, _ : _*) => // wildcard pattern 13 | } 14 | ``` 15 | 16 | The old syntax, which is shorter but less regular, is no longer supported. 17 | 18 | ```scala 19 | /*!*/ case List(1, 2, xs @ _*) // syntax error 20 | /*!*/ case List(1, 2, _*) => ... // syntax error 21 | ``` 22 | 23 | The change to the grammar is: 24 | 25 | ```diff 26 | SimplePattern ::= ‘_’ 27 | | varid 28 | | Literal 29 | | StableId 30 | | StableId ‘(’ [Patterns ‘)’ 31 | - | StableId ‘(’ [Patterns ‘,’] [varid ‘@’] ‘_’ ‘*’ ‘)’ 32 | + | StableId ‘(’ [Patterns ‘,’] (varid | ‘_’) ‘:’ ‘_’ ‘*’ ‘)’ 33 | | ‘(’ [Patterns] ‘)’ 34 | | XmlPattern 35 | ``` 36 | 37 | ## Compatibility considerations 38 | 39 | To enable smooth cross compilation between Scala 2 and Scala 3, Dotty will 40 | accept both the old and the new syntax. Under the `-strict` setting, an error 41 | will be emitted when the old syntax is encountered. They will be enabled by 42 | default in version 3.1 of the language. 43 | 44 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/changed-features/wildcards.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Wildcard Arguments in Types 4 | --- 5 | 6 | The syntax of wildcard arguments in types has changed from `_` to `?`. Example: 7 | ```scala 8 | List[?] 9 | Map[? <: AnyRef, ? >: Null] 10 | ``` 11 | 12 | ### Motivation 13 | 14 | We would like to use the underscore syntax `_` to stand for an anonymous type parameter, aligning it with its meaning in 15 | value parameter lists. So, just as `f(_)` is a shorthand for the lambda `x => f(x)`, in the future `C[_]` will be a shorthand 16 | for the type lambda `[X] =>> C[X]`. This makes higher-kinded types easier to use. It also removes the wart that, used as a type 17 | parameter, `F[_]` means `F` is a type constructor whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. 18 | In the future, `F[_]` will mean the same thing, no matter where it is used. 19 | 20 | We pick `?` as a replacement syntax for wildcard types, since it aligns with Java's syntax. 21 | 22 | ### Migration Strategy 23 | 24 | The migration to the new scheme is complicated, in particular since the [kind projector](https://github.com/typelevel/kind-projector) 25 | compiler plugin still uses the reverse convention, with `?` meaning parameter placeholder instead of wildcard. Fortunately, kind projector has added `*` as an alternative syntax for `?`. 26 | 27 | A step-by-step migration is made possible with the following measures: 28 | 29 | 1. In Scala 3.0, both `_` and `?` are legal names for wildcards. 30 | 2. In Scala 3.1, `_` is deprecated in favor of `?` as a name for a wildcard. A `-rewrite` option is 31 | available to rewrite one to the other. 32 | 3. In Scala 3.2, the meaning of `_` changes from wildcard to placeholder for type parameter. 33 | 4. The Scala 3.1 behavior is already available today under the `-strict` setting. 34 | 35 | To smooth the transition for codebases that use kind-projector, we adopt the following measures under the command line 36 | option `-Ykind-projector`: 37 | 38 | 1. In Scala 3.0, `*` is available as a type parameter placeholder. 39 | 2. In Scala 3.2, `*` is deprecated in favor of `_`. A `-rewrite` option is 40 | available to rewrite one to the other. 41 | 3. In Scala 3.3, `*` is removed again, and all type parameter placeholders will be expressed with `_`. 42 | 43 | These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using option `-Ykind-projector`. 44 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/by-name-context-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "By-Name Context Parameters" 4 | --- 5 | 6 | Context parameters can be declared by-name to avoid a divergent inferred expansion. Example: 7 | 8 | ```scala 9 | trait Codec[T] { 10 | def write(x: T): Unit 11 | } 12 | 13 | given intCodec as Codec[Int] = ??? 14 | 15 | given optionCodec[T](using ev: => Codec[T]) as Codec[Option[T]] { 16 | def write(xo: Option[T]) = xo match { 17 | case Some(x) => ev.write(x) 18 | case None => 19 | } 20 | } 21 | 22 | val s = summon[Codec[Option[Int]]] 23 | 24 | s.write(Some(33)) 25 | s.write(None) 26 | ``` 27 | As is the case for a normal by-name parameter, the argument for the context parameter `ev` 28 | is evaluated on demand. In the example above, if the option value `x` is `None`, it is 29 | not evaluated at all. 30 | 31 | The synthesized argument for a context parameter is backed by a local val 32 | if this is necessary to prevent an otherwise diverging expansion. 33 | 34 | The precise steps for synthesizing an argument for a by-name context parameter of type `=> T` are as follows. 35 | 36 | 1. Create a new given of type `T`: 37 | 38 | ```scala 39 | given lv as T = ??? 40 | ``` 41 | where `lv` is an arbitrary fresh name. 42 | 43 | 1. This given is not immediately available as candidate for argument inference (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an argument to a by-name context parameter. 44 | 45 | 1. If this search succeeds with expression `E`, and `E` contains references to `lv`, replace `E` by 46 | 47 | 48 | ```scala 49 | { given lv as T = E; lv } 50 | ``` 51 | 52 | Otherwise, return `E` unchanged. 53 | 54 | In the example above, the definition of `s` would be expanded as follows. 55 | 56 | ```scala 57 | val s = summon[Test.Codec[Option[Int]]]( 58 | optionCodec[Int](using intCodec) 59 | ) 60 | ``` 61 | 62 | No local given instance was generated because the synthesized argument is not recursive. 63 | 64 | ### Reference 65 | 66 | For more info, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) 67 | and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). 68 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/context-bounds.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Context Bounds" 4 | --- 5 | 6 | A context bound is a shorthand for expressing the common pattern of a context parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this: 7 | 8 | ```scala 9 | def maximum[T: Ord](xs: List[T]): T = xs.reduceLeft(max) 10 | ``` 11 | 12 | A bound like `: Ord` on a type parameter `T` of a method or class indicates a context parameter `with Ord[T]`. The context parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g., 13 | 14 | ```scala 15 | def f[T: C1 : C2, U: C3](x: T)(using y: U, z: V): R 16 | ``` 17 | 18 | would expand to 19 | 20 | ```scala 21 | def f[T, U](x: T)(using y: U, z: V)(using C1[T], C2[T], C3[U]): R 22 | ``` 23 | 24 | Context bounds can be combined with subtype bounds. If both are present, subtype bounds come first, e.g. 25 | 26 | ```scala 27 | def g[T <: B : C](x: T): R = ... 28 | ``` 29 | 30 | ## Migration 31 | 32 | To ease migration, context bounds in Dotty map in Scala 3.0 to old-style implicit parameters 33 | for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. 34 | 35 | If the source version is `3.1` and the `-migration` command-line option is set, any pairing of an evidence 36 | context parameter stemming from a context bound with a normal argument will give a migration 37 | warning. The warning indicates that a `(using ...)` clause is needed instead. The rewrite can be 38 | done automatically under `-rewrite`. 39 | 40 | ## Syntax 41 | 42 | ``` 43 | TypeParamBounds ::= [SubtypeBounds] {ContextBound} 44 | ContextBound ::= ‘:’ Type 45 | ``` 46 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/delegates.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Given Instances" 4 | --- 5 | 6 | The contents of this page have [moved](./givens.md). 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/given-clauses.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Given Parameters" 4 | --- 5 | 6 | The contents of this page have [moved](./using-clauses.md). 7 | 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/implicit-by-name-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Implicit By-Name Parameters" 4 | --- 5 | 6 | The contents of this page have [moved](./by-name-context-parameters.md). 7 | 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/implicit-function-types-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Implicit Function Types - More Details" 4 | --- 5 | 6 | The contents of this page have [moved](./context-functions-spec.md). 7 | 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/implicit-function-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Implicit Function Types" 4 | --- 5 | 6 | The contents of this page have [moved](./context-functions.md). 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/import-delegate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Import Given" 4 | --- 5 | 6 | The contents of this page have [moved](./given-imports.md). 7 | 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/import-implied.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./given-imports.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/inferable-by-name-parameters.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./by-name-context-parameters.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/inferable-params.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./using-clauses.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/instance-defs.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./givens.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/query-types-spec.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./context-functions-spec.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/contextual/query-types.md: -------------------------------------------------------------------------------- 1 | The contents of this page have [moved](./context-functions.md). 2 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/class-shadowing-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Dropped: Class Shadowing - More Details" 4 | --- 5 | 6 | Spec diff: in section [5.1.4 Overriding](https://www.scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html), add *M' must not be a class*. 7 | 8 | > Why do we want to make this change to the language? 9 | 10 | Class shadowing is irregular compared to other types of overrides. Indeed, inner classes are not actually overriden but simply shadowed. 11 | 12 | 13 | > How much existing code is going to be affected? 14 | 15 | From all the code compiled so far with Dotty the only instance of this I could find is in the stdlib. Looking at [this commit](https://github.com/lampepfl/scala/commit/68f13bf39979b631ed211ec1751934306ceb5d6c#diff-7aa508b70e055b47c823764e3e5646b8) it seems like the usage of class shadowing was accidental. 16 | 17 | 18 | > How exactly is existing code going to be affected? 19 | 20 | Code that relies on overridden inner classes will stop compiling. 21 | 22 | 23 | > Is this change going to be migratable automatically? 24 | 25 | No. 26 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/class-shadowing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Class Shadowing 4 | --- 5 | 6 | Scala so far allowed patterns like this: 7 | ```scala 8 | class Base { 9 | class Ops { ... } 10 | } 11 | 12 | class Sub extends Base { 13 | class Ops { ... } 14 | } 15 | ``` 16 | Dotty rejects this with the error message: 17 | ```scala 18 | 6 | class Ops { } 19 | | ^ 20 | |class Ops cannot have the same name as class Ops in class Base -- class definitions cannot be overridden 21 | ``` 22 | The issue is that the two `Ops` classes _look_ like one overrides the 23 | other, but classes in Scala cannot be overridden. To keep things clean 24 | (and its internal operations consistent) the Dotty compiler forces you 25 | to rename the inner classes so that their names are different. 26 | 27 | [More details](./class-shadowing-spec.md) 28 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/delayed-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Delayedinit 4 | --- 5 | 6 | The special handling of the `DelayedInit` trait is no longer 7 | supported. 8 | 9 | One consequence is that the `App` class, which used `DelayedInit` is 10 | now partially broken. You can still use `App` for an easy and concise 11 | way to set up a main program. Example: 12 | ```scala 13 | object HelloWorld extends App { 14 | println("Hello, world!") 15 | } 16 | ``` 17 | However, the code is now run in the initializer of the object, which on 18 | some JVM's means that it will only be interpreted. So, better not use it 19 | for benchmarking! Also, if you want to access the command line arguments, 20 | you need to use an explicit `main` method for that. 21 | ```scala 22 | object Hello { 23 | def main(args: Array[String]) = 24 | println(s"Hello, ${args(0)}") 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/do-while.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Do-While 4 | --- 5 | 6 | The syntax construct 7 | ```scala 8 | do while 9 | ``` 10 | is no longer supported. Instead, it is recommended to use the equivalent `while` loop 11 | below: 12 | ```scala 13 | while ({ ; }) () 14 | ``` 15 | For instance, instead of 16 | ```scala 17 | do 18 | i += 1 19 | while (f(i) == 0) 20 | ``` 21 | one writes 22 | ```scala 23 | while ({ 24 | i += 1 25 | f(i) == 0 26 | }) () 27 | ``` 28 | Under the [new syntax rules](../other-new-features/control-syntax), this code can be written also without the awkward `({...})` bracketing like this: 29 | ```scala 30 | while { 31 | i += 1 32 | f(i) == 0 33 | } do () 34 | ``` 35 | The idea to use a block as the condition of a while also gives a solution 36 | to the "loop-and-a-half" problem. For instance: 37 | ```scala 38 | while { 39 | val x: Int = iterator.next 40 | x >= 0 41 | } do print(".") 42 | ``` 43 | 44 | ### Why Drop The Construct? 45 | 46 | - `do-while` is used relatively rarely and it can expressed faithfully using just while. So there seems to be little point in having it as a separate syntax construct. 47 | - Under the [new syntax rules](../other-new-features/control-syntax) `do` is used 48 | as a statement continuation, which would clash with its meaning as a statement 49 | introduction. 50 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/early-initializers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Early Initializers 4 | --- 5 | 6 | Early initializers of the form 7 | ```scala 8 | class C extends { ... } with SuperClass ... 9 | ``` 10 | have been dropped. They were rarely used, and mostly to compensate for the lack of 11 | [trait parameters](../other-new-features/trait-parameters.md), which are now directly supported in Dotty. 12 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/existential-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Existential Types 4 | --- 5 | 6 | Existential types using `forSome` have been dropped. The reasons for dropping them were: 7 | 8 | - Existential types violate a type soundness principle on which DOT 9 | and Dotty are constructed. That principle says that every 10 | prefix (`p`, respectvely `S`) of a type selection `p.T` or `S#T` 11 | must either come from a value constructed at runtime or refer to a 12 | type that is known to have only good bounds. 13 | 14 | - Existential types create many difficult feature interactions 15 | with other Scala constructs. 16 | 17 | - Existential types largely overlap with path-dependent types, 18 | so the gain of having them is relatively minor. 19 | 20 | Existential types that can be expressed using only wildcards (but not 21 | `forSome`) are still supported, but are treated as refined types. 22 | For instance, the type 23 | ```scala 24 | Map[_ <: AnyRef, Int] 25 | ``` 26 | is treated as the type `Map`, where the first type parameter 27 | is upper-bounded by `AnyRef` and the second type parameter is an alias 28 | of `Int`. 29 | 30 | When reading classfiles compiled with _scalac_, Dotty will do a best 31 | effort to approximate existential types with its own types. It will 32 | issue a warning that a precise emulation is not possible. 33 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/limit22.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Limit 22 4 | --- 5 | 6 | The limits of 22 for the maximal number of parameters of function types 7 | and the maximal number of fields in tuple types have been dropped. 8 | 9 | Functions can now have an arbitrary number of 10 | parameters. Functions beyond Function22 are erased to a new trait 11 | `scala.FunctionXXL` and tuples beyond Tuple22 are erased to a new trait `scala.TupleXXL`. 12 | Both of these are implemented using arrays. 13 | 14 | Tuples can also have an arbitrary number of fields. Furthermore, they support generic operation such as concatenation and indexing. 15 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/macros.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Scala 2 Macros 4 | --- 5 | 6 | The previous, experimental macro system has been dropped. Instead, there is a cleaner, more restricted system based on two complementary concepts: `inline` and `'{ ... }`/`${ ... }` code generation. 7 | `'{ ... }` delays the compilation of the code and produces an object containing the code, dually `${ ... }` evaluates an expression which produces code and inserts it in the surrounding `${ ... }`. 8 | In this setting, a definition marked as inlined containing a `${ ... }` is a macro, the code inside the `${ ... }` is executed at compile-time and produces code in the form of `'{ ... }`. 9 | Additionally, the contents of code can be inspected and created with a more complex reflection API (TASTy Reflect) as an extension of `'{ ... }`/`${ ... }` framework. 10 | 11 | * `inline` has been [implemented](../metaprogramming/inline.md) in Dotty. 12 | * Quotes `'{ ... }` and splices `${ ... }` has been [implemented](../metaprogramming/macros.md) in Dotty. 13 | * [TASTy reflect](../metaprogramming/tasty-reflect.md) provides more complex tree based APIs to inspect or create quoted code. 14 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/nonlocal-returns.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Deprecated: Nonlocal Returns 4 | --- 5 | 6 | Returning from nested anonymous functions has been deprecated. Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. 7 | 8 | A drop-in library replacement is provided in `scala.util.control.NonLocalReturns`: 9 | 10 | ```scala 11 | import scala.util.control.NonLocalReturns._ 12 | 13 | returning { ... throwReturn(x) ... } 14 | ``` 15 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/package-objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Dropped: Package Objects" 4 | --- 5 | 6 | Package objects 7 | ```scala 8 | package object p { 9 | val a = ... 10 | def b = ... 11 | } 12 | ``` 13 | will be dropped. They are still available in Scala 3.0, but will be deprecated and removed afterwards. 14 | 15 | Package objects are no longer needed since all kinds of definitions can now be written at the top-level. E.g. 16 | ```scala 17 | package p 18 | type Labelled[T] = (String, T) 19 | val a: Labelled[Int] = ("count", 1) 20 | def b = a._2 21 | 22 | case class C() 23 | 24 | implicit object Cops { 25 | extension (x: C) def pair(y: C) = (x, y) 26 | } 27 | ``` 28 | There may be several source files in a package containing such toplevel definitions, and source files can freely mix toplevel value, method, and type definitions with classes and objects. 29 | 30 | The compiler generates synthetic objects that wrap toplevel definitions falling into one of the following categories: 31 | 32 | - all pattern, value, method, and type definitions, 33 | - implicit classes and objects, 34 | - companion objects of opaque type aliases. 35 | 36 | If a source file `src.scala` contains such toplevel definitions, they will be put in a synthetic object named `src$package`. The wrapping is transparent, however. The definitions in `src` can still be accessed as members of the enclosing package. 37 | 38 | **Note 1:** This means that the name of a source file containing wrapped toplevel definitions is relevant for binary compatibility. If the name changes, so does the name of the generated object and its class. 39 | 40 | **Note 2:** A toplevel main method `def main(args: Array[String]): Unit = ...` is wrapped as any other method. If it appears 41 | in a source file `src.scala`, it could be invoked from the command line using a command like `scala src$package`. Since the 42 | "program name" is mangled it is recommended to always put `main` methods in explicitly named objects. 43 | 44 | **Note 3:** The notion of `private` is independent of whether a definition is wrapped or not. A `private` toplevel definition is always visible from everywhere in the enclosing package. 45 | 46 | **Note 4:** If several toplevel definitions are overloaded variants with the same name, 47 | they must all come from the same source file. 48 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/procedure-syntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Procedure Syntax 4 | --- 5 | 6 | Procedure syntax 7 | ```scala 8 | def f() { ... } 9 | ``` 10 | has been dropped. You need to write one of the following instead: 11 | ```scala 12 | def f() = { ... } 13 | def f(): Unit = { ... } 14 | ``` 15 | Dotty will accept the old syntax under the `-source:3.0-migration` option. 16 | If the `-migration` option is set, it can even rewrite old syntax to new. 17 | The [ScalaFix](https://scalacenter.github.io/scalafix/) tool also 18 | can rewrite procedure syntax to make it Dotty-compatible. 19 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/symlits.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Symbol Literals 4 | --- 5 | 6 | Symbol literals are no longer supported. The `scala.Symbol` class still exists, so a 7 | literal translation of the symbol literal `'xyz` is `Symbol("xyz")`. However, it is recommended to use a plain string literal `"xyz"` instead. (The `Symbol` class will be deprecated and removed in the future). 8 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/this-qualifier.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: private[this] and protected[this] 4 | --- 5 | 6 | The `private[this]` and `protected[this]` access modifiers are deprecated and will be phased out. 7 | 8 | Previously, these modifiers were needed 9 | 10 | - for avoiding the generation of getters and setters 11 | - for excluding code under a `private[this]` from variance checks. (Scala 2 also excludes `protected[this]` but this was found to be unsound and was therefore removed). 12 | 13 | The compiler now infers for `private` members the fact that they are only accessed via `this`. Such members are treated as if they had been declared `private[this]`. `protected[this]` is dropped without a replacement. 14 | 15 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/type-projection.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: General Type Projection 4 | --- 5 | 6 | Scala so far allowed general type projection `T#A` where `T` is an arbitrary type 7 | and `A` names a type member of `T`. 8 | 9 | Dotty disallows this if `T` is an abstract type (class types and type aliases 10 | are fine). This change was made because unrestricted type projection 11 | is [unsound](https://github.com/lampepfl/dotty/issues/1050). 12 | 13 | This restriction rules out the [type-level encoding of a combinator 14 | calculus](https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/). 15 | 16 | To rewrite code using type projections on abstract types, consider using 17 | path-dependent types or implicit parameters. 18 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/weak-conformance-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Weak Conformance - More Details 4 | --- 5 | 6 | To simplify the underlying type theory, Dotty drops the notion of weak 7 | conformance altogether. Instead, it provides more flexibility when 8 | assigning a type to a constant expression. The new rule is: 9 | 10 | - If a list of expressions `Es` appears as one of 11 | 12 | - the elements of a vararg parameter, or 13 | - the alternatives of an if-then-else or match expression, or 14 | - the body and catch results of a try expression, 15 | 16 | 17 | and all expressions have primitive numeric types, but they do not 18 | all have the same type, then the following is attempted: 19 | 20 | - the expressions `Es` are partitioned into `Int` constants on the 21 | one hand, and all other expressions on the other hand, 22 | - if all the other expressions have the same numeric type `T` 23 | (which can be one of `Byte`, `Short`, `Char`, `Int`, `Long`, `Float`, 24 | `Double`), possibly after widening, and if none of the `Int` 25 | literals would incur a loss of precision when converted to `T`, 26 | then they are thus converted (the other expressions are left 27 | unchanged regardless), 28 | - otherwise, the expressions `Es` are used unchanged. 29 | 30 | A loss of precision occurs for an `Int -> Float` conversion of a constant 31 | `c` if `c.toFloat.toInt != c`. For an `Int -> Byte` conversion it occurs 32 | if `c.toByte.toInt != c`. For an `Int -> Short` conversion, it occurs 33 | if `c.toShort.toInt != c`. 34 | 35 | ### Examples 36 | 37 | ```scala 38 | inline val b = 33 39 | def f(): Int = b + 1 40 | Array(b, 33, 5.5) : Array[Double] // b is an inline val 41 | Array(f(), 33, 5.5) : Array[AnyVal] // f() is not a constant 42 | Array(5, 11L) : Array[Long] 43 | Array(5, 11L, 5.5) : Array[AnyVal] // Long and Double found 44 | Array(1.0f, 2) : Array[Float] 45 | Array(1.0f, 1234567890): Array[AnyVal] // loss of precision 46 | Array(b, 33, 'a') : Array[Char] 47 | Array(5.toByte, 11) : Array[Byte] 48 | ``` 49 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/weak-conformance.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: Weak Conformance 4 | --- 5 | 6 | In some situations, Scala used a _weak conformance_ relation when 7 | testing type compatibility or computing the least upper bound of a set 8 | of types. The principal motivation behind weak conformance was to 9 | make an expression like this have type `List[Double]`: 10 | 11 | ```scala 12 | List(1.0, math.sqrt(3.0), 0, -3.3) // : List[Double] 13 | ``` 14 | 15 | It's "obvious" that this should be a `List[Double]`. However, without 16 | some special provision, the least upper bound of the lists's element 17 | types `(Double, Double, Int, Double)` would be `AnyVal`, hence the list 18 | expression would be given type `List[AnyVal]`. 19 | 20 | A less obvious example is the following one, which was also typed as a 21 | `List[Double]`, using the weak conformance relation. 22 | 23 | ```scala 24 | val n: Int = 3 25 | val c: Char = 'X' 26 | val d: Double = math.sqrt(3.0) 27 | List(n, c, d) // used to be: List[Double], now: List[AnyVal] 28 | ``` 29 | 30 | Here, it is less clear why the type should be widened to 31 | `List[Double]`, a `List[AnyVal]` seems to be an equally valid -- and 32 | more principled -- choice. 33 | 34 | Weak conformance applies to all "numeric" types (including `Char`), and 35 | independently of whether the expressions are literals or not. However, 36 | in hindsight, the only intended use case is for *integer literals* to 37 | be adapted to the type of the other expressions. Other types of numerics 38 | have an explicit type annotation embedded in their syntax (`f`, `d`, 39 | `.`, `L` or `'` for `Char`s) which ensures that their author really 40 | meant them to have that specific type). 41 | 42 | Therefore, Dotty drops the general notion of weak conformance, and 43 | instead keeps one rule: `Int` literals are adapted to other numeric 44 | types if necessary. 45 | 46 | [More details](weak-conformance-spec.md) 47 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/dropped-features/xml.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Dropped: XML Literals 4 | --- 5 | 6 | XML Literals are still supported, but will be dropped in the near future, to 7 | be replaced with XML string interpolation: 8 | ```scala 9 | xml""" ... """ 10 | ``` 11 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/metaprogramming/erased-terms-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Erased Terms Spec" 4 | --- 5 | 6 | # Implementation 7 | 8 | ## Rules 9 | 10 | 1. The `erased` modifier can appear: 11 | * At the start of a parameter block of a method, function or class 12 | * In a method definition 13 | * In a `val` definition (but not `lazy val` or `var`) 14 | 15 | ```scala 16 | erased val x = ... 17 | erased def f = ... 18 | 19 | def g(erased x: Int) = ... 20 | 21 | (erased x: Int) => ... 22 | def h(x: (erased Int) => Int) = ... 23 | 24 | class K(erased x: Int) { ... } 25 | ``` 26 | 27 | 28 | 2. A reference to an `erased` definition can only be used 29 | * Inside the expression of argument to an `erased` parameter 30 | * Inside the body of an `erased` `val` or `def` 31 | 32 | 33 | 3. Functions 34 | * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R` 35 | * `(given erased x1: T1, x2: T2, ..., xN: TN) => y as (given erased T1, T2, ..., TN) => R` 36 | * `(given erased T1) => R <:< erased T1 => R` 37 | * `(given erased T1, T2) => R <:< (erased T1, T2) => R` 38 | * ... 39 | 40 | Note that there is no subtype relation between `(erased T) => R` and `T => R` (or `(given erased T) => R` and `(given T) => R`) 41 | 42 | 43 | 4. Eta expansion 44 | 45 | if `def f(erased x: T): U` then `f: (erased T) => U`. 46 | 47 | 48 | 5. Erasure Semantics 49 | * All `erased` parameters are removed from the function 50 | * All argument to `erased` parameters are not passed to the function 51 | * All `erased` definitions are removed 52 | * All `(erased T1, T2, ..., TN) => R` and `(given erased T1, T2, ..., TN) => R` become `() => R` 53 | 54 | 55 | 6. Overloading 56 | 57 | Method with `erased` parameters will follow the normal overloading constraints after erasure. 58 | 59 | 60 | 7. Overriding 61 | * Member definitions overriding each other must both be `erased` or not be `erased` 62 | * `def foo(x: T): U` cannot be overridden by `def foo(erased x: T): U` and vice-versa 63 | 64 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/metaprogramming/tasty-inspect.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "TASTy Inspection" 4 | --- 5 | 6 | ```scala 7 | libraryDependencies += "ch.epfl.lamp" %% "dotty-tasty-inspector" % scalaVersion.value 8 | ``` 9 | 10 | TASTy files contain the full typed tree of a class including source positions 11 | and documentation. This is ideal for tools that analyze or extract semantic 12 | information from the code. To avoid the hassle of working directly with the TASTy 13 | file we provide the `TastyInspector` which loads the contents and exposes it 14 | through the TASTy reflect API. 15 | 16 | 17 | ## Inspecting TASTy files 18 | 19 | To inspect the TASTy Reflect trees of a TASTy file a consumer can be defined in 20 | the following way. 21 | 22 | ```scala 23 | import scala.tasty.Reflection 24 | import scala.tasty.file._ 25 | 26 | class Consumer extends TastyInspector { 27 | final def apply(reflect: Reflection)(root: reflect.Tree): Unit = { 28 | import reflect._ 29 | // Do something with the tree 30 | } 31 | } 32 | ``` 33 | 34 | Then the consumer can be instantiated with the following code to get the tree of 35 | the class `foo.Bar` for a foo in the classpath. 36 | 37 | ```scala 38 | object Test { 39 | def main(args: Array[String]): Unit = { 40 | InspectTasty("", List("foo.Bar"), new Consumer) 41 | } 42 | } 43 | ``` 44 | 45 | Note that if we need to run the main (in the example below defined in an object called `Test`) after 46 | compilation we need to make the compiler available to the runtime: 47 | 48 | ```shell 49 | dotc -d out Test.scala 50 | dotr -with-compiler -classpath out Test 51 | ``` 52 | 53 | 54 | ## Template project 55 | Using sbt version `1.1.5+`, do: 56 | ``` 57 | sbt new lampepfl/dotty-tasty-inspector.g8 58 | ``` 59 | in the folder where you want to clone the template. 60 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/metaprogramming/toc.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Overview" 4 | --- 5 | 6 | The following pages introduce the redesign of metaprogramming in Scala. They 7 | introduce the following fundamental facilities: 8 | 9 | 1. [Inline](./inline.md) `inline` is a new modifier that guarantees that 10 | a definition will be inlined at the point of use. The primary motivation 11 | behind inline is to reduce the overhead behind function calls and access to 12 | values. The expansion will be performed by the Scala compiler during the 13 | `Typer` compiler phase. As opposed to inlining in some other ecosystems, 14 | inlining in Scala is not merely a request to the compiler but is a 15 | _command_. The reason is that inlining in Scala can drive other compile-time 16 | operations, like inline pattern matching (enabling type-level 17 | programming), macros (enabling compile-time, generative, metaprogramming) and 18 | runtime code generation (multi-stage programming). 19 | 20 | 2. [Macros](./macros.md) Macros are built on two well-known fundamental 21 | operations: quotation and splicing. Quotation converts program code to 22 | data, specifically, a (tree-like) representation of this code. It is 23 | expressed as `'{...}` for expressions and as `'[...]` for types. Splicing, 24 | expressed as `${ ... }`, goes the other way: it converts a program's representation 25 | to program code. Together with `inline`, these two abstractions allow 26 | to construct program code programmatically. 27 | 28 | 3. [Staging](./staging.md) Where macros construct code at _compile-time_, 29 | staging lets programs construct new code at _runtime_. That way, 30 | code generation can depend not only on static data but also on data available at runtime. This splits the evaluation of the program in two or more phases or ... 31 | stages. Consequently, this method of generative programming is called "Multi-Stage Programming". Staging is built on the same foundations as macros. It uses 32 | quotes and splices, but leaves out `inline`. 33 | 34 | 4. [TASTy Reflection](./tasty-reflect.md) Quotations are a "black-box" 35 | representation of code. They can be parameterized and composed using 36 | splices, but their structure cannot be analyzed from the outside. Tasty 37 | reflection gives a way to analyze code structure by partly revealing the representation type of a piece of code in a standard API. The representation 38 | type is a form of typed abstract syntax tree, which gives rise to the `TASTy` 39 | moniker. 40 | 41 | 5. [TASTy Inspection](./tasty-inspect.md) Typed abstract syntax trees are serialized 42 | in a custom compressed binary format stored in `.tasty` files. TASTy inspection allows 43 | to load these files and analyze their content's tree structure. 44 | 45 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/new-types/dependent-function-types-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Dependent Function Types - More Details" 4 | --- 5 | 6 | Initial implementation in [#3464](https://github.com/lampepfl/dotty/pull/3464) 7 | 8 | ## Syntax 9 | 10 | ``` 11 | FunArgTypes ::= InfixType 12 | | ‘(’ [ FunArgType {',' FunArgType } ] ‘)’ 13 | | ‘(’ TypedFunParam {',' TypedFunParam } ‘)’ 14 | TypedFunParam ::= id ‘:’ Type 15 | ``` 16 | 17 | Dependent function types associate to the right, e.g. 18 | `(s: S) ⇒ (t: T) ⇒ U` is the same as `(s: S) ⇒ ((t: T) ⇒ U)`. 19 | 20 | ## Implementation 21 | 22 | Dependent function types are shorthands for class types that define `apply` 23 | methods with a dependent result type. Dependent function types desugar to 24 | refinement types of `scala.FunctionN`. A dependent function type 25 | `(x1: K1, ..., xN: KN) => R` of arity `N` translates to: 26 | 27 | ```scala 28 | FunctionN[K1, ..., Kn, R'] { 29 | def apply(x1: K1, ..., xN: KN): R 30 | } 31 | ``` 32 | 33 | where the result type parameter `R'` is the least upper approximation of the 34 | precise result type `R` without any reference to value parameters `x1, ..., xN`. 35 | 36 | The syntax and sementics of anonymous dependent functions is identical to the 37 | one of regular functions. Eta expansion is naturally generalized to produce 38 | dependent function types for methods with dependent result types. 39 | 40 | Dependent functions can be implicit, and generalize to arity `N > 22` in the 41 | same way that other functions do, see [the corresponding 42 | documentation](../dropped-features/limit22.md). 43 | 44 | ## Examples 45 | 46 | - [depfuntype.scala](https://github.com/lampepfl/dotty/blob/master/tests/pos/depfuntype.scala) 47 | 48 | - [eff-dependent.scala](https://github.com/lampepfl/dotty/blob/master/tests/run/eff-dependent.scala) 49 | 50 | ### Type Checking 51 | 52 | After desugaring no additional typing rules are required for dependent function types. 53 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/new-types/dependent-function-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Dependent Function Types" 4 | --- 5 | 6 | A dependent function type describes functions where the result type may depend 7 | on the function's parameter values. Example: 8 | ```scala 9 | trait Entry { type Key; val key: Key } 10 | 11 | def extractKey(e: Entry): e.Key = e.key // a dependent method 12 | val extractor: (e: Entry) => e.Key = extractKey // a dependent function value 13 | // ║ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ⇓ ║ 14 | // ║ Dependent ║ 15 | // ║ Function Type ║ 16 | // ╚═══════════════════╝ 17 | ``` 18 | Scala already has _dependent methods_, i.e. methods where the result 19 | type refers to some of the parameters of the method. Method 20 | `extractKey` is an example. Its result type, `e.Key` refers to its 21 | parameter `e` (we also say, `e.Key` _depends_ on `e`). But so far it 22 | was not possible to turn such methods into function values, so that 23 | they can be passed as parameters to other functions, or returned as 24 | results. Dependent methods could not be turned into functions simply 25 | because there was no type that could describe them. 26 | 27 | In Dotty this is now possible. The type of the `extractor` value above is 28 | 29 | ```scala 30 | (e: Entry) => e.Key 31 | ``` 32 | 33 | This type describes function values that take any argument `e` of type 34 | `Entry` and return a result of type `e.Key`. 35 | 36 | Recall that a normal function type `A => B` is represented as an 37 | instance of the `Function1` trait (i.e. `Function1[A, B]`) and 38 | analogously for functions with more parameters. Dependent functions 39 | are also represented as instances of these traits, but they get an additional 40 | refinement. In fact, the dependent function type above is just syntactic sugar for 41 | ```scala 42 | Function1[Entry, Entry#Key] { 43 | def apply(e: Entry): e.Key 44 | } 45 | ``` 46 | [More details](./dependent-function-types-spec.md) 47 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/new-types/intersection-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Intersection Types" 4 | --- 5 | 6 | Used on types, the `&` operator creates an intersection type. 7 | 8 | ## Type Checking 9 | 10 | The type `S & T` represents values that are of the type `S` and `T` at the same time. 11 | 12 | ```scala 13 | trait Resettable { 14 | def reset(): Unit 15 | } 16 | trait Growable[T] { 17 | def add(t: T): Unit 18 | } 19 | def f(x: Resettable & Growable[String]) = { 20 | x.reset() 21 | x.add("first") 22 | } 23 | ``` 24 | 25 | The parameter `x` is required to be _both_ a `Resettable` and a 26 | `Growable[String]`. 27 | 28 | The members of an intersection type `A & B` are all the members of `A` and all 29 | the members of `B`. For instance `Resettable & Growable[String]` 30 | has member methods `reset` and `add`. 31 | 32 | `&` is _commutative_: `A & B` is the same type as `B & A`. 33 | 34 | If a member appears in both `A` and `B`, its type in `A & B` is the intersection 35 | of its type in `A` and its type in `B`. For instance, assume the definitions: 36 | 37 | ```scala 38 | trait A { 39 | def children: List[A] 40 | } 41 | trait B { 42 | def children: List[B] 43 | } 44 | val x: A & B = new C 45 | val ys: List[A & B] = x.children 46 | ``` 47 | 48 | The type of `children` in `A & B` is the intersection of `children`'s 49 | type in `A` and its type in `B`, which is `List[A] & List[B]`. This 50 | can be further simplified to `List[A & B]` because `List` is 51 | covariant. 52 | 53 | One might wonder how the compiler could come up with a definition for 54 | `children` of type `List[A & B]` since what is given are `children` 55 | definitions of type `List[A]` and `List[B]`. The answer is the compiler does not 56 | need to. `A & B` is just a type that represents a set of requirements for 57 | values of the type. At the point where a value is _constructed_, one 58 | must make sure that all inherited members are correctly defined. 59 | So if one defines a class `C` that inherits `A` and `B`, one needs 60 | to give at that point a definition of a `children` method with the required type. 61 | 62 | ```scala 63 | class C extends A with B { 64 | def children: List[A & B] = ??? 65 | } 66 | ``` 67 | 68 | 69 | [More details](./intersection-types-spec.md) 70 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/new-types/type-lambdas.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Type Lambdas" 4 | --- 5 | 6 | A _type lambda_ lets one express a higher-kinded type directly, without 7 | a type definition. 8 | 9 | ```scala 10 | [X, Y] =>> Map[Y, X] 11 | ``` 12 | 13 | For instance, the type above defines a binary type constructor, which maps arguments `X` and `Y` to `Map[Y, X]`. 14 | Type parameters of type lambdas can have bounds, but they cannot carry `+` or `-` variance annotations. 15 | 16 | [More details](./type-lambdas-spec.md) 17 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/new-types/union-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Union Types" 4 | --- 5 | 6 | A union type `A | B` has as values all values of type `A` and also all values of type `B`. 7 | 8 | 9 | ```scala 10 | case class UserName(name: String) 11 | case class Password(hash: Hash) 12 | 13 | def help(id: UserName | Password) = { 14 | val user = id match { 15 | case UserName(name) => lookupName(name) 16 | case Password(hash) => lookupPassword(hash) 17 | } 18 | ... 19 | } 20 | ``` 21 | 22 | Union types are duals of intersection types. `|` is _commutative_: 23 | `A | B` is the same type as `B | A`. 24 | 25 | The compiler will assign a union type to an expression only if such a 26 | type is explicitly given. This can be seen in the following REPL transcript: 27 | 28 | ```scala 29 | scala> val password = Password(123) 30 | val password: Password = Password(123) 31 | 32 | scala> val name = UserName("Eve") 33 | val name: UserName = UserName(Eve) 34 | 35 | scala> if (true) name else password 36 | val res2: Object & Product = UserName(Eve) 37 | 38 | scala> val either: Password | UserName = if (true) name else password 39 | val either: Password | UserName = UserName(Eve) 40 | ``` 41 | 42 | The type of `res2` is `Object & Product`, which is a supertype of 43 | `UserName` and `Password`, but not the least supertype `Password | 44 | UserName`. If we want the least supertype, we have to give it 45 | explicitly, as is done for the type of `either`. 46 | 47 | [More details](./union-types-spec.md) 48 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/control-syntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: New Control Syntax 4 | --- 5 | 6 | Scala 3 has a new "quiet" syntax for control expressions that does not rely on 7 | enclosing the condition in parentheses, and also allows to drop parentheses or braces 8 | around the generators of a `for`-expression. Examples: 9 | ```scala 10 | if x < 0 then 11 | "negative" 12 | else if x == 0 13 | "zero" 14 | else 15 | "positive" 16 | 17 | if x < 0 then -x else x 18 | 19 | while x >= 0 do x = f(x) 20 | 21 | for x <- xs if x > 0 22 | yield x * x 23 | 24 | for 25 | x <- xs 26 | y <- ys 27 | do 28 | println(x + y) 29 | ``` 30 | 31 | The rules in detail are: 32 | 33 | - The condition of an `if`-expression can be written without enclosing parentheses if it is followed by a `then` 34 | or some [indented](./indentation.html) code on a following line. 35 | - The condition of a `while`-loop can be written without enclosing parentheses if it is followed by a `do`. 36 | - The enumerators of a `for`-expression can be written without enclosing parentheses or braces if they are followed by a `yield` or `do`. 37 | - A `do` in a `for`-expression expresses a `for`-loop. 38 | 39 | ### Rewrites 40 | 41 | The Dotty compiler can rewrite source code from old syntax to new syntax and back. 42 | When invoked with options `-rewrite -new-syntax` it will rewrite from old to new syntax, dropping parentheses and braces in conditions and enumerators. When invoked with options `-rewrite -old-syntax` it will rewrite in the reverse direction, inserting parentheses and braces as needed. 43 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/creator-applications.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Creator Applications" 4 | --- 5 | 6 | Creator applications allow using simple function call syntax to create instances 7 | of a class, even if there is no apply method implemented. Example: 8 | ```scala 9 | class StringBuilder(s: String) { 10 | def this() = this("") 11 | } 12 | 13 | StringBuilder("abc") // same as new StringBuilder("abc") 14 | StringBuilder() // same as new StringBuilder() 15 | ``` 16 | Creator applications generalize a functionality provided so far only for case classes, but the mechanism how this is achieved is different. Instead of generating an apply method, the compiler adds a new possible interpretation to a function call `f(args)`. The previous rules are: 17 | 18 | Given a function call `f(args)`, 19 | 20 | - if `f` is a method applicable to `args`, typecheck `f(args)` unchanged, 21 | - otherwise, if `f` has an `apply` method applicable to `args` as a member, continue with `f.apply(args)`, 22 | - otherwise, if `f` is of the form `p.m` and there is an implicit conversion `c` applicable to `p` so that `c(p).m` is applicable to `args`, continue with `c(p).m(args)` 23 | 24 | There's now a fourth rule following these rules: 25 | 26 | - otherwise, if `f` is syntactically a stable identifier, and `new f` where `f` is interpreted as a type identifier is applicable to `args`, continue with `new f(args)`. 27 | 28 | Analogously, the possible interpretations of a function call with type arguments `f[targs]` are augmented with the following interpretation as a final fallback: 29 | 30 | - if `f` is syntactically a stable identifier, and `new f[targs]` where `f` is interpreted as a type identifier is well-typed, continue with `new f[targs]`. 31 | 32 | ### Motivation 33 | 34 | Leaving out `new` hides an implementation detail and makes code more pleasant to read. Even though it requires a new rule, it will likely increase the perceived regularity of the language, since case classes already provide function call creation syntax (and are often defined for this reason alone). 35 | 36 | ### Discussion 37 | 38 | An alternative design would auto-generate `apply` methods for normal classes, in the same way it is done now for case classes. This design was tried but abandoned since it 39 | caused numerous problems, including 40 | 41 | - overloading ambiguities 42 | - overriding errors 43 | - shadowing of user-defined `apply` methods by more specific auto-generated ones. 44 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/implicit-by-name-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Implicit By-Name Parameters" 4 | --- 5 | The contents of this page have [moved](../contextual/by-name-context-parameters.md). 6 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/kind-polymorphism.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Kind Polymorphism" 4 | --- 5 | 6 | Normally type parameters in Scala are partitioned into _kinds_. First-level types are types of values. Higher-kinded types are type constructors 7 | such as `List` or `Map`. The kind of a type is indicated by the top type of which it is a subtype. Normal types are subtypes of `Any`, 8 | covariant single argument type constructors such as `List` are subtypes of `[+X] =>> Any`, and the `Map` type constructor is 9 | a subtype of `[X, +Y] =>> Any`. 10 | 11 | A type can be used only as prescribed by its kind. Subtypes of `Any` cannot be applied to type arguments whereas subtypes of `[X] =>> Any` 12 | _must_ be applied to a type argument, unless they are passed to type parameters of the same kind. 13 | 14 | Sometimes we would like to have type parameters that can have more than one kind, for instance to define an implicit 15 | value that works for parameters of any kind. This is now possible through a form of (_subtype_) kind polymorphism. 16 | Kind polymorphism relies on the special type `scala.AnyKind` that can be used as an upper bound of a type. 17 | 18 | ```scala 19 | def f[T <: AnyKind] = ... 20 | ``` 21 | 22 | The actual type arguments of `f` can then be types of arbitrary kinds. So the following would all be legal: 23 | 24 | ```scala 25 | f[Int] 26 | f[List] 27 | f[Map] 28 | f[[X] =>> String] 29 | ``` 30 | 31 | We call type parameters and abstract types with an `AnyKind` upper bound _any-kinded types_. 32 | Since the actual kind of an any-kinded type is unknown, its usage must be heavily restricted: An any-kinded type 33 | can be neither the type of a value, nor can it be instantiated with type parameters. So about the only 34 | thing one can do with an any-kinded type is to pass it to another any-kinded type argument. 35 | Nevertheless, this is enough to achieve some interesting generalizations that work across kinds, typically 36 | through advanced uses of implicits. 37 | 38 | (todo: insert good concise example) 39 | 40 | Some technical details: `AnyKind` is a synthesized class just like `Any`, but without any members. It extends no other class. 41 | It is declared `abstract` and `final`, so it can be neither instantiated nor extended. 42 | 43 | `AnyKind` plays a special role in Scala's subtype system: It is a supertype of all other types no matter what their kind is. It is also assumed to be kind-compatible with all other types. Furthermore, `AnyKind` is treated as a higher-kinded type (so it cannot be used as a type of values), but at the same time it has no type parameters (so it cannot be instantiated). 44 | 45 | **Note**: This feature is considered experimental but stable and it can be disabled under compiler flag 46 | (i.e. `-Yno-kind-polymorphism`). 47 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/named-typeargs-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Named Type Arguments - More Details" 4 | --- 5 | 6 | ## Syntax 7 | 8 | The addition to the grammar is: 9 | 10 | ``` 11 | SimpleExpr1 ::= ... 12 | | SimpleExpr (TypeArgs | NamedTypeArgs) 13 | NamedTypeArgs ::= ‘[’ NamedTypeArg {‘,’ NamedTypeArg} ‘]’ 14 | NamedTypeArg ::= id ‘=’ Type 15 | ``` 16 | 17 | Note in particular that named arguments cannot be passed to type constructors: 18 | 19 | ``` scala 20 | class C[T] 21 | 22 | val x: C[T = Int] = // error 23 | new C[T = Int] // error 24 | 25 | class E extends C[T = Int] // error 26 | ``` 27 | 28 | ## Compatibility considerations 29 | 30 | Named type arguments do not have an impact on binary compatibility, but they 31 | have an impact on source compatibility: if the name of a method type parameter 32 | is changed, any existing named reference to this parameter will break. This 33 | means that the names of method type parameters are now part of the public API 34 | of a library. 35 | 36 | (Unimplemented proposal: to mitigate this, 37 | [`scala.deprecatedName`](https://www.scala-lang.org/api/current/scala/deprecatedName.html) 38 | could be extended to also be applicable on method type parameters.) 39 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/named-typeargs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Named Type Arguments" 4 | --- 5 | 6 | **Note:** This feature is implemented in Dotty, but is not expected to be part of Scala 3.0. 7 | 8 | Type arguments of methods can now be specified by name as well as by position. Example: 9 | 10 | ``` scala 11 | def construct[Elem, Coll[_]](xs: Elem*): Coll[Elem] = ??? 12 | 13 | val xs1 = construct[Coll = List, Elem = Int](1, 2, 3) 14 | val xs2 = construct[Coll = List](1, 2, 3) 15 | ``` 16 | 17 | Similar to a named value argument `(x = e)`, a named type argument 18 | `[X = T]` instantiates the type parameter `X` to the type `T`. 19 | Named type arguments do not have to be in order (see `xs1` above) and 20 | unspecified arguments are inferred by the compiler (see `xs2` above). 21 | Type arguments must be all named or un-named, mixtures of named and 22 | positional type arguments are not supported. 23 | 24 | ## Motivation 25 | 26 | The main benefit of named type arguments is that unlike positional arguments, 27 | you are allowed to omit passing arguments for some parameters, like in the 28 | definition of `xs2` above. A missing type argument is inferred as usual by 29 | local type inference. This is particularly useful in situations where some type 30 | arguments can be easily inferred from others. 31 | 32 | [More details](./named-typeargs-spec.md) 33 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/parameter-untupling.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Parameter Untupling" 4 | --- 5 | 6 | Say you have a list of pairs 7 | ```scala 8 | val xs: List[(Int, Int)] 9 | ``` 10 | and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to 11 | their sum. Previously, the best way to do this was with a pattern-matching decomposition: 12 | ```scala 13 | xs map { 14 | case (x, y) => x + y 15 | } 16 | ``` 17 | While correct, this is also inconvenient and confusing, since the `case` 18 | suggests that the pattern match could fail. As a shorter and clearer alternative Dotty now allows 19 | ```scala 20 | xs.map { 21 | (x, y) => x + y 22 | } 23 | ``` 24 | or, equivalently: 25 | ```scala 26 | xs.map(_ + _) 27 | ``` 28 | Generally, a function value with `n > 1` parameters is converted to a 29 | pattern-matching closure using `case` if the expected type is a unary 30 | function type of the form `((T_1, ..., T_n)) => U`. 31 | 32 | ### Reference 33 | 34 | For more info see: 35 | 36 | * [More details](./parameter-untupling-spec.md) 37 | * [Issue #897](https://github.com/lampepfl/dotty/issues/897). 38 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/threadUnsafe-annotation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: threadUnsafe annotation 4 | --- 5 | 6 | A new annotation `@threadUnsafe` can be used on a field which defines a `lazy 7 | val`. When this annotation is used, the initialization of the lazy val will use a 8 | faster mechanism which is not thread-safe. 9 | 10 | ### Example 11 | 12 | ```scala 13 | import scala.annotation.threadUnsafe 14 | 15 | class Hello { 16 | @threadUnsafe lazy val x: Int = 1 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/other-new-features/trait-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Trait Parameters" 4 | --- 5 | 6 | Dotty allows traits to have parameters, just like classes have parameters. 7 | 8 | ```scala 9 | trait Greeting(val name: String) { 10 | def msg = s"How are you, $name" 11 | } 12 | 13 | class C extends Greeting("Bob") { 14 | println(msg) 15 | } 16 | ``` 17 | 18 | Arguments to a trait are evaluated immediately before the trait is initialized. 19 | 20 | One potential issue with trait parameters is how to prevent 21 | ambiguities. For instance, you might try to extend `Greeting` twice, 22 | with different parameters. 23 | 24 | ```scala 25 | class D extends C with Greeting("Bill") // error: parameter passed twice 26 | ``` 27 | 28 | Should this print "Bob" or "Bill"? In fact this program is illegal, 29 | because it violates the second rule of the following for trait parameters: 30 | 31 | 1. If a class `C` extends a parameterized trait `T`, and its superclass does not, `C` _must_ pass arguments to `T`. 32 | 33 | 2. If a class `C` extends a parameterized trait `T`, and its superclass does as well, `C` _must not_ pass arguments to `T`. 34 | 35 | 3. Traits must never pass arguments to parent traits. 36 | 37 | Here's a trait extending the parameterized trait `Greeting`. 38 | 39 | ```scala 40 | trait FormalGreeting extends Greeting { 41 | override def msg = s"How do you do, $name" 42 | } 43 | ``` 44 | As is required, no arguments are passed to `Greeting`. However, this poses an issue 45 | when defining a class that extends `FormalGreeting`: 46 | 47 | ```scala 48 | class E extends FormalGreeting // error: missing arguments for `Greeting`. 49 | ``` 50 | 51 | The correct way to write `E` is to extend both `Greeting` and 52 | `FormalGreeting` (in either order): 53 | 54 | ```scala 55 | class E extends Greeting("Bob") with FormalGreeting 56 | ``` 57 | 58 | ### Reference 59 | 60 | For more info, see [Scala SIP 25](http://docs.scala-lang.org/sips/pending/trait-parameters.html). 61 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/reference/soft-modifier.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Soft Modifiers 4 | --- 5 | 6 | A soft modifier is one of the identifiers `opaque` and `inline`. 7 | 11 | 12 | It is treated as a potential modifier of a definition, if it is followed by a hard modifier or a keyword combination starting a definition (`def`, `val`, `var`, `type`, `class`, `case class`, `trait`, `object`, `case object`, `enum`). Between the two words there may be a sequence of newline tokens and soft modifiers. 13 | 14 | It is treated as a potential modifier of a parameter binding unless it is followed by `:`. 15 | 16 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/cbt-projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Using Dotty with cbt" 4 | --- 5 | 6 | **NOTE: cbt support for Dotty is experimental and incomplete (for example, 7 | incremental compilation is not supported), we recommend [using Dotty with sbt](sbt-projects.md) for now.** 8 | 9 | cbt comes with built-in Dotty support. Follow the 10 | [cbt tutorial](https://github.com/cvogt/cbt/), then simply extend `Dotty` in the Build class. 11 | 12 | ```scala 13 | // build/build.scala 14 | import cbt._ 15 | class Build(val context: Context) extends Dotty { 16 | ... 17 | } 18 | ``` 19 | 20 | Also see the [example project](https://github.com/cvogt/cbt/tree/master/examples/dotty-example). 21 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: Getting Started: Users 4 | --- 5 | 6 | ## Trying out Dotty 7 | 8 | ### In your web browser 9 | [Scastie](https://scastie.scala-lang.org/?target=dotty), the online Scala playground, supports Dotty. 10 | This is an easy way to try Dotty without installing anything, directly in your browser. 11 | 12 | ### sbt 13 | The fastest way to create a new project compiled by Dotty is using [sbt (1.1.4+)](http://www.scala-sbt.org/) 14 | 15 | Create a simple Dotty project: 16 | ```bash 17 | $ sbt new lampepfl/dotty.g8 18 | ``` 19 | 20 | Or a Dotty project that cross compiles with Scala 2: 21 | ```bash 22 | $ sbt new lampepfl/dotty-cross.g8 23 | ``` 24 | 25 | You can then start a Dotty REPL directly from your sbt project: 26 | ```bash 27 | $ sbt 28 | > console 29 | scala> 30 | ``` 31 | 32 | For more information, see the [Dotty Example Project](https://github.com/lampepfl/dotty-example-project) 33 | 34 | ### IDE support 35 | Start using the Dotty IDE in any Dotty project by following the 36 | [IDE guide](./ide-support.md). 37 | 38 | ### Standalone installation 39 | Releases are available for download on the [Releases Section](https://github.com/lampepfl/dotty/releases) 40 | of the Dotty repository. Releases include three executables: `dotc` the Dotty compiler, 41 | `dotd` the [Dotty Documentation tool](./dottydoc.md) and `dotr` the Dotty REPL. 42 | 43 | ``` 44 | . 45 | └── bin 46 |    ├── dotc 47 |    ├── dotd 48 |    └── dotr 49 | ``` 50 | 51 | Add these executables to your `PATH` and you will be able to run the corresponding commands directly 52 | from your console: 53 | ```bash 54 | # Compile code using Dotty 55 | $ dotc HelloWorld.scala 56 | 57 | # Run it with the proper classpath 58 | $ dotr HelloWorld 59 | 60 | # Start a Dotty REPL 61 | $ dotr 62 | Starting dotty REPL... 63 | scala> 64 | ``` 65 | 66 | If you're a Mac user, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: 67 | 68 | ```bash 69 | brew install lampepfl/brew/dotty 70 | ``` 71 | 72 | In case you have already installed Dotty via brew, you should instead update it: 73 | 74 | ```bash 75 | brew upgrade dotty 76 | ``` 77 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/ide-support.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "IDE support for Dotty" 4 | --- 5 | 6 | Dotty comes built-in with the Dotty Language Server, an implementation of the 7 | [Language Server Protocol](https://github.com/Microsoft/language-server-protocol), 8 | which means that any editor that implements the LSP can be used as a Dotty IDE. 9 | Currently, the only IDE we officially support is 10 | [Visual Studio Code](https://code.visualstudio.com/). 11 | 12 | Prerequisites 13 | ============ 14 | To use this in your own Scala project, you must first get it to compile with 15 | Dotty, please follow the instructions at https://github.com/lampepfl/dotty-example-project 16 | 17 | Usage 18 | ===== 19 | 1. Install [Visual Studio Code](https://code.visualstudio.com/). 20 | 2. Make sure `code`, the binary for Visual Studio Code, is on your `$PATH`, this 21 | is the case if you can start the IDE by running `code` in a terminal. This 22 | is the default on all systems except Mac where you'll need to follow these 23 | instructions: https://code.visualstudio.com/docs/setup/mac#_command-line 24 | 3. In your project, run: 25 | ```shell 26 | sbt launchIDE 27 | ``` 28 | 29 | Status 30 | ====== 31 | 32 | ## Fully supported features: 33 | - Typechecking as you type to show compiler errors/warnings 34 | - Type information on hover 35 | - Go to definition (in the current project) 36 | - Find all references 37 | - Documentation on hover 38 | - [Worksheet mode](worksheet-mode.md) 39 | 40 | ## Partially working features: 41 | - Completion 42 | - Renaming 43 | - Go to definition in external projects 44 | 45 | ## Unimplemented features: 46 | - Formatting code (requires integrating with scalafmt) 47 | - Quick fixes (probably by integrating with scalafix) 48 | 49 | ## Current limitations, to be fixed: 50 | - Projects should be compiled with sbt before starting the IDE, this is 51 | automatically done for you if you run `sbt launchIDE`. 52 | - Once the IDE is started, source files that are not opened in the IDE 53 | should not be modified in some other editor, the IDE won't pick up 54 | these changes. 55 | - Not all compiler errors/warnings are displayed, just those occurring 56 | during typechecking. 57 | 58 | 59 | Feedback 60 | ======== 61 | Please report issues on https://github.com/lampepfl/dotty/issues, 62 | you can also come chat with use on the 63 | [Dotty gitter channel](https://gitter.im/lampepfl/dotty)! 64 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/language-versions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Language Versions" 4 | --- 5 | 6 | The default Scala language version currently supported by the Dotty compiler is `3.0`. There are also other language versions that can be specified instead: 7 | 8 | - `3.1`: A preview of changes introduced in the next version after 3.0. Some Scala-2 specific idioms will be dropped in this version. The feature set supported by this version will be refined over time as we approach its release. 9 | 10 | - `3.0-migration`: Same as `3.0` but with a Scala 2 compatibility mode that helps moving Scala 2.13 sources over to Scala 3. In particular, it 11 | 12 | - flags some Scala 2 constructs that are disallowed in Scala 3 as migration warnings instead of hard errors, 13 | - changes some rules to be more lenient and backwards compatible with Scala 2.13 14 | - gives some additional warnings where the semantics has changed between Scala 2.13 and 3.0 15 | - in conjunction with `-rewrite`, offer code rewrites from Scala 2.13 to 3.0. 16 | 17 | - `3.1-migration`: Same as `3.1` but with additional helpers to migrate from `3.0`. Similarly to the helpers available under `3.0-migration`, these include migration warnings and optional rewrites. 18 | 19 | There are two ways to specify a language version. 20 | 21 | - With a `-source` command line setting, e.g. `-source 3.0-migration`. 22 | - With a `scala.language` import at the top of a compilation unit, e.g: 23 | 24 | ```scala 25 | package p 26 | import scala.language.`3.1` 27 | 28 | class C { ... } 29 | ``` 30 | 31 | Language imports supersede command-line settings in the compilation units where they are specified. Only one language import is allowed in a compilation unit, and it must come before any definitions in that unit. 32 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/sbt-projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Using Dotty with sbt" 4 | --- 5 | 6 | To try it in your project see the [Getting Started User Guide](./getting-started.md). 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/version-numbers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Version numbers" 4 | --- 5 | 6 | **This documentation is outdated! Please find the newer version [here](../contributing/procedures/release.md)**. 7 | 8 | Dotty uses multiple schemes for version numbering. 9 | 10 | Stable releases have version numbers of the form `0.${x}.${y}`, where `x` is a main version and `y` is a bug-fix update id. 11 | 12 | Release candidates version numbers have the form `0.${x}.${y}-RC${z}`. 13 | Every 6 weeks, the latest release candidate is promoted to stable and becomes version `0.${x}.${y}`. 14 | The release candidates let library authors test their code in advance of each 15 | release. Multiple release candidates may be released during each 6 weeks 16 | period to fix regressions and are differentiated by `z`. 17 | 18 | Nightlies have version numbers of the form `0.${x}.${y}-bin-${date}-${sha}-NIGHTLY`. 19 | Every 6 weeks, the latest nightly is promoted to release candidate becomes version `0.${x}.${y}-RC1`. 20 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/worksheet-mode-implementation-details.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Worksheet Mode - Implementation details" 4 | --- 5 | 6 | In brief, the worksheets extend the Language Server Protocol and rely on the 7 | Dotty REPL to evaluate code. 8 | 9 | ## Evaluation 10 | Each of the individual expressions and statements of the worksheet is extracted 11 | and passed to the Dotty REPL. After the REPL has finished evaluating one unit of 12 | input, it emits a special delimiter that indicates the end of the output for 13 | this input. (See `dotty.tools.languageserver.worksheet.InputStreamConsumer`) 14 | 15 | This process continues until all input has been evaluated. 16 | 17 | The Dotty REPL is run in a separate JVM. The `Evaluator` (see 18 | `dotty.tools.languageserver.worksheet.Evaluator`) will re-use a JVM if the 19 | configuration of the project hasn't changed. 20 | 21 | ## Communication with the client 22 | The worksheets extend the Language Server Protocol and add one request and one 23 | notification. 24 | 25 | ### Run worksheet request 26 | The worksheet run request is sent from the client to the server to request that 27 | the server runs a given worksheet and streams the result. 28 | 29 | *Request:* 30 | 31 | - method: `worksheet/run` 32 | - params: `WorksheetRunParams` defined as follows: 33 | ```typescript 34 | interface WorksheetRunParams { 35 | /** 36 | * The worksheet to evaluate. 37 | */ 38 | textDocument: VersionedTextDocumentIdentifier; 39 | } 40 | ``` 41 | 42 | *Response:* 43 | 44 | - result: `WorksheetRunResult` defined as follows: 45 | ```typescript 46 | interface WorksheetRunResult { 47 | /** 48 | * Indicates whether evaluation was successful. 49 | */ 50 | success: boolean; 51 | } 52 | ``` 53 | 54 | ### Worksheet output notification 55 | The worksheet output notification is sent from the server to the client to 56 | indicate that worksheet execution has produced some output. 57 | 58 | *Notification:* 59 | 60 | - method: `worksheet/publishOutput` 61 | - params: `WorksheetRunOutput` defined as follows: 62 | ```typescript 63 | interface WorksheetRunOutput { 64 | /** 65 | * The worksheet that produced this output. 66 | */ 67 | textDocument: VersionedTextDocumentIdentifier; 68 | 69 | /** 70 | * The range of the expression that produced this output. 71 | */ 72 | range: Range; 73 | 74 | /** 75 | * The output that has been produced. 76 | */ 77 | content: string; 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /dotty-docs/docs/docs/usage/worksheet-mode.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: doc-page 3 | title: "Worksheet mode with Dotty IDE" 4 | --- 5 | 6 | A worksheet is a Scala file that is evaluated on save, and the result of each 7 | expression is shown in a column to the right of your program. Worksheets are 8 | like a REPL session on steroids, and enjoy 1st class editor support: completion, 9 | hyperlinking, interactive errors-as-you-type, etc. Worksheet use the extension 10 | `.sc`. 11 | 12 | How to use the worksheets 13 | ========================= 14 | The only supported client for the Worksheet mode is [Visual Studio 15 | Code](https://code.visualstudio.com/). 16 | 17 | To use the worksheets, start Dotty IDE by [following the 18 | instruction](ide-support.md) and create a new file `MyWorksheet.sc` and 19 | write some code: 20 | 21 | ```scala 22 | val xyz = 123 23 | println("Hello, worksheets!") 24 | 456 + xyz 25 | ``` 26 | 27 | On top of the buffer, the message `Run this worksheet` appears. Click it to 28 | evaluate the code of the worksheet. Each line of output is printed on the right 29 | of the expression that produced it. The worksheets run with the classes of your 30 | project and its dependencies on their classpath. 31 | 32 | ![../../images/worksheets/worksheet-run.png ]("Run worksheet") 33 | 34 | By default, the worksheets are also run when the file is saved. This can be 35 | configured in VSCode preferences: 36 | 37 | ![../../images/worksheets/config-autorun.png]("Configure run on save") 38 | 39 | Note that the worksheet are fully integrated with the rest of Dotty IDE: While 40 | typing, errors are shown, completions are suggested, and you can use all the 41 | other features of Dotty IDE such as go to definition, find all references, etc. 42 | 43 | ![../../images/worksheets/worksheet-help.png]("IDE features in the worksheet") 44 | 45 | Implementation details 46 | ====================== 47 | 48 | The implementation details of the worksheet mode and the information necessary to add support for 49 | other clients are available in [Worksheet mode - Implementation 50 | details](worksheet-mode-implementation-details.md). 51 | -------------------------------------------------------------------------------- /dotty-docs/docs/images/aggelos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/aggelos.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/allan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/allan.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/anatolii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/anatolii.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/dotty-ide/decompiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/dotty-ide/decompiler.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/dotty-ide/documentation-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/dotty-ide/documentation-hover.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/dotty-ide/signature-help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/dotty-ide/signature-help.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/explicit-nulls/explicit-nulls-type-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/explicit-nulls/explicit-nulls-type-hierarchy.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/favicon.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/felix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/felix.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/fengyun.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/fengyun.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/github-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dotty-docs/docs/images/martin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/martin.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/nico.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/nico.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/olivier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/olivier.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/others/scala-days-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/others/scala-days-logo.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/petrashko.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/petrashko.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/preview.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/scala-logo copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dotty-docs/docs/images/scala-logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dotty-docs/docs/images/smarter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/smarter.jpg -------------------------------------------------------------------------------- /dotty-docs/docs/images/worksheets/config-autorun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/worksheets/config-autorun.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/worksheets/worksheet-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/worksheets/worksheet-demo.gif -------------------------------------------------------------------------------- /dotty-docs/docs/images/worksheets/worksheet-help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/worksheets/worksheet-help.png -------------------------------------------------------------------------------- /dotty-docs/docs/images/worksheets/worksheet-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/dotty-docs/docs/images/worksheets/worksheet-run.png -------------------------------------------------------------------------------- /dotty-docs/docs/js/sidebar.js: -------------------------------------------------------------------------------- 1 | // Toggles a sidebar section 2 | function toggleSection(titleElement) { 3 | const title = $(titleElement); 4 | title.siblings("ul").toggleClass("toggled"); 5 | title.children("i.fas").toggleClass("fa-angle-right").toggleClass("fa-angle-down"); 6 | } 7 | -------------------------------------------------------------------------------- /dotty-docs/docs/js/toolbar.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $("#menu-icon").click(() => { 3 | $(".sidebar").toggleClass("toggled"); 4 | }) 5 | $("#search-icon").click(() => { 6 | $("#searchbar").toggleClass("shown"); 7 | $("#search-api-input").focus(); 8 | }) 9 | const searchInput = $("#search-api-input"); 10 | searchInput.keydown(evt => { 11 | if (evt.which == 13) { 12 | const baseUrl = $("#baseurl-input").val(); 13 | window.location = ( 14 | baseUrl + "/api/search.html?" + 15 | "searchTerm=" + searchInput.val() + 16 | "&previousUrl=" + encodeURI(window.location) 17 | ); 18 | } 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /example-project/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.class 3 | *.log 4 | *~ 5 | 6 | # sbt specific 7 | dist/* 8 | target/ 9 | lib_managed/ 10 | src_managed/ 11 | project/boot/ 12 | project/plugins/project/ 13 | project/local-plugins.sbt 14 | .history 15 | 16 | # Scala-IDE specific 17 | .scala_dependencies 18 | .cache 19 | .classpath 20 | .project 21 | .settings 22 | classes/ 23 | 24 | # idea 25 | .idea 26 | .idea_modules 27 | /.worksheet/ 28 | -------------------------------------------------------------------------------- /example-project/.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | 3 | jdk: 4 | - openjdk8 5 | 6 | script: 7 | - sbt run 8 | - sbt 'set scalaVersion := dottyLatestNightlyBuild.get' run 9 | -------------------------------------------------------------------------------- /example-project/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The dotty-example-project contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /example-project/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.3.13 2 | -------------------------------------------------------------------------------- /example-project/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1") 2 | -------------------------------------------------------------------------------- /example-project/src/main/scala/AutoParamTupling.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Automatic Tupling of Function Params: https://dotty.epfl.ch/docs/reference/other-new-features/auto-parameter-tupling.html 5 | */ 6 | object AutoParamTupling { 7 | 8 | def test: Unit = { 9 | 10 | /** 11 | * In order to get thread safety, you need to put @volatile before lazy vals. 12 | * https://dotty.epfl.ch/docs/reference/changed-features/lazy-vals.html 13 | */ 14 | @volatile lazy val xs: List[String] = List("d", "o", "t", "t", "y") 15 | 16 | /** 17 | * Current behaviour in Scala 2.12.2 : 18 | * error: missing parameter type 19 | * Note: The expected type requires a one-argument function accepting a 2-Tuple. 20 | * Consider a pattern matching anonymous function, `{ case (s, i) => ... }` 21 | */ 22 | xs.zipWithIndex.map((s, i) => println(s"$i: $s")) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example-project/src/main/scala/ContextQueries.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import scala.concurrent.{ExecutionContext, Future} 4 | import scala.util.Try 5 | 6 | /** 7 | * Context Queries: 8 | * - http://dotty.epfl.ch/docs/reference/contextual/query-types.html, 9 | * - https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html 10 | */ 11 | object ContextQueries /* Formerly known as Implicit Function Types */ { 12 | 13 | object context { 14 | // type alias Contextual 15 | type Contextual[T] = ExecutionContext ?=> T 16 | 17 | // sum is expanded to sum(x, y)(ctx) 18 | def asyncSum(x: Int, y: Int): Contextual[Future[Int]] = Future(x + y) 19 | 20 | def asyncMult(x: Int, y: Int)(using ctx: ExecutionContext) = Future(x * y) 21 | } 22 | 23 | object parse { 24 | 25 | type Parseable[T] = ImpliedInstances.StringParser[T] ?=> Try[T] 26 | 27 | def sumStrings(x: String, y: String): Parseable[Int] = { 28 | val parser = implicitly[ImpliedInstances.StringParser[Int]] 29 | val tryA = parser.parse(x) 30 | val tryB = parser.parse(y) 31 | 32 | for { 33 | a <- tryA 34 | b <- tryB 35 | } yield a + b 36 | } 37 | } 38 | 39 | def test: Unit = { 40 | import ExecutionContext.Implicits.global 41 | context.asyncSum(3, 4).foreach(println) 42 | context.asyncMult(3, 4).foreach(println) 43 | 44 | println(parse.sumStrings("3", "4")) 45 | println(parse.sumStrings("3", "a")) 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /example-project/src/main/scala/Conversion.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import scala.language.implicitConversions 4 | 5 | /** 6 | * Conversions: http://dotty.epfl.ch/docs/reference/contextual/conversions.html 7 | */ 8 | object Conversion { 9 | 10 | case class IntWrapper(a: Int) extends AnyVal 11 | case class DoubleWrapper(b: Double) extends AnyVal 12 | 13 | def convert[T, U](x: T)(using converter: Conversion[T, U]): U = converter(x) 14 | 15 | given IntWrapperToDoubleWrapper as Conversion[IntWrapper, DoubleWrapper] = new Conversion[IntWrapper, DoubleWrapper] { 16 | override def apply(i: IntWrapper): DoubleWrapper = new DoubleWrapper(i.a.toDouble) 17 | } 18 | 19 | def useConversion(using f: Conversion[IntWrapper, DoubleWrapper]) = { 20 | val y: IntWrapper = new IntWrapper(4) 21 | val x: DoubleWrapper = y 22 | x 23 | } 24 | 25 | /* Not working anymore. 26 | def useConversion(implicit f: A => B) = { 27 | val y: A = ... 28 | val x: B = a // error under Dotty 29 | } 30 | */ 31 | 32 | def test: Unit = { 33 | println(useConversion) 34 | println(convert(new IntWrapper(42))) 35 | } 36 | 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /example-project/src/main/scala/EnumTypes.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Enum Types: http://dotty.epfl.ch/docs/reference/enums/adts.html 5 | */ 6 | object EnumTypes { 7 | 8 | enum ListEnum[+A] { 9 | case Cons(h: A, t: ListEnum[A]) 10 | case Empty 11 | } 12 | 13 | enum Planet(mass: Double, radius: Double) { 14 | private final val G = 6.67300E-11 15 | def surfaceGravity = G * mass / (radius * radius) 16 | def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity 17 | 18 | case Mercury extends Planet(3.303e+23, 2.4397e6) 19 | case Venus extends Planet(4.869e+24, 6.0518e6) 20 | case Earth extends Planet(5.976e+24, 6.37814e6) 21 | case Mars extends Planet(6.421e+23, 3.3972e6) 22 | case Jupiter extends Planet(1.9e+27, 7.1492e7) 23 | case Saturn extends Planet(5.688e+26, 6.0268e7) 24 | case Uranus extends Planet(8.686e+25, 2.5559e7) 25 | case Neptune extends Planet(1.024e+26, 2.4746e7) 26 | } 27 | 28 | def test: Unit = { 29 | 30 | val emptyList = ListEnum.Empty 31 | val list = ListEnum.Cons(1, ListEnum.Cons(2, ListEnum.Cons(3, ListEnum.Empty))) 32 | println(emptyList) 33 | println(s"${list}\n") 34 | 35 | def calculateEarthWeightOnPlanets(earthWeight: Double) = { 36 | val mass = earthWeight/Planet.Earth.surfaceGravity 37 | for (p <- Planet.values) 38 | println(s"Your weight on $p is ${p.surfaceWeight(mass)}") 39 | } 40 | 41 | calculateEarthWeightOnPlanets(80) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /example-project/src/main/scala/ImpliedInstances.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import scala.util.{Success, Try} 4 | 5 | /** 6 | * Implied Instances: 7 | * - https://dotty.epfl.ch/docs/reference/contextual/instance-defs.html 8 | */ 9 | object ImpliedInstances { 10 | 11 | sealed trait StringParser[A] { 12 | def parse(s: String): Try[A] 13 | } 14 | 15 | object StringParser { 16 | 17 | def apply[A](using parser: StringParser[A]): StringParser[A] = parser 18 | 19 | private def baseParser[A](f: String ⇒ Try[A]): StringParser[A] = new StringParser[A] { 20 | override def parse(s: String): Try[A] = f(s) 21 | } 22 | 23 | given stringParser as StringParser[String] = baseParser(Success(_)) 24 | given intParser as StringParser[Int] = baseParser(s ⇒ Try(s.toInt)) 25 | 26 | given optionParser[A](using parser: => StringParser[A]) as StringParser[Option[A]] = new StringParser[Option[A]] { 27 | override def parse(s: String): Try[Option[A]] = s match { 28 | case "" ⇒ Success(None) // implicit parser not used. 29 | case str ⇒ parser.parse(str).map(x ⇒ Some(x)) // implicit parser is evaluated at here 30 | } 31 | } 32 | } 33 | 34 | def test: Unit = { 35 | println(implicitly[StringParser[Option[Int]]].parse("21")) 36 | println(implicitly[StringParser[Option[Int]]].parse("")) 37 | println(implicitly[StringParser[Option[Int]]].parse("21a")) 38 | 39 | println(implicitly[StringParser[Option[Int]]](StringParser.optionParser[Int]).parse("42")) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example-project/src/main/scala/IntersectionTypes.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Intersection Types: https://dotty.epfl.ch/docs/reference/new-types/intersection-types.html 5 | */ 6 | object IntersectionTypes { 7 | 8 | sealed trait X { 9 | def x: Double 10 | def tpe: X 11 | } 12 | 13 | sealed trait Y { 14 | def y: Double 15 | def tpe: Y 16 | } 17 | 18 | type P = Y & X 19 | type PP = X & Y 20 | 21 | final case class Point(x: Double, y: Double) extends X with Y { 22 | override def tpe: X & Y = ??? 23 | } 24 | 25 | def test: Unit = { 26 | 27 | def euclideanDistance(p1: X & Y, p2: X & Y) = { 28 | Math.sqrt(Math.pow(p2.y - p1.y, 2) + Math.pow(p2.x - p1.x, 2)) 29 | } 30 | 31 | val p1: P = Point(3, 4) 32 | val p2: PP = Point(6, 8) 33 | println(euclideanDistance(p1, p2)) 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example-project/src/main/scala/Main.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | object Main { 4 | 5 | def main(args: Array[String]): Unit = { 6 | 7 | runExample("Trait Params")(TraitParams.test) 8 | 9 | runExample("Enum Types")(EnumTypes.test) 10 | 11 | runExample("Context Queries")(ContextQueries.test) 12 | 13 | runExample("Implied Instances")(ImpliedInstances.test) 14 | 15 | runExample("Conversion")(Conversion.test) 16 | 17 | runExample("Union Types")(UnionTypes.test) 18 | 19 | runExample("Intersection Types")(IntersectionTypes.test) 20 | 21 | runExample("Type Lambda")(TypeLambdas.test) 22 | 23 | runExample("Multiversal Equality")(MultiversalEquality.test) 24 | 25 | runExample("Named Type Arguments")(NamedTypeArguments.test) 26 | 27 | runExample("Auto Param Tupling")(AutoParamTupling.test) 28 | 29 | runExample("Structural Types")(StructuralTypes.test) 30 | 31 | runExample("Pattern Matching")(PatternMatching.test) 32 | 33 | } 34 | 35 | private def runExample(name: String)(f: => Unit) = { 36 | println(Console.MAGENTA + s"$name example:" + Console.RESET) 37 | f 38 | println() 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /example-project/src/main/scala/MultiversalEquality.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import scala.language.strictEquality 4 | 5 | /** 6 | * Multiversal Equality: https://dotty.epfl.ch/docs/reference/contextual/multiversal-equality.html 7 | * scala.Eq definition: https://github.com/lampepfl/dotty/blob/master/library/src/scala/Eql.scala 8 | */ 9 | object MultiversalEquality { 10 | 11 | def test: Unit = { 12 | 13 | // Values of types Int and String cannot be compared with == or !=, 14 | // unless we add the derived delegate instance like: 15 | given Eql[Int, String] = Eql.derived 16 | println(3 == "3") 17 | 18 | // By default, all numbers are comparable, because of; 19 | // implicit def eqlNumber: Eql[Number, Number] = derived 20 | println(3 == 5.1) 21 | 22 | // By default, all Sequences are comparable, because of; 23 | // implicit def eqlSeq[T, U](implicit eq: Eql[T, U]): Eql[GenSeq[T], GenSeq[U]] = derived 24 | println(List(1, 2) == Vector(1, 2)) 25 | 26 | class A(a: Int) 27 | class B(b: Int) 28 | 29 | val a = new A(4) 30 | val b = new B(4) 31 | 32 | // scala.language.strictEquality is enabled, therefore we need some extra delegate instances 33 | // to compare instances of A and B. 34 | given Eql[A, B] = Eql.derived 35 | given Eql[B, A] = Eql.derived 36 | 37 | println(a != b) 38 | println(b == a) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example-project/src/main/scala/NamedTypeArguments.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Named Type Arguments: https://dotty.epfl.ch/docs/reference/other-new-features/named-typeargs.html 5 | */ 6 | object NamedTypeArguments { 7 | 8 | trait Functor[F[_]] { 9 | def map[A, B](fa: F[A])(f: A => B): F[B] 10 | } 11 | 12 | implicit object listFunctor extends Functor[List] { 13 | override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) 14 | } 15 | 16 | def test: Unit = { 17 | 18 | def fmap[F[_], A, B](fa: F[A])(f: A => B)(implicit F: Functor[F]): F[B] = F.map(fa)(f) 19 | 20 | val result: List[Int] = fmap[F = List, A = Int, B = Int](List(1,2,3))(i => i + 1) 21 | 22 | println(result) 23 | 24 | // val notCompile = fmap[F = List, B = String](List(1,2,3))(i => i + 1) 25 | 26 | val compile: List[String] = fmap[F = List, B = String](List(1,2,3))(i => (i + 1).toString) 27 | 28 | println(compile) 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /example-project/src/main/scala/StructuralTypes.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Structural Types: https://dotty.epfl.ch/docs/reference/changed-features/structural-types.html 5 | */ 6 | object StructuralTypes { 7 | 8 | case class Record(elems: (String, Any)*) extends Selectable { 9 | def selectDynamic(name: String): Any = elems.find(_._1 == name).get._2 10 | } 11 | 12 | type Person = Record { 13 | val name: String 14 | val age: Int 15 | } 16 | 17 | val person = Record("name" -> "Emma", "age" -> 42, "salary" -> 320L).asInstanceOf[Person] 18 | 19 | val invalidPerson = Record("name" -> "John", "salary" -> 42).asInstanceOf[Person] 20 | 21 | def test: Unit = { 22 | println(person.name) 23 | println(person.age) 24 | 25 | println(invalidPerson.name) 26 | // age field is java.util.NoSuchElementException: None.get 27 | //println(invalidPerson.age) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example-project/src/main/scala/TraitParams.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Trait Parameters: https://dotty.epfl.ch/docs/reference/other-new-features/trait-parameters.html 5 | */ 6 | object TraitParams { 7 | 8 | trait Base(val msg: String) 9 | class A extends Base("Hello") 10 | class B extends Base("Dotty!") 11 | 12 | // Union types only exist in Dotty, so there's no chance that this will accidentally be compiled with Scala 2 13 | private def printMessages(msgs: (A | B)*) = println(msgs.map(_.msg).mkString(" ")) 14 | 15 | def test: Unit = { 16 | 17 | printMessages(new A, new B) 18 | 19 | // Sanity check the classpath: this won't run if the dotty jar is not present. 20 | val x: Int => Int = z => z 21 | x(1) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example-project/src/main/scala/TypeLambdas.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Type Lambdas: https://dotty.epfl.ch/docs/reference/new-types/type-lambdas.html 5 | */ 6 | object TypeLambdas { 7 | 8 | type T[+X, Y] = Map[Y, X] 9 | 10 | type Tuple = [X] =>> (X, X) 11 | 12 | def test: Unit = { 13 | 14 | val m: T[String, Int] = Map(1 -> "1") 15 | println(m) 16 | 17 | val tuple: Tuple[String] = ("a", "b") 18 | println(tuple) 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /example-project/src/main/scala/UnionTypes.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | /** 4 | * Union Types: https://dotty.epfl.ch/docs/reference/new-types/union-types.html 5 | */ 6 | object UnionTypes { 7 | 8 | sealed trait Division 9 | final case class DivisionByZero(msg: String) extends Division 10 | final case class Success(double: Double) extends Division 11 | 12 | // You can create type aliases for your union types (sum types). 13 | type DivisionResult = DivisionByZero | Success 14 | 15 | sealed trait List[+A] 16 | final case class Empty() extends List[Nothing] 17 | final case class Cons[+A](h: A, t: List[A]) extends List[A] 18 | 19 | private def safeDivide(a: Double, b: Double): DivisionResult = { 20 | if (b == 0) DivisionByZero("DivisionByZeroException") else Success(a / b) 21 | } 22 | 23 | private def either(division: Division) = division match { 24 | case DivisionByZero(m) => Left(m) 25 | case Success(d) => Right(d) 26 | } 27 | 28 | def test: Unit = { 29 | 30 | val divisionResultSuccess: DivisionResult = safeDivide(4, 2) 31 | 32 | // commutative 33 | val divisionResultFailure: Success | DivisionByZero = safeDivide(4, 0) 34 | 35 | // calling `either` function with union typed value. 36 | println(either(divisionResultSuccess)) 37 | 38 | // calling `either` function with union typed value. 39 | println(either(divisionResultFailure)) 40 | 41 | val list: Cons[Int] | Empty = Cons(1, Cons(2, Cons(3, Empty()))) 42 | val emptyList: Empty | Cons[Any] = Empty() 43 | println(list) 44 | println(emptyList) 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /project/ExampleProject.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import sbt.Keys._ 3 | 4 | object ExampleProject { 5 | import Protoplugin.Keys._ 6 | 7 | val `example-project` = 8 | project.in(file("example-project")) 9 | .settings(Protoplugin.Settings ++ Seq( 10 | name := "scala3doc-example-project", 11 | description := "Example SBT project that is documented using Scala3doc", 12 | version := "0.1.0-SNAPSHOT", 13 | scalaVersion := "0.27.0-RC1", 14 | 15 | scala3docOptions ++= Seq("--name", "example-project"), 16 | Compile / doc / target := file("output/example-project"), 17 | ): _*) 18 | } 19 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.4.0-M2 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1") -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin: -------------------------------------------------------------------------------- 1 | dotty.dokka.DottyDokkaPlugin -------------------------------------------------------------------------------- /src/main/resources/dotty_res/fonts/dotty-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/src/main/resources/dotty_res/fonts/dotty-icons.ttf -------------------------------------------------------------------------------- /src/main/resources/dotty_res/fonts/dotty-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lampepfl/scala3doc/b892437cf1437efe6d6352c761d416bcad564b4a/src/main/resources/dotty_res/fonts/dotty-icons.woff -------------------------------------------------------------------------------- /src/main/resources/dotty_res/hljs/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2006, Ivan Sagalaev. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/common/component.js: -------------------------------------------------------------------------------- 1 | class Component { 2 | constructor(props = {}) { 3 | this.props = props; 4 | this.prevProps = {}; 5 | this.state = {}; 6 | } 7 | 8 | setState(nextState, cb = () => {}) { 9 | const prevState = { ...this.state }; 10 | if (typeof nextState === "function") { 11 | this.state = { 12 | ...this.state, 13 | ...nextState(this.state), 14 | }; 15 | } else { 16 | this.state = { 17 | ...this.state, 18 | ...nextState, 19 | }; 20 | } 21 | 22 | cb(); 23 | 24 | if (this.render) { 25 | this.render(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/common/utils.js: -------------------------------------------------------------------------------- 1 | const findRef = (searchBy, element = document) => 2 | element.querySelector(searchBy); 3 | 4 | const findRefs = (searchBy, element = document) => 5 | element ? [...element.querySelectorAll(searchBy)] : []; 6 | 7 | const withEvent = (element, listener, callback) => { 8 | element && element.addEventListener(listener, callback); 9 | return () => element && element.removeEventListener(listener, callback); 10 | }; 11 | 12 | const init = (cb) => window.addEventListener("DOMContentLoaded", cb); 13 | 14 | const attachDOM = (element, html) => { 15 | if (element) { 16 | element.innerHTML = htmlToString(html); 17 | } 18 | }; 19 | 20 | const startsWith = (str, character) => str.charAt(0) === character; 21 | 22 | const htmlToString = (html) => { 23 | if (Array.isArray(html)) { 24 | return html.join(""); 25 | } 26 | return html; 27 | }; 28 | 29 | const attachListeners = (elementsRefs, type, callback) => 30 | elementsRefs.map((elRef) => withEvent(elRef, type, callback)); 31 | 32 | const getElementTextContent = (element) => (element ? element.textContent : ""); 33 | 34 | const getElementDescription = (elementRef) => 35 | findRef(".documentableBrief", elementRef); 36 | 37 | const getElementNameRef = (elementRef) => 38 | findRef(".documentableName", elementRef); 39 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/components/FilterBar.js: -------------------------------------------------------------------------------- 1 | class FilterBar extends Component { 2 | constructor(props) { 3 | super(props); 4 | 5 | this.refs = { 6 | elements: findRefs(".documentableElement"), 7 | filterBar: findRef(".documentableFilter"), 8 | }; 9 | 10 | this.state = { 11 | filter: new Filter("", {}, this.refs.elements, true), 12 | isVisible: false, 13 | }; 14 | 15 | this.inputComp = new Input({ onInputChange: this.onInputChange }); 16 | this.listComp = new DocumentableList({ 17 | filter: this.state.filter, 18 | }); 19 | this.filterGroupComp = new FilterGroup({ 20 | filter: this.state.filter, 21 | onFilterToggle: this.onFilterToggle, 22 | onGroupSelectChange: this.onGroupSelectChange, 23 | onFilterVisibilityChange: this.onFilterVisibilityChange, 24 | }); 25 | 26 | this.render(); 27 | } 28 | 29 | onInputChange = (value) => { 30 | this.setState((prevState) => ({ 31 | filter: prevState.filter.onInputValueChange(value), 32 | })); 33 | }; 34 | 35 | onGroupSelectChange = (key, isActive) => { 36 | this.setState((prevState) => ({ 37 | filter: prevState.filter.onGroupSelectionChange(key, isActive), 38 | })); 39 | }; 40 | 41 | onFilterVisibilityChange = () => { 42 | this.setState((prevState) => ({ isVisible: !prevState.isVisible })); 43 | }; 44 | 45 | onFilterToggle = (key, value) => { 46 | this.setState((prevState) => ({ 47 | filter: prevState.filter.onFilterToggle(key, value), 48 | })); 49 | }; 50 | 51 | render() { 52 | if (this.refs.filterBar) { 53 | if (this.state.isVisible) { 54 | this.refs.filterBar.classList.add("active"); 55 | } else { 56 | this.refs.filterBar.classList.remove("active"); 57 | } 58 | } 59 | 60 | this.listComp.render({ filter: this.state.filter }); 61 | this.filterGroupComp.render({ filter: this.state.filter }); 62 | } 63 | } 64 | 65 | init(() => new FilterBar()); 66 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/components/Input.js: -------------------------------------------------------------------------------- 1 | class Input extends Component { 2 | constructor(props) { 3 | super(props); 4 | 5 | this.inputRef = findRef(".filterableInput"); 6 | this.onChangeFn = withEvent(this.inputRef, "input", this.onInputChange); 7 | } 8 | 9 | onInputChange = ({ currentTarget: { value } }) => { 10 | this.props.onInputChange(value); 11 | }; 12 | 13 | componentWillUnmount() { 14 | if (this.onChangeFn) { 15 | this.onChangeFn(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/diagram.js: -------------------------------------------------------------------------------- 1 | $("#inheritance-diagram").ready(function() { 2 | if ($("svg#graph").children().length == 0) { 3 | var dotNode = document.querySelector("#dot") 4 | if (dotNode){ 5 | var svg = d3.select("#graph"); 6 | var inner = svg.append("g"); 7 | 8 | // Set up zoom support 9 | var zoom = d3.zoom() 10 | .on("zoom", function({transform}) { 11 | inner.attr("transform", transform); 12 | }); 13 | svg.call(zoom); 14 | 15 | var render = new dagreD3.render(); 16 | var g = graphlibDot.read(dotNode.text); 17 | g.graph().rankDir = 'BT'; 18 | g.nodes().forEach(function (v) { 19 | g.setNode(v, { 20 | labelType: "html", 21 | label: g.node(v).label, 22 | style: g.node(v).style 23 | }); 24 | }); 25 | g.edges().forEach(function(v) { 26 | g.setEdge(v, { 27 | arrowhead: "vee" 28 | }); 29 | }); 30 | render(inner, g); 31 | } 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/scripts/ux.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("DOMContentLoaded", () => { 2 | var toggler = document.getElementById("leftToggler"); 3 | if (toggler) { 4 | toggler.onclick = function () { 5 | document.getElementById("leftColumn").classList.toggle("open"); 6 | }; 7 | } 8 | var logo = document.getElementById("logo"); 9 | if (logo) { 10 | logo.onclick = function() { 11 | window.location = pathToRoot; // global variable pathToRoot is created by the html renderer 12 | }; 13 | } 14 | hljs.registerLanguage("scala", highlightDotty); 15 | hljs.registerAliases(["dotty", "scala3"], "scala"); 16 | hljs.initHighlighting(); 17 | }); 18 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/styles/diagram.css: -------------------------------------------------------------------------------- 1 | .node { 2 | stroke: #333; 3 | stroke-width: 2.5px; 4 | fill: white; 5 | } 6 | 7 | .edgeLabel { 8 | fill: white; 9 | } 10 | 11 | .edgePath { 12 | stroke: #333; 13 | stroke-width: 1.5px; 14 | fill: #333; 15 | } 16 | 17 | #graph { 18 | width: 100%; 19 | height: 80%; 20 | } 21 | 22 | .diagram-class a { 23 | text-decoration: underline; 24 | color: #FFF; 25 | } 26 | 27 | .diagram-class a:hover { 28 | color: #BFE7F3; 29 | } 30 | 31 | .diagram-class span[data-unresolved-link] { 32 | color: #FFF; 33 | } -------------------------------------------------------------------------------- /src/main/resources/dotty_res/styles/dotty-icons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'dotty-icons'; 3 | src: 4 | url('../fonts/dotty-icons.woff?kefi7x') format('woff'), 5 | url('../fonts/dotty-icons.ttf?kefi7x') format('truetype'); 6 | font-weight: normal; 7 | font-style: normal; 8 | font-display: block; 9 | } 10 | 11 | [class^="icon-"], [class*=" icon-"] { 12 | /* use !important to prevent issues with browser extensions that change fonts */ 13 | font-family: 'dotty-icons' !important; 14 | speak: never; 15 | font-style: normal; 16 | font-weight: normal; 17 | font-variant: normal; 18 | text-transform: none; 19 | line-height: 1; 20 | 21 | /* Better Font Rendering */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | .icon-git:before { 27 | content: "\e908"; 28 | } 29 | .icon-clear:before { 30 | content: "\e900"; 31 | } 32 | .icon-content_copy:before { 33 | content: "\e90b"; 34 | } 35 | .icon-create:before { 36 | content: "\e907"; 37 | } 38 | .icon-link:before { 39 | content: "\e901"; 40 | } 41 | .icon-vertical_align_top:before { 42 | content: "\e902"; 43 | } 44 | .icon-keyboard_arrow_down:before { 45 | content: "\e903"; 46 | } 47 | .icon-keyboard_arrow_right:before { 48 | content: "\e904"; 49 | } 50 | .icon-keyboard_arrow_up:before { 51 | content: "\e905"; 52 | } 53 | .icon-menu:before { 54 | content: "\e90a"; 55 | } 56 | .icon-check_circle:before { 57 | content: "\e909"; 58 | } 59 | .icon-search:before { 60 | content: "\e906"; 61 | } 62 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/styles/nord-light.css: -------------------------------------------------------------------------------- 1 | /* Theme inspired by nordtheme. The colors have been darkened to work on light backgrounds. */ 2 | pre, .hljs { 3 | background: #F4F5FA; 4 | color: #4C566A; 5 | } 6 | 7 | .hljs-comment { 8 | color: #90A1C1; 9 | } 10 | .hljs-doctag { 11 | color: #4B6B92; 12 | font-weight: 500; 13 | } 14 | .hljs-emphasis { 15 | font-style: italic; 16 | } 17 | .hljs-bold { 18 | font-weight: bold; 19 | } 20 | 21 | .hljs-meta { 22 | color: #F9A600; 23 | font-weight: 500; 24 | } 25 | .hljs-subst { 26 | color: #F9A600; 27 | } 28 | .hljs-title { 29 | color: #2B8FAC; 30 | font-weight: 500; 31 | } 32 | .hljs-type { 33 | color: #1E7C7A; 34 | } 35 | .hljs-keyword { 36 | color: #2E6BB8; 37 | font-weight: 500; 38 | } 39 | .hljs-string { 40 | color: #6AA13B; 41 | } 42 | .hljs-built_in, .hljs-number, .hljs-literal { 43 | color: #9D5490; 44 | } 45 | -------------------------------------------------------------------------------- /src/main/resources/dotty_res/styles/search-bar.css: -------------------------------------------------------------------------------- 1 | /* Global search */ 2 | .search-content { 3 | padding: 0; 4 | margin: var(--content-padding); 5 | position: absolute; 6 | top: 0; 7 | right: 0; 8 | z-index: 5; 9 | background: none; 10 | } 11 | 12 | /* button */ 13 | .search button { 14 | background: #ED3522; 15 | fill: #fff; 16 | cursor: pointer; 17 | border: none; 18 | padding: 9px; 19 | border-radius: 24px; 20 | box-shadow: 0 0 16px #F27264; 21 | } 22 | .search button:hover { 23 | fill: #F27264; 24 | } 25 | 26 | /* popup */ 27 | .popup-wrapper { 28 | box-shadow: 0 0 10px var(--border-light) !important; 29 | border: 2px solid var(--border-light) !important; 30 | font-family: var(--mono-font) !important; 31 | width: calc(100% - var(--side-width) - 84px); 32 | left: calc(var(--side-width) + 42px) !important; 33 | } 34 | .popup-wrapper .indented { 35 | text-indent: 1.5em !important; 36 | } 37 | .popup-wrapper .disabled { 38 | color: var(--inactive-fg) !important; 39 | font-weight: 500 !important; 40 | } 41 | .action_def:hover, .action_def.hover_a79 { 42 | color: var(--selected-fg); 43 | background: var(--selected-bg) !important; 44 | font-weight: 500; 45 | } 46 | .action_def .template-description { 47 | margin-left: 2rem; 48 | font-style: italic; 49 | } 50 | 51 | /* Landscape phones, portait tablets */ 52 | @media(max-width: 768px) { 53 | .popup-wrapper { 54 | width: calc(100% - 48px); 55 | left: 24px !important; 56 | } 57 | } 58 | 59 | /* Portrait phones */ 60 | @media(max-width: 576px) { 61 | .search button { 62 | background: none; 63 | fill: var(--icon-color); 64 | cursor: pointer; 65 | border: none; 66 | padding: 0; 67 | box-shadow: none; 68 | margin-top: 2px; 69 | } 70 | .search button:hover { 71 | fill: var(--link-hover-fg); 72 | } 73 | .search-content { 74 | margin: 0 !important; 75 | top: 9px !important; 76 | right: 12px !important; 77 | } 78 | .popup-wrapper { 79 | width: 100%; 80 | left: 0 !important; 81 | top: 36px !important; 82 | } 83 | /* Allow to scroll horizontally in the search results, which is useful on small screens */ 84 | .popup-wrapper div.ReactVirtualized__Grid__innerScrollContainer { 85 | overflow: auto !important; 86 | } 87 | .popup-wrapper div.ReactVirtualized__Grid__innerScrollContainer > div { 88 | min-width: 100%; 89 | width: auto !important; 90 | } 91 | } -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/DottyDokkaConfig.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka._ 4 | import org.jetbrains.dokka.DokkaSourceSetImpl 5 | import java.io.File 6 | import java.util.{ List => JList, Map => JMap} 7 | import collection.JavaConverters._ 8 | 9 | case class DottyDokkaConfig(docConfiguration: DocConfiguration) extends DokkaConfiguration: 10 | override def getOutputDir: File = docConfiguration.args.output 11 | override def getCacheRoot: File = null 12 | override def getOfflineMode: Boolean = false 13 | override def getFailOnWarning: Boolean = false 14 | override def getSourceSets: JList[DokkaConfiguration.DokkaSourceSet] = List(mkSourceSet).asJava 15 | override def getModules: JList[DokkaConfiguration.DokkaModuleDescription] = List().asJava 16 | override def getPluginsClasspath: JList[File] = Nil.asJava 17 | override def getModuleName(): String = "ModuleName" 18 | override def getModuleVersion(): String = "" 19 | 20 | private object OurConfig extends DokkaConfiguration.PluginConfiguration: 21 | override def getFqPluginName = "ExternalDocsTooKey" 22 | override def getSerializationFormat: DokkaConfiguration$SerializationFormat = DokkaConfiguration$SerializationFormat.JSON 23 | override def getValues: String = docConfiguration.args.docsRoot.getOrElse("") 24 | 25 | override def getPluginsConfiguration: JList[DokkaConfiguration.PluginConfiguration] = List(OurConfig).asJava 26 | 27 | def mkSourceSet: DokkaConfiguration.DokkaSourceSet = 28 | val sourceLinks:Set[SourceLinkDefinitionImpl] = docConfiguration.args.sourceLinks.map(SourceLinkDefinitionImpl.Companion.parseSourceLinkDefinition(_)).toSet 29 | new DokkaSourceSetImpl( 30 | /*displayName=*/ docConfiguration.args.name, 31 | /*sourceSetID=*/ new DokkaSourceSetID(docConfiguration.args.name, "main"), 32 | /*classpath=*/ Nil.asJava, 33 | /*sourceRoots=*/ Set().asJava, 34 | /*dependentSourceSets=*/ Set().asJava, 35 | /*samples=*/ Set().asJava, 36 | /*includes=*/ Set().asJava, 37 | /*includeNonPublic=*/ true, 38 | /*reportUndocumented=*/ false, /* changed because of exception in reportUndocumentedTransformer - there's 'when' which doesnt match because it contains only KotlinVisbility cases */ 39 | /*skipEmptyPackages=*/ false, // Now all our packages are empty from dokka perspective 40 | /*skipDeprecated=*/ true, 41 | /*jdkVersion=*/ 8, 42 | /*sourceLinks=*/ sourceLinks.asJava, 43 | /*perPackageOptions=*/ Nil.asJava, 44 | /*externalDocumentationLinks=*/ Set().asJava, 45 | /*languageVersion=*/ null, 46 | /*apiVersion=*/ null, 47 | /*noStdlibLink=*/ true, 48 | /*noJdkLink=*/ true, 49 | /*suppressedFiles=*/ Set().asJava, 50 | /*suppressedFiles=*/ Platform.jvm 51 | ).asInstanceOf[DokkaConfiguration.DokkaSourceSet] // Why I do need to cast here? Kotlin magic? 52 | 53 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/ScalaModuleCreator.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.{ DokkaConfiguration$DokkaSourceSet => DokkaSourceSet } 4 | import com.virtuslab.dokka.site.JavaSourceToDocumentableTranslator 5 | import com.virtuslab.dokka.site.SourceSetWrapper 6 | import org.jetbrains.dokka.plugability.DokkaContext 7 | import org.jetbrains.dokka.model.properties.PropertyContainer 8 | 9 | import dotty.dokka.tasty.{DokkaTastyInspector, SbtDokkaTastyInspector} 10 | import org.jetbrains.dokka.pages._ 11 | import dotty.dokka.model.api._ 12 | import org.jetbrains.dokka.model._ 13 | import org.jetbrains.dokka.links.DRI 14 | import java.util.{List => JList} 15 | import org.jetbrains.dokka.base.parsers.MarkdownParser 16 | import collection.JavaConverters._ 17 | 18 | object ScalaModuleProvider extends JavaSourceToDocumentableTranslator: 19 | override def process(rawSourceSet: DokkaSourceSet, cxt: DokkaContext) = 20 | val sourceSet = SourceSetWrapper(rawSourceSet) 21 | cxt.getConfiguration match 22 | case dottyConfig: DottyDokkaConfig => 23 | val result = dottyConfig.docConfiguration match { 24 | case DocConfiguration.Standalone(args, tastyFiles) => 25 | // TODO use it to resolve link logic 26 | val inspector = DokkaTastyInspector(sourceSet, new MarkdownParser(_ => null), dottyConfig) 27 | inspector.inspect(args.classpath, tastyFiles) 28 | inspector.result() 29 | case DocConfiguration.Sbt(args, tastyFiles, rootCtx) => 30 | val inspector = 31 | SbtDokkaTastyInspector( 32 | sourceSet, 33 | // new MarkdownParser(null, null, cxt.getLogger), 34 | dottyConfig, 35 | tastyFiles, 36 | rootCtx, 37 | ) 38 | inspector.run() 39 | } 40 | 41 | def flattenMember(m: Member): Seq[(DRI, Member)] = (m.dri -> m) +: m.allMembers.flatMap(flattenMember) 42 | 43 | new DModule( 44 | sourceSet.getSourceSet.getDisplayName, 45 | result.asJava, 46 | Map().asJava, 47 | null, 48 | sourceSet.toSet, 49 | PropertyContainer.Companion.empty() plus ModuleExtension(result.flatMap(flattenMember).toMap) 50 | ) 51 | case _ => 52 | ??? 53 | 54 | object EmptyModuleProvider extends JavaSourceToDocumentableTranslator: 55 | override def process(sourceSet: DokkaSourceSet, context: DokkaContext) = 56 | DModule("", Nil.asJava, Map.empty.asJava, null, Set(sourceSet).asJava, PropertyContainer.Companion.empty()) -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/model/extras.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.DokkaConfiguration$DokkaSourceSet 4 | import org.jetbrains.dokka.links._ 5 | import org.jetbrains.dokka.model.{Projection => JProjection} 6 | import org.jetbrains.dokka.model._ 7 | import org.jetbrains.dokka.pages._ 8 | import collection.JavaConverters._ 9 | import org.jetbrains.dokka.links._ 10 | import org.jetbrains.dokka.model.doc._ 11 | import org.jetbrains.dokka.model.properties._ 12 | import java.util.{List => JList, Set => JSet} 13 | import dotty.dokka.model.api._ 14 | 15 | case class ModuleExtension(driMap: Map[DRI, Member]) extends ExtraProperty[DModule]: 16 | override def getKey = ModuleExtension 17 | 18 | object ModuleExtension extends BaseKey[DModule, ModuleExtension] 19 | 20 | case class MethodExtension(parametersListSizes: Seq[Int]) extends ExtraProperty[DFunction]: 21 | override def getKey = MethodExtension 22 | 23 | object MethodExtension extends BaseKey[DFunction, MethodExtension] 24 | 25 | case class ParameterExtension(isExtendedSymbol: Boolean, isGrouped: Boolean) extends ExtraProperty[DParameter]: 26 | override def getKey = ParameterExtension 27 | 28 | object ParameterExtension extends BaseKey[DParameter, ParameterExtension] 29 | 30 | case class ClasslikeExtension( 31 | constructor: Option[DFunction], // will be replaced by signature 32 | companion: Option[DRI], // moved to kind? 33 | ) extends ExtraProperty[DClasslike]: 34 | override def getKey = ClasslikeExtension 35 | 36 | object ClasslikeExtension extends BaseKey[DClasslike, ClasslikeExtension] 37 | 38 | 39 | case class SourceLinks( 40 | links: Map[DokkaConfiguration$DokkaSourceSet, String] 41 | ) extends ExtraProperty[Documentable]: 42 | override def getKey = SourceLinks 43 | 44 | object SourceLinks extends BaseKey[Documentable, SourceLinks] 45 | 46 | // case class ImplicitConversions(val conversions: List[ImplicitConversion]) extends ExtraProperty[WithScope]: 47 | // override def getKey = ImplicitConversions 48 | 49 | // object ImplicitConversions extends BaseKey[WithScope, ImplicitConversions] 50 | 51 | 52 | case class IsInherited(flag: Boolean) extends ExtraProperty[Documentable]: 53 | override def getKey = IsInherited 54 | 55 | object IsInherited extends BaseKey[Documentable, IsInherited] 56 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/preprocessors/ScalaEmbeddedResourceApppender.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.transformers.pages.{PageTransformer} 4 | import org.jetbrains.dokka.pages.{RootPageNode, PageNode} 5 | import scala.jdk.CollectionConverters._ 6 | 7 | class ScalaEmbeddedResourceAppender extends PageTransformer { 8 | override def invoke(input: RootPageNode): RootPageNode = 9 | input.transformContentPagesTree(page => 10 | page.modified( 11 | page.getName, 12 | page.getContent, 13 | page.getDri, 14 | // Remove default CSS and add our own 15 | (page.getEmbeddedResources.asScala 16 | .filterNot(_.endsWith(".css")) ++ Seq( 17 | "styles/nord-light.css", 18 | "styles/scalastyle.css", 19 | "styles/dotty-icons.css", 20 | "styles/diagram.css", 21 | "styles/filter-bar.css", 22 | "styles/search-bar.css", 23 | "https://code.jquery.com/jquery-3.5.1.min.js", 24 | "https://d3js.org/d3.v6.min.js", 25 | "https://cdn.jsdelivr.net/npm/graphlib-dot@0.6.2/dist/graphlib-dot.min.js", 26 | "https://cdnjs.cloudflare.com/ajax/libs/dagre-d3/0.6.1/dagre-d3.min.js", 27 | "scripts/diagram.js", 28 | "hljs/highlight.pack.js", 29 | "scripts/hljs-scala3.js", 30 | "scripts/ux.js", 31 | "scripts/common/component.js", 32 | "scripts/common/utils.js", 33 | "scripts/components/FilterBar.js", 34 | "scripts/components/DocumentableList.js", 35 | "scripts/components/Input.js", 36 | "scripts/components/FilterGroup.js", 37 | "scripts/components/Filter.js", 38 | "scripts/data.js", 39 | )).asJava, 40 | page.getChildren 41 | ) 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/preprocessors/ScalaResourceInstaller.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.transformers.pages.{PageTransformer} 4 | import org.jetbrains.dokka.pages.{RootPageNode, RendererSpecificResourcePage, RenderingStrategy$Copy, PageNode, RenderingStrategy$Write} 5 | import scala.jdk.CollectionConverters._ 6 | import com.fasterxml.jackson.databind.ObjectMapper 7 | import dotty.dokka.translators.FilterAttributes 8 | 9 | class ScalaResourceInstaller extends PageTransformer: 10 | private def dottyRes(resourceName: String) = 11 | new RendererSpecificResourcePage(resourceName, java.util.ArrayList(), RenderingStrategy$Copy(s"/dotty_res/$resourceName")) 12 | 13 | override def invoke(input: RootPageNode): RootPageNode = 14 | val newResources = input.getChildren.asScala ++ Seq("fonts", "images", "styles", "scripts", "hljs").map(dottyRes) ++ Seq(dynamicJsData) 15 | input.modified(input.getName, newResources.asJava) 16 | 17 | private def dynamicJsData = 18 | // If data at any point will become more complex we should use a proper 19 | val data: Map[String, Map[String, String]] = Map("filterDefaults" -> FilterAttributes.defaultValues) 20 | val str = new ObjectMapper().writeValueAsString(data.transform((_, v) => v.asJava).asJava) 21 | 22 | new RendererSpecificResourcePage("scripts/data.js", java.util.ArrayList(), RenderingStrategy$Write(s"var scala3DocData = $str")) 23 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/tasty/PackageSupport.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty 2 | 3 | import org.jetbrains.dokka.model._ 4 | import org.jetbrains.dokka.links._ 5 | import org.jetbrains.dokka.model.properties._ 6 | import org.jetbrains.dokka.model.doc.DocumentationNode 7 | import dotty.dokka._ 8 | import dotty.dokka.model.api.CompositeMemberExtension 9 | 10 | import collection.JavaConverters._ 11 | 12 | trait PackageSupport: 13 | self: TastyParser => 14 | import reflect._ 15 | 16 | def parsePackage(pck: PackageClause): DPackage = { 17 | val name = extractPackageName(pck.pid.show) 18 | val documentation = pck.symbol.documentation 19 | DPackage( 20 | new DRI(name, null, null, PointingToDeclaration.INSTANCE, null), 21 | Nil.asJava, 22 | Nil.asJava, 23 | Nil.asJava, 24 | Nil.asJava, 25 | documentation.asJava, 26 | null, 27 | sourceSet.toSet, 28 | PropertyContainer.Companion.empty() 29 | ) 30 | } 31 | 32 | def parsePackageObject(pckObj: ClassDef): DPackage = 33 | parseClasslike(pckObj) match { 34 | case clazz: DClass => 35 | DPackage( 36 | new DRI(pckObj.symbol.dri.getPackageName, null, null, PointingToDeclaration.INSTANCE, null), 37 | clazz.getFunctions, 38 | clazz.getProperties, 39 | Nil.asJava, 40 | Nil.asJava, 41 | pckObj.symbol.documentation.asJava, 42 | null, 43 | sourceSet.toSet, 44 | PropertyContainer.Companion.empty() 45 | .plus(clazz.get(CompositeMemberExtension)) 46 | ) 47 | } 48 | 49 | 50 | private def extractPackageName(pidShowNoColor: String): String = { 51 | val pidSplit = pidShowNoColor.split("\\.") 52 | pidSplit.mkString("",".","") 53 | } 54 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/tasty/comments/BaseConverter.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | import scala.jdk.CollectionConverters._ 4 | 5 | import org.jetbrains.dokka.model.{doc => dkkd} 6 | 7 | /** Quick'n'dirty class to remove some code duplication */ 8 | trait BaseConverter { 9 | 10 | protected def withParsedQuery(queryStr: String)(thunk: Query => dkkd.DocTag): dkkd.DocTag = { 11 | QueryParser(queryStr).tryReadQuery() match { 12 | case Left(err) => 13 | val msg = err.getMessage 14 | // TODO: for better experience we should show source location here 15 | println("WARN: " + msg) 16 | dkkd.A(List(dkk.text(queryStr)).asJava, Map("title" -> msg, "href" -> "#").asJava) 17 | case Right(query) => 18 | thunk(query) 19 | } 20 | } 21 | 22 | protected val SchemeUri = """[a-z]+:.*""".r 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/tasty/comments/Cleaner.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | object Cleaner { 4 | import Regexes._ 5 | import java.util.regex.Matcher 6 | 7 | /** Prepares the comment for pre-parsing: removes documentation markers and 8 | * extra whitespace, removes dangerous HTML and Javadoc tags, and splits it 9 | * into lines. 10 | */ 11 | def clean(comment: String): List[String] = { 12 | def cleanLine(line: String): String = { 13 | // Remove trailing whitespaces 14 | TrailingWhitespace.replaceAllIn(line, "") match { 15 | case CleanCommentLine(ctl) => ctl 16 | case tl => tl 17 | } 18 | } 19 | val strippedComment = comment.trim.stripPrefix("/*").stripSuffix("*/") 20 | val safeComment = DangerousTags.replaceAllIn(strippedComment, { htmlReplacement(_) }) 21 | val javadoclessComment = JavadocTags.replaceAllIn(safeComment, { javadocReplacement(_) }) 22 | val markedTagComment = 23 | SafeTags.replaceAllIn(javadoclessComment, { mtch => 24 | Matcher.quoteReplacement(s"$safeTagMarker${mtch.matched}$safeTagMarker") 25 | }) 26 | markedTagComment.linesIterator.toList map (cleanLine) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/tasty/comments/Emitter.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | import scala.collection.mutable.ArrayBuffer 4 | 5 | object Emitter { 6 | opaque type Emitter[T] = ArrayBuffer[T] 7 | 8 | def collect[T](thunk: Emitter[T] ?=> Unit): Seq[T] = { 9 | val bld = new ArrayBuffer[T] 10 | thunk(using bld) 11 | bld.toSeq 12 | } 13 | 14 | def emit[T](using e: Emitter[T])(t: T) = e.addOne(t) 15 | 16 | def lastEmittedItem[T](using e: Emitter[T]) = 17 | if e.isEmpty then None else Some(e.last) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/tasty/comments/MarkdownParser.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | import java.util.{ Arrays } 4 | 5 | import com.vladsch.flexmark.util.{ast => mdu} 6 | import com.vladsch.flexmark.formatter.Formatter 7 | import com.vladsch.flexmark.parser.Parser 8 | import com.vladsch.flexmark.util.sequence.CharSubSequence 9 | import com.vladsch.flexmark.parser.ParserEmulationProfile 10 | import com.vladsch.flexmark.ext.gfm.tables.TablesExtension 11 | import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension 12 | import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension 13 | import com.vladsch.flexmark.ext.emoji.EmojiExtension 14 | import com.vladsch.flexmark.ext.autolink.AutolinkExtension 15 | import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension 16 | import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterExtension 17 | import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension 18 | import com.vladsch.flexmark.util.options.{ DataHolder, MutableDataSet } 19 | 20 | object MarkdownParser { 21 | 22 | val markdownOptions: DataHolder = 23 | new MutableDataSet() 24 | .setFrom(ParserEmulationProfile.KRAMDOWN.getOptions) 25 | .set(Parser.EXTENSIONS, Arrays.asList( 26 | TablesExtension.create(), 27 | TaskListExtension.create(), 28 | AutolinkExtension.create(), 29 | AnchorLinkExtension.create(), 30 | EmojiExtension.create(), 31 | YamlFrontMatterExtension.create(), 32 | StrikethroughExtension.create(), 33 | WikiLinkExtension.create(), 34 | )) 35 | .set(EmojiExtension.ROOT_IMAGE_PATH, 36 | "https://github.global.ssl.fastly.net/images/icons/emoji/") 37 | .set(WikiLinkExtension.LINK_ESCAPE_CHARS, "") 38 | 39 | val RENDERER = Formatter.builder(markdownOptions).build() 40 | 41 | def parseToMarkdown(text: String): mdu.Document = 42 | Parser.builder(markdownOptions) 43 | .build.parse(text).asInstanceOf[mdu.Document] 44 | 45 | 46 | def renderToText(node: mdu.Node): String = 47 | RENDERER.render(node) 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/transformers/InheritanceInformationTransformer.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer 4 | import org.jetbrains.dokka.model._ 5 | import collection.JavaConverters._ 6 | import org.jetbrains.dokka.plugability.DokkaContext 7 | import org.jetbrains.dokka.links.DRI 8 | import org.jetbrains.dokka.model.properties._ 9 | 10 | import dotty.dokka.model._ 11 | import dotty.dokka.model.api._ 12 | 13 | 14 | class InheritanceInformationTransformer(val ctx: DokkaContext) extends DocumentableTransformer: 15 | override def invoke(original: DModule, context: DokkaContext): DModule = 16 | val subtypes = getSupertypes(original).groupBy(_._1).transform((k, v) => v.map(_._2)) 17 | original.updateMembers { m => 18 | val st: Seq[LinkToType] = subtypes.getOrElse(m.dri, Nil) 19 | m.withKnownChildren(st).withNewGraphEdges(st.map(_ -> m.asLink)) 20 | } 21 | 22 | private def getSupertypes(d: Documentable): Seq[(DRI, LinkToType)] = d match 23 | case m: DModule => m.getPackages.asScala.toList.flatMap(p => getSupertypes(p)) 24 | case c: Member => 25 | val selfMapping = if !c.kind.isInstanceOf[Classlike] then Nil else c.parents.map(_._2 -> c.asLink) 26 | c.allMembers.flatMap(getSupertypes) ++ selfMapping 27 | case other => List.empty 28 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/transformers/ScalaCommentToContentConverter.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka._ 4 | import org.jetbrains.dokka.model.doc._ 5 | import org.jetbrains.dokka.model.properties.PropertyContainer 6 | import org.jetbrains.dokka.pages._ 7 | import collection.JavaConverters._ 8 | import org.jetbrains.dokka.base.transformers.pages.comments.{DocTagToContentConverter, CommentsToContentConverter} 9 | import org.jetbrains.dokka.model.properties.{PropertyContainer, ExtraProperty, ExtraProperty$Key, MergeStrategy} 10 | import java.util.{Set => JSet, List => JList} 11 | 12 | object ScalaCommentToContentConverter extends DocTagToContentConverter { 13 | override def buildContent( 14 | docTag: DocTag, 15 | dci: DCI, 16 | sourceSets: JSet[? <: DokkaConfiguration$DokkaSourceSet], 17 | styles: JSet[? <: Style], 18 | extra: PropertyContainer[ContentNode] 19 | ): JList[ContentNode] = docTag match { 20 | case docTag: A => 21 | val superRes = super.buildContent(docTag, dci, sourceSets, styles, extra).get(0) 22 | val res = superRes.withNewExtras(superRes.getExtra plus ExtraLinkAttributes( 23 | title = docTag.getParams.asScala.get("title") 24 | )) 25 | List(res).asJava 26 | case h: Html => List( 27 | HtmlContentNode( 28 | h.getChildren.asScala.collect{case c: Text => c}.head.getBody, 29 | dci, 30 | sourceSets.asScala.toSet.toDisplay.asScala.toSet, 31 | styles.asScala.toSet 32 | ) 33 | ).asJava 34 | case other => super.buildContent(other, dci, sourceSets, styles, extra) 35 | } 36 | 37 | case class ExtraLinkAttributes(title: Option[String]) extends ExtraProperty[ContentNode] { 38 | def getKey() = LinkAttributesKey 39 | } 40 | 41 | case object LinkAttributesKey extends ExtraProperty.Key[ContentNode, Null] { 42 | def mergeStrategyFor(left: Null, right: Null) = MergeStrategy.Fail( 43 | () => throw NotImplementedError(s"Property merging for $this is not implemented") 44 | ).asInstanceOf[MergeStrategy[ContentNode]] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/translators/FilterAttributes.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.translators 2 | 3 | import org.jetbrains.dokka.base.translators.documentables.{DefaultPageCreator, PageContentBuilder, PageContentBuilder$DocumentableContentBuilder} 4 | import org.jetbrains.dokka.base.signatures.SignatureProvider 5 | import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter 6 | import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator 7 | import org.jetbrains.dokka.utilities.DokkaLogger 8 | import org.jetbrains.dokka.model._ 9 | import org.jetbrains.dokka.pages._ 10 | import collection.JavaConverters._ 11 | import org.jetbrains.dokka.model.properties._ 12 | import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions 13 | import org.jetbrains.dokka.DokkaConfiguration$DokkaSourceSet 14 | import org.jetbrains.dokka.base.resolvers.anchors._ 15 | import org.jetbrains.dokka.links._ 16 | import org.jetbrains.dokka.model.properties.PropertyContainer 17 | import org.jetbrains.dokka.model.doc._ 18 | import dotty.dokka.model.api._ 19 | 20 | import dotty.dokka._ 21 | 22 | object FilterAttributes: 23 | def attributesFor(documentable: Documentable): Map[String, String] = 24 | val base = visibity(documentable) ++ visibity(documentable) ++ origin(documentable) ++ keywords(documentable) 25 | base.filter(_._2.nonEmpty) 26 | 27 | private def keywords(documentable: Documentable): Map[String, String] = documentable match 28 | case v: Member => 29 | Map("keywords" -> v.modifiers.map(_.name).mkString(",")) 30 | case _ => 31 | Map.empty 32 | 33 | 34 | private def visibity(documentable: Documentable): Map[String, String] = documentable match 35 | case v: Member => 36 | Map("visibility" -> v.visibility.name) 37 | case _ => 38 | Map.empty 39 | 40 | 41 | private def origin(documentable: Documentable): Map[String, String] = documentable match 42 | case v: Member => 43 | v.origin match 44 | case Origin.InheritedFrom(name, _) => Map("inherited" -> name) 45 | case Origin.ImplicitlyAddedBy(convName, _, _, _) => Map("implicitly" -> s"by $convName") 46 | case Origin.ExtensionFrom(name, _) => Map("extension" -> s"from $name") 47 | case _ => Map.empty 48 | case _ => 49 | Map.empty 50 | 51 | def defaultValues = Map( 52 | "inherited" -> "Not inherited", 53 | "implicitly" -> "Explicit method", 54 | "extension" -> "Standard member", 55 | "keywords" -> "no keywords", 56 | "visibility" -> "public", 57 | ) 58 | -------------------------------------------------------------------------------- /src/main/scala/dotty/dokka/translators/ScalaDocumentableToPageTranslator.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.jetbrains.dokka.base.signatures.SignatureProvider 4 | import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter 5 | import org.jetbrains.dokka.model.DModule 6 | import org.jetbrains.dokka.pages.ModulePageNode 7 | import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator 8 | import org.jetbrains.dokka.utilities.DokkaLogger 9 | 10 | class ScalaDocumentableToPageTranslator( 11 | val commentsToContentConverter: CommentsToContentConverter, 12 | val signatureProvider: SignatureProvider, 13 | val logger: DokkaLogger 14 | ) extends DocumentableToPageTranslator { 15 | override def invoke(module: DModule): ModulePageNode = ScalaPageCreator(commentsToContentConverter, signatureProvider, logger).pageForModule(module) 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/dotty/renderers/DotDiagramBuilder.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import dotty.dokka.model._ 4 | import org.jetbrains.dokka.model._ 5 | import org.jetbrains.dokka.links.DRI 6 | import org.jetbrains.dokka.base.resolvers.local.LocationProvider 7 | import org.jetbrains.dokka.pages._ 8 | import dotty.dokka.model.api.Kind 9 | import scalatags.Text.all._ 10 | import dotty.dokka.model.api._ 11 | 12 | object DotDiagramBuilder: 13 | def build(diagram: HierarchyGraph, renderer: SignatureRenderer): String = 14 | val vWithId = diagram.verteciesWithId 15 | val vertecies = vWithId.map { (vertex, id) => 16 | s"""node${id} [label="${getHtmlLabel(vertex, renderer)}", style="${getStyle(vertex)}"];\n""" 17 | }.mkString 18 | 19 | val edges = diagram.edges.map { (from, to) => 20 | s"""node${vWithId(from)} -> node${vWithId(to)};\n""" 21 | }.mkString 22 | 23 | s""" digraph g { 24 | | $vertecies 25 | | 26 | | $edges 27 | |} 28 | |""".stripMargin 29 | 30 | 31 | private def getStyle(vertex: LinkToType) = vertex.kind match 32 | case Kind.Class => "fill: #45AD7D;" 33 | case Kind.Object => "fill: #285577;" 34 | case Kind.Trait => "fill: #1CAACF;" 35 | case Kind.Enum => "fill: #B66722;" 36 | case Kind.EnumCase => "fill: #B66722;" 37 | 38 | 39 | private def getHtmlLabel(vertex: LinkToType, renderer: SignatureRenderer): String = 40 | span(style := "color: #FFFFFF;")( 41 | vertex.kind.name, 42 | " ", 43 | vertex.signature.map(renderer.renderElementWith(_)) 44 | ).toString.replace("\"", "\\\"") 45 | -------------------------------------------------------------------------------- /src/main/scala/dotty/tools/dottydoc/Main.scala: -------------------------------------------------------------------------------- 1 | package dotty.tools 2 | package dottydoc 3 | 4 | import dotty.dokka.{Args, RawArgs, DocConfiguration, DottyDokkaConfig} 5 | 6 | import org.jetbrains.dokka._ 7 | import org.jetbrains.dokka.utilities._ 8 | import org.jetbrains.dokka.plugability._ 9 | 10 | import dotc.core.Contexts._ 11 | import dotc.reporting.Reporter 12 | import dotc.{ Compiler, Driver } 13 | import dotc.config._ 14 | 15 | import java.io.File 16 | 17 | /** Main object for SBT. 18 | * 19 | * See [[this.process]]. 20 | */ 21 | object Main extends Driver { 22 | 23 | /** Actual entrypoint from SBT. 24 | * 25 | * Internal SBT code for `sbt doc` locates this precise method with 26 | * reflection, and passes to us both `args` and `rootCtx`. "Internal" here 27 | * means that it's painful to modify this code with a plugin. 28 | * 29 | * `args` contains arguments both for us and for the compiler (see code on 30 | * how they're split). 31 | */ 32 | override def process(args: Array[String], rootCtx: Context): Reporter = { 33 | // split args into ours and Dotty's 34 | val (dokkaStrArgs, compilerArgs) = { 35 | args.partitionMap { arg => 36 | // our options start with this magic prefix, inserted by the SBT plugin 37 | val magicPrefix = "--+DOC+" 38 | if arg startsWith magicPrefix then 39 | Left(arg stripPrefix magicPrefix) 40 | else 41 | Right(arg) 42 | } 43 | } 44 | 45 | val (filesToCompile, ctx) = setup(compilerArgs, rootCtx) 46 | given as Context = ctx 47 | 48 | // parse Dokka args 49 | // note: all required args should be set with SBT settings, 50 | // to make it easier to set and override them 51 | val dokkaArgs = { 52 | val dokkaRawArgs = new RawArgs 53 | val requiredArgs = Seq( 54 | "--tastyRoots", "", // hack, value is not used in SBT but required in CLI 55 | // we extract some settings from Dotty options since that's how SBT passes them 56 | "--name", ctx.settings.projectName.value, 57 | "--projectTitle", ctx.settings.projectName.value, 58 | "--output", ctx.settings.outputDir.value.toString, 59 | ) 60 | 61 | val parser = org.kohsuke.args4j.CmdLineParser(dokkaRawArgs) 62 | try { 63 | parser.parseArgument(requiredArgs ++ dokkaStrArgs : _*) 64 | } catch { 65 | case ex: org.kohsuke.args4j.CmdLineException => 66 | // compiler errors are reported in SBT 67 | dotc.report.error(s"Error when parsing Scala3doc options: ${ex.getMessage}") 68 | throw ex 69 | } 70 | dokkaRawArgs.toArgs 71 | } 72 | 73 | val config = DocConfiguration.Sbt(dokkaArgs, filesToCompile, ctx) 74 | val dokkaCfg = new DottyDokkaConfig(config) 75 | new DokkaGenerator(dokkaCfg, DokkaConsoleLogger.INSTANCE).generate() 76 | 77 | rootCtx.reporter 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/scala/example/Documentation2.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | class ReturnTypeClass[T] { 4 | } 5 | 6 | class UserDocLinkingClass { 7 | def linkMeFromUserDoc() = ??? 8 | } 9 | 10 | object ReturnObjectWithType { 11 | type returnType = Int 12 | } -------------------------------------------------------------------------------- /src/main/scala/example/Inheritance.scala: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import example.level2.Documentation 4 | 5 | abstract class DocumentationInheritance[T, A <: Int, B >: String, -X, +Y] extends Documentation[T, A, B, X, Y] {} 6 | 7 | class DocumentationInheritanceMethod: 8 | def wierdMethod[T, A <: Int, B >: String](t: T, a: A): B = ??? 9 | def threOtherWay[A <: Nothing, B >: Any](a: A, c: B): Unit = ??? 10 | 11 | class A: 12 | def this(s: String) = this() 13 | def this(i: Int) = this() 14 | type I = Int 15 | given Unit = () 16 | extension (u: Unit) def foo = "foo" 17 | object X 18 | class B extends C: 19 | class D extends C 20 | 21 | class C extends A 22 | -------------------------------------------------------------------------------- /src/main/scala/example/level2/SameLevelTypeLinking.scala: -------------------------------------------------------------------------------- 1 | package example.level2 2 | 3 | class SameLevelTypeLinking { 4 | 5 | } -------------------------------------------------------------------------------- /src/main/scala/example/level2/level3/level4/ClassLevel4.scala: -------------------------------------------------------------------------------- 1 | package example.level2.level3.level4 2 | 3 | import example.level2.Documentation 4 | 5 | sealed abstract class ClassLevel4[T, A <: Int, B >: String, -X, +Y]() extends Documentation[T, A, B, X, Y] { 6 | 7 | /** 8 | * [[example.level2.Documentation]] 9 | * [[example.level2.Documentation$.valInsideDocObject]] 10 | * [[example.level2.Documentation.abstractType]] 11 | */ 12 | def linkingToDocMethodInUserDoc = ??? 13 | } -------------------------------------------------------------------------------- /src/main/scala/tests/annotations.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package annotations 3 | 4 | import scala.annotation.StaticAnnotation 5 | 6 | 7 | class SomeObject(val s: String) 8 | 9 | class MyAnnotation extends StaticAnnotation 10 | 11 | class AnnotationWithArg(val s: String, val o: SomeObject) extends StaticAnnotation 12 | 13 | class AnnotationWithMultiArg(val i: Int, val s: String, val c: Char*) extends StaticAnnotation 14 | 15 | class EnumAnnotation(val e: Enum) extends StaticAnnotation 16 | 17 | class ClassAnnotation[T](val c: Class[T]) extends StaticAnnotation 18 | 19 | @AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c') @MyAnnotation class AnnotatedClass 20 | 21 | 22 | class AnnotatedParams(@MyAnnotation val a: String, @AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c') val b: Int) 23 | 24 | class AnnotatedMethods 25 | { 26 | @MyAnnotation @AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c') def a: String 27 | = ??? 28 | } -------------------------------------------------------------------------------- /src/main/scala/tests/annotationsExample.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package annotationsExample 3 | 4 | import scala.annotation.StaticAnnotation 5 | 6 | enum Enum { 7 | case A extends Enum 8 | case B extends Enum 9 | case C extends Enum 10 | } 11 | 12 | class SomeObject(val s: String) 13 | 14 | class MyAnnotation extends StaticAnnotation 15 | 16 | class AnnotationWithArg(val s: String, val o: SomeObject) extends StaticAnnotation 17 | 18 | class AnnotationWithMultiArg(val i: Int, val s: String, val c: Char*) extends StaticAnnotation 19 | 20 | class EnumAnnotation(val e: Enum) extends StaticAnnotation 21 | 22 | class ClassAnnotation[T](val c: Class[T]) extends StaticAnnotation 23 | 24 | @MyAnnotation@AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c')@EnumAnnotation(Enum.A)class AnnotatedClass 25 | 26 | 27 | class AnnotatedParams(@MyAnnotation val a: String, @AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c') val b: Int) 28 | 29 | class AnnotatedMethods 30 | { 31 | @MyAnnotation 32 | @AnnotationWithMultiArg(2, "cda", 'a', 'b', 'c') 33 | def a: String 34 | = ??? 35 | } -------------------------------------------------------------------------------- /src/main/scala/tests/classModifiers.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package classModifiers 4 | 5 | sealed abstract class B 6 | 7 | abstract case class C(s: String) 8 | 9 | sealed case class D(c: String) 10 | 11 | final case class E(c: String) 12 | 13 | open class F 14 | -------------------------------------------------------------------------------- /src/main/scala/tests/classSignatureTestSource.scala: -------------------------------------------------------------------------------- 1 | package tests.classSignatureTestSource 2 | 3 | import scala.collection._ 4 | import scala.deprecated 5 | import scala.annotation._ 6 | import scala.math.{Pi, max} 7 | import example.level2.Documentation 8 | 9 | abstract class Documentation[T, A <: Int, B >: String, -X, +Y](c1: String, val c2: List[T]) extends Seq[T] with Product with Serializable 10 | { 11 | def this(ac: String) 12 | = this(ac, Nil) 13 | 14 | def this() 15 | = this("", Nil) 16 | 17 | def this(x: T) 18 | = this() 19 | 20 | class innerDocumentationClass 21 | { 22 | 23 | } 24 | 25 | sealed trait CaseImplementThis(id: Int) 26 | 27 | case class IAmACaseClass(x: T, id: Int) extends CaseImplementThis/*<-*/(id)/*->*/ 28 | 29 | case object IAmACaseObject extends CaseImplementThis/*<-*/(0)/*->*/ 30 | 31 | object testObject 32 | 33 | class Graph 34 | { 35 | type Node = Int 36 | } 37 | 38 | type typeExample[X] >: X <: String 39 | 40 | type abstractType 41 | } 42 | 43 | object Documentation 44 | { 45 | // TODO We do not see members from companions val valInsideDocObject = ??? 46 | } 47 | 48 | sealed abstract class ClassExtendingDocumentation[T, A <: Int, B >: String, -X, +Y] extends Documentation[T, A, B, X, Y] 49 | {} 50 | 51 | trait TraitTest 52 | { 53 | 54 | } 55 | 56 | trait TraitWithCompanion{} //expected: trait TraitWithCompanion 57 | 58 | object TraitWithCompanion 59 | {} 60 | 61 | // TODO #25 do we need to add 'val' in case class signatures? 62 | case class ManyModifiers(/*<-*/val /*->*/x: Int, var y: Double, z: String) 63 | class ManyModifiers2(val x: Int, var y: Double, z: String) -------------------------------------------------------------------------------- /src/main/scala/tests/companionObjectSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package companionObjectSignatures 3 | 4 | case class CaseClass(parameterOfClassConstructor: String) 5 | { 6 | val classProperty1: String 7 | = ??? 8 | val classProperty2: String 9 | = ??? 10 | def methodInClass1(): String 11 | = ??? 12 | 13 | def methodInClass2(): CaseClass 14 | = ??? 15 | } 16 | 17 | case object CaseClass 18 | { 19 | val parameterOfObject: String 20 | = "asd" 21 | 22 | def methodInCompanion1(): String 23 | = ??? 24 | 25 | def methodInCompanion2(): CaseClass 26 | = ??? 27 | } 28 | 29 | case class WithoutExplicitCompanion(parameter: Int) 30 | 31 | class StandardClass 32 | 33 | object StandardClass 34 | 35 | class StandardClassWithCaseCompanion 36 | 37 | case object StandardClassWithCaseCompanion -------------------------------------------------------------------------------- /src/main/scala/tests/enumSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package enumSignatures 4 | 5 | enum Enum1 6 | { 7 | case A 8 | case B 9 | case C 10 | } 11 | enum Enum2(val i: Int): 12 | case A(val s: String) extends Enum2(1) 13 | case B(val t: String) extends Enum2(2) 14 | case C(val u: String) extends Enum2(3) 15 | 16 | enum Enum3(val param: Int): 17 | case A extends Enum3(1) with A 18 | case B extends Enum3(2) 19 | case C extends Enum3(3) 20 | 21 | enum Enum4[+T]: 22 | case G(s: String) 23 | case B extends Enum4[Int] with A 24 | case C[V](s:String) extends Enum4[V] 25 | case D[T](s: String) extends Enum4[T] 26 | 27 | trait A -------------------------------------------------------------------------------- /src/main/scala/tests/extensionMethodSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package extensionMethodSignatures 3 | 4 | class ClassOne 5 | { 6 | // Commented cases won't work for now 7 | // extension ClassTwoOps on (c: ClassTwo): 8 | // def getA() = c.a 9 | extension (c: ClassTwo) 10 | def getB(): String 11 | = c.b 12 | 13 | extension (c: ClassTwo) 14 | def getGivenParams(a: Int, b: Int, d: Int)(e: String): Int 15 | = 56 16 | 17 | extension (c: ClassTwo) 18 | def |||:(a: Int, b: Int, d: Int)(e: String): Int 19 | = 56 20 | 21 | extension (b: Int) 22 | def secondGroup(): String 23 | = ??? 24 | 25 | extension (c:ClassTwo) 26 | : 27 | def getString(a: String): String 28 | = a 29 | 30 | def getInt(): Int 31 | = 5 32 | 33 | extension (s: String) 34 | def someMethod(): String 35 | = ??? 36 | def otherMethod(a: Int): Int 37 | = ??? 38 | } 39 | 40 | case class ClassTwo(a: String, b: String) 41 | { 42 | 43 | } 44 | 45 | class ClassOneTwo extends ClassOne -------------------------------------------------------------------------------- /src/main/scala/tests/fieldsSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package fieldsSignatures 3 | 4 | case class A(cA: String, var cB: Int) 5 | { 6 | val A: Int 7 | = 1 8 | val B: Int 9 | = 2 10 | var other: Int 11 | = 4 12 | } 13 | 14 | trait C 15 | { 16 | val d: Int 17 | } 18 | 19 | abstract class D extends C 20 | { 21 | override val d: Int 22 | = 1 23 | } 24 | 25 | trait C2 26 | { 27 | def d: Int 28 | } 29 | 30 | 31 | abstract class D2 extends C 32 | { 33 | override val d: Int 34 | = 1 35 | } 36 | 37 | object Documentation 38 | { 39 | val valInsideDocObject: Nothing 40 | = ??? 41 | } -------------------------------------------------------------------------------- /src/main/scala/tests/genericMethods.scala: -------------------------------------------------------------------------------- 1 | package tests.genericMethods 2 | 3 | class Types: 4 | def orTypes(base: Int | String, nested: List[Int | Double] | Seq[String]): Unit 5 | = ??? 6 | def andTypes(base: Int & String, nested: List[Int & Double] & Seq[String]): Unit 7 | = ??? 8 | 9 | def mixedAndAndOr(base: Int & String, nested: List[Int | Double] & Seq[String]): Unit 10 | = ??? 11 | 12 | def literal(i: 1, d: 3.3, c: 'c'): 34 13 | = 34 14 | 15 | def byName(a: => Int, b: => String | Int): Unit 16 | = ??? -------------------------------------------------------------------------------- /src/main/scala/tests/genericSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests.genericSignatures 2 | 3 | class D[T] 4 | 5 | // TODO #26 this is not supported :( class D1[T ] 6 | 7 | class D2[T]() 8 | 9 | class DD[+T] 10 | 11 | class A 12 | 13 | class E[T] extends D[T] 14 | 15 | class F[+T, -F] extends DD[T] 16 | 17 | class A2[E, +T <: DD[E]] 18 | -------------------------------------------------------------------------------- /src/main/scala/tests/givenSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package givenSignatures 4 | 5 | 6 | 7 | class GivenClass { 8 | trait B 9 | trait C[T] 10 | val r: Int = 5 11 | type R = Int 12 | given R = r 13 | trait Ord[T] { 14 | def compare(x: T, y: T): Int 15 | extension (x: T) def < (y: T) = compare(x, y) < 0 16 | extension (x: T) def > (y: T) = compare(x, y) > 0 17 | } 18 | given intOrd as Ord[Int] { 19 | def compare(x: Int, y: Int) = 20 | if (x < y) -1 else if (x > y) +1 else 0 21 | } 22 | 23 | given asd(using int: Int) as B 24 | 25 | given asd2[T] as C[T] 26 | 27 | given listOrd[T](using ord: Ord[T]) as Ord[List[T]] { 28 | 29 | def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match 30 | case (Nil, Nil) => 0 31 | case (Nil, _) => -1 32 | case (_, Nil) => +1 33 | case (x :: xs1, y :: ys1) => 34 | val fst = ord.compare(x, y) 35 | if (fst != 0) fst else compare(xs1, ys1) 36 | } 37 | 38 | given IntOps as Int.type = Int 39 | 40 | given GivenType = GivenType() 41 | 42 | class GivenType 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/main/scala/tests/implicitClasslikes.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package implicitClasslikes 4 | 5 | implicit object ImplicitObject 6 | { 7 | implicit class ImplicitClass(val i: Int) 8 | } 9 | 10 | object A 11 | { 12 | class B 13 | implicit object B 14 | } -------------------------------------------------------------------------------- /src/main/scala/tests/implicitConversions/A.scala: -------------------------------------------------------------------------------- 1 | package tests.implicitConversions 2 | 3 | implicit val convDtoC: Conversion[ClazzD, ClazzC] 4 | = ??? 5 | 6 | class ClazzA 7 | { 8 | /* Methods inside this comment block should be added by implicit conversion 9 | val prop1: String 10 | 11 | def met1: String 12 | */ 13 | } 14 | 15 | object ClazzA 16 | { 17 | implicit def convToB1(a: ClazzA): ClazzB 18 | = ??? 19 | } 20 | 21 | class ClazzAB extends ClazzA 22 | { 23 | /* Methods inside this comment block should be added by implicit conversion 24 | val prop1: String 25 | 26 | def met1: String 27 | */ 28 | 29 | } 30 | 31 | object ClazzAB 32 | { 33 | 34 | } 35 | 36 | class ClazzD 37 | { 38 | /* Methods inside this comment block should be added by implicit conversion 39 | val prop2: String 40 | 41 | def met2: String 42 | */ 43 | } 44 | 45 | class ClazzF[T] 46 | { 47 | /* Methods inside this comment block should be added by implicit conversion 48 | val prop3: String 49 | 50 | def met3: String 51 | */ 52 | } 53 | 54 | object ClazzF 55 | { 56 | implicit def convFtoE: Conversion[ClazzF[String], ClazzE] 57 | = ??? 58 | } -------------------------------------------------------------------------------- /src/main/scala/tests/implicitConversions/B.scala: -------------------------------------------------------------------------------- 1 | package tests.implicitConversions 2 | 3 | class ClazzB 4 | { 5 | val prop1: String 6 | = ??? 7 | 8 | def met1: String 9 | = ??? 10 | } 11 | 12 | class ClazzC 13 | { 14 | val prop2: String 15 | = ??? 16 | 17 | def met2: String 18 | = ??? 19 | } 20 | 21 | class ClazzE 22 | { 23 | val prop3: String 24 | = ??? 25 | 26 | def met3: String 27 | = ??? 28 | } -------------------------------------------------------------------------------- /src/main/scala/tests/implicitConversions/classesWithConversions.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package implicitConversions 4 | 5 | given Conversion[A, B] { 6 | def apply(a: A): B = ??? 7 | } 8 | 9 | extension (a: A) def extended_bar(): String = ??? 10 | 11 | class A { 12 | implicit def conversion(c: C): D = ??? 13 | implicit def conversion: Conversion[C,D] = ??? 14 | implicit val a: Conversion[C,D] = ??? 15 | 16 | extension (c: C) def extended_bar(): String = ??? 17 | 18 | class C { 19 | def bar: String = ??? 20 | } 21 | 22 | class D extends E() { 23 | def bar2: String = ??? 24 | 25 | val string: String = ??? 26 | 27 | class Bar() 28 | 29 | type ImplicitType >: String 30 | 31 | extension (e: E) def extended_bar(): String = ??? 32 | } 33 | 34 | class E { 35 | def inherited: Int = ??? 36 | } 37 | } 38 | 39 | class B { 40 | def foo: Int = ??? 41 | 42 | var b: String = ??? 43 | } 44 | 45 | class C { 46 | def extensionInCompanion: String = ??? 47 | } 48 | 49 | object C { 50 | implicit def companionConversion(c: C): B = ??? 51 | 52 | extension (c: C) def extensionInCompanion: String = ??? 53 | } 54 | 55 | package nested { 56 | extension (opt: Opt[Int]) def sum: Int = ??? 57 | class Opt[A] 58 | 59 | class Lst[A] 60 | object Lst { 61 | extension (lst: Lst[Int]) def sum: Int = ??? 62 | } 63 | 64 | object Wrapper { 65 | class Foo 66 | class Bar { 67 | def bar = "bar" 68 | } 69 | implicit def foobar(foo: Foo): Bar = Bar() 70 | } 71 | 72 | class Z 73 | } -------------------------------------------------------------------------------- /src/main/scala/tests/implicitMembers.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package implicitMembers 4 | 5 | class OuterClass: 6 | class ImplicitMemberTarget 7 | 8 | object ImplicitMemberTarget: 9 | extension (a: ImplicitMemberTarget): 10 | def extensionFromCompanion: String = 11 | "ImplicitMemberTarget" 12 | 13 | // does not work 14 | extension (a: ImplicitMemberTarget): 15 | def extensionFromOuterClass: String = 16 | "ImplicitMemberTarget" 17 | 18 | extension (a: OuterClass#ImplicitMemberTarget): 19 | def extensionFromPackage: String = 20 | "ImplicitMemberTarget" 21 | -------------------------------------------------------------------------------- /src/main/scala/tests/markdown-tests.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | /** 4 | * * a 5 | * * b 6 | * * c 7 | * 8 | * - a 9 | * - b 10 | * - c 11 | * 12 | * 1. a 13 | * 1. b 14 | * 1. c 15 | * 16 | * 17 | * If the following list was indented one space less, it wouldn't parse 18 | * properly. That is, the first nested list would not be nested. This is 19 | * because ATTW we trim _up to two_ spaces between the star "gutter" and actual 20 | * comment bodies. 21 | * 22 | * * a 23 | * - a.a 24 | * - a.b 25 | * - a.c 26 | * * b 27 | * 1. b.1 28 | * 2. b.2 29 | * 3. b.3 30 | * * b.3.a 31 | * * b.3.b 32 | * * b.3.c 33 | */ 34 | class MdLists 35 | 36 | /** 37 | * | day | time | spent | 38 | * |:------------|:-----:|--------:| 39 | * | nov. 2. tue | 10:00 | 4h 40m | 40 | * | nov. 3. thu | 11:00 | 4h | 41 | * | nov. 7. mon | 10:20 | 4h 20m | 42 | * | total: || 13h | 43 | */ 44 | class MdTables 45 | -------------------------------------------------------------------------------- /src/main/scala/tests/mergedPackage1.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package mergedPackage 4 | 5 | val propertyFromPackage1: String 6 | = ??? 7 | 8 | def methodFromPackage1(): Int 9 | = ??? -------------------------------------------------------------------------------- /src/main/scala/tests/mergedPackage2.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package mergedPackage 4 | 5 | val propertyFromPackage2: Int 6 | = ??? 7 | 8 | def methodFromPackage2(): String 9 | = ??? -------------------------------------------------------------------------------- /src/main/scala/tests/mergedPackage3.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package object mergedPackage{ 4 | val propertyFromPackageObject: Double 5 | = ??? 6 | def functionFromPackageObject(): String => String 7 | = ??? 8 | } -------------------------------------------------------------------------------- /src/main/scala/tests/methodsAndConstructors.scala: -------------------------------------------------------------------------------- 1 | package tests.methodsAndConstructors 2 | 3 | class A 4 | class B extends A 5 | class C 6 | class D[T] 7 | class E[T] extends D[T] 8 | 9 | class Constructors(a: String): 10 | def this() 11 | = this("Ala") 12 | 13 | def this(a: A)(b: A) 14 | = this("Ala") 15 | 16 | /** Some methods to tests */ 17 | class Methods: 18 | def nobraces: A 19 | = ??? 20 | 21 | def simple(): B 22 | = ??? 23 | 24 | def oneParam(a: A): B 25 | = ??? 26 | 27 | def multipleParams(a: A, b: B): C 28 | = ??? 29 | 30 | def vararg(a: A*): C 31 | = ??? 32 | 33 | def multipleList(a: A)(b: B): C 34 | = ??? 35 | 36 | def generic[T](a: D[T]): D[T] 37 | = ??? 38 | 39 | def generic2[T, V](a: D[T], b: E[V]): D[T] 40 | = ??? 41 | 42 | def primitives(a: Int, b: Double, c: Short): Byte 43 | = 0 44 | 45 | def strings(a: String): String 46 | = "" 47 | 48 | def arrays(a: Array[String], b: Array[Int]): Array[Double] 49 | = ??? 50 | -------------------------------------------------------------------------------- /src/main/scala/tests/modifiersSignatureTestSource.scala: -------------------------------------------------------------------------------- 1 | package tests.modifiersSignatureTestSource 2 | 3 | case class Case() 4 | 5 | final class Final() 6 | 7 | abstract class Abstract() 8 | 9 | class Empty() 10 | 11 | sealed class Sealed() 12 | 13 | open class Open 14 | 15 | opaque type Opaque 16 | = Open 17 | 18 | abstract class Methods() 19 | { 20 | def method1(): Unit 21 | 22 | inline def inlineMethod(): Unit 23 | = Unit 24 | 25 | implicit def toImplicitString(): String 26 | = "asd" 27 | } 28 | 29 | class ImplementedMethods() extends Methods/*<-*/()/*->*/ 30 | { 31 | override def method1(): Unit 32 | = ??? 33 | 34 | } 35 | 36 | case class ReimplementedMethods() extends ImplementedMethods/*<-*/()/*->*/ 37 | { 38 | override def method1(): Unit 39 | = ??? 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/tests/nested.scala: -------------------------------------------------------------------------------- 1 | package tests.nested 2 | 3 | class A 4 | { 5 | object B 6 | { 7 | def bb(): Int 8 | = 123 9 | val a: Double 10 | = 0.3 11 | } 12 | 13 | class C 14 | { 15 | def cc: Int 16 | = 123 17 | } 18 | 19 | trait D 20 | { 21 | type AA = Int 22 | } 23 | } 24 | 25 | object R 26 | { 27 | object B 28 | { 29 | def bb(): Int 30 | = 123 31 | val a: Double 32 | = 0.3 33 | } 34 | 35 | class C 36 | { 37 | def cc: Int 38 | = 123 39 | } 40 | 41 | trait D 42 | { 43 | type AA = Int 44 | } 45 | } 46 | 47 | class X 48 | { 49 | object Y 50 | } 51 | 52 | // bug found in dotty code, still fails with type 53 | sealed trait ErrorKind 54 | object ErrorKind 55 | { 56 | // This below produce some strange type 57 | // case object Parser extends ErrorKind 58 | // case object Typer extends ErrorKind 59 | } -------------------------------------------------------------------------------- /src/main/scala/tests/objectSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package objectSignatures 3 | 4 | class A[T] 5 | { 6 | val a: String = "asd" 7 | def method3() = "asd" 8 | } 9 | 10 | object A 11 | 12 | trait C 13 | 14 | object Base 15 | 16 | object A2 extends A[String] with C 17 | 18 | // We are not going to add final below 19 | // final object B 20 | -------------------------------------------------------------------------------- /src/main/scala/tests/opaqueTypes.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package opaqueTypes 4 | 5 | opaque type Permissions 6 | = Int 7 | opaque type PermissionChoice 8 | = Int 9 | //opaque type Permission <: Permissions & PermissionChoice = Int TODO: #112 -------------------------------------------------------------------------------- /src/main/scala/tests/package.scala: -------------------------------------------------------------------------------- 1 | /** This should be moved to its own project */ 2 | package object tests { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /src/main/scala/tests/packageObjectSymbolSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package object packageObjectSymbolSignatures 4 | { 5 | val property1: String 6 | = ??? 7 | 8 | type MyType = String 9 | 10 | val property2: Int 11 | = ??? 12 | 13 | def method1(): Int 14 | = ??? 15 | 16 | def method2(): String 17 | = ??? 18 | } -------------------------------------------------------------------------------- /src/main/scala/tests/packageSymbolSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package packageSymbolSignatures 4 | 5 | val packageSymbol1: String 6 | = ??? 7 | 8 | val packageSymbol2: Int 9 | = ??? 10 | 11 | def packageMethod1: String 12 | = ??? 13 | 14 | def packageMethod2: Int 15 | = ??? 16 | 17 | type PackageInteger = Int 18 | 19 | class A 20 | -------------------------------------------------------------------------------- /src/main/scala/tests/signatureTestSource.scala: -------------------------------------------------------------------------------- 1 | package tests.signatureTestSource 2 | class A 3 | class B extends A 4 | class C 5 | class D[T] 6 | class E[T] extends D[T] 7 | 8 | class SignatureTestClass(a: String) 9 | : 10 | def simple(): B 11 | = ??? 12 | def oneParam(a: A): B 13 | = ??? 14 | def multipleParams(a: A, b: B): C 15 | = ??? 16 | def likeVararg(a: Seq[A]): C 17 | = ??? 18 | def vararg(a: A*): C 19 | = ??? 20 | def multipleList(a: A)(b: B): C 21 | = ??? 22 | 23 | def generic[T](a: D[T]): D[T] 24 | = ??? 25 | def generic2[T, V](a: D[T], b: E[V]): D[T] 26 | = ??? 27 | 28 | def primitives(a: Int, b: Double, c: Short): Byte 29 | = 0 30 | def strings(a: String): String 31 | = "" 32 | def arrays(a: Array[String], b: Array[Int]): Array[Double] 33 | = ??? 34 | def bounds1[T <: String](a: T, b: T): Unit 35 | = ??? 36 | def bounds2[T >: String](a: T, b: T): Unit 37 | = ??? 38 | def this() 39 | = this("Ala") -------------------------------------------------------------------------------- /src/main/scala/tests/structuralTypes.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package structuralTypes 4 | 5 | type Person = Record { val name: String; val age: Int; type Height = Int; def sth(a: Int, b: String): Int; } 6 | 7 | type R = { type T; val x: Int; type U <: this.T; def foo(): Int; } 8 | 9 | class Record(elems: (String, Any)*) extends Selectable { 10 | val fields: Map[String, Any] 11 | = elems.toMap 12 | def selectDynamic(name: String): Any 13 | = fields(name) 14 | } -------------------------------------------------------------------------------- /src/main/scala/tests/traitSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package traitSignatures 3 | 4 | trait A 5 | 6 | trait B extends A 7 | 8 | trait C(a: Int) 9 | 10 | trait D(b: Double) extends C with A -------------------------------------------------------------------------------- /src/main/scala/tests/typeLambdas.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | package typeLambdas 4 | 5 | type L1 = Int 6 | type U1 = String 7 | type R1 = Double 8 | 9 | type Id[T <: AnyKind] 10 | 11 | type TL1 = Id[[X, Y] =>> Map[X,Y]] 12 | 13 | type TL2 = Id[[X >: Int] =>> [Y <: String] =>> Map[X, Y]] -------------------------------------------------------------------------------- /src/main/scala/tests/typesSignatures.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package typesSignatures 3 | 4 | class A 5 | { 6 | type A = Int 7 | type B[+T] = Seq[T] 8 | type C[A, B <: A] = Seq[B] 9 | } 10 | 11 | trait V 12 | { 13 | type Ala[+J] <: Int 14 | type Ola[+T] 15 | type X 16 | } 17 | 18 | class Generic[T] 19 | 20 | class Base 21 | { 22 | type A 23 | type B = Int 24 | 25 | // Tests not support multiline signatures 26 | type MatchT[T] = T match { case String => Char case Int => Byte } 27 | 28 | // Tests do not support multiline signatures 29 | type Elem[X] = X match { case String => Char case Array[t] => t case Iterable[t] => t } 30 | 31 | type F = [X] => (x: X) => List[X] 32 | 33 | type G = Int => Int 34 | 35 | type H = () => String 36 | 37 | type I = (Int, String, Int) => (String, Int) 38 | } 39 | 40 | class Operators 41 | { 42 | type Binary = String =:= Int 43 | 44 | // Infix annotation is not well supported in Dotty 45 | // import scala.annotation.infix 46 | // @infix type op[A, B] = Int 47 | // type Binary2 = String op Int 48 | 49 | import scala.compiletime.ops.boolean._ 50 | type Unary = ![true] 51 | } -------------------------------------------------------------------------------- /src/main/scala/tests/visibility.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | package visibility 3 | 4 | private object PrivateTopLevelObject //unexpected 5 | 6 | private[tests] object PrivateInOuterPackageTopLevelObject //unexpected 7 | 8 | private[visibility] object PrivateInInnerPackageTopLevelObject //unexpected 9 | 10 | private[this] object LocallyPrivateTopLevelObject //unexpected 11 | 12 | protected object ProtectedTopLevelObject //unexpected 13 | 14 | protected[tests] object ProtectedInOuterPackageTopLevelObject //unexpected 15 | 16 | protected[visibility] object ProtectedInInnerPackageTopLevelObject //unexpected 17 | 18 | protected[this] object LocallyProtectedTopLevelObject //unexpected 19 | 20 | private def privateTopLevelMethod: Int //unexpected 21 | = 1 22 | 23 | protected def protectedTopLevelMethod: Int //unexpected 24 | = 1 25 | 26 | class InClassVisibility() 27 | { 28 | private def privateMethod: Int //unexpected 29 | = ??? 30 | 31 | private[tests] def privateInOuterPackageMethod: Int //unexpected 32 | = ??? 33 | 34 | private[visibility] def privateInInnerPackageMethod: Int //unexpected 35 | = ??? 36 | 37 | private[InClassVisibility] def privateInClassMethod: Int //unexpected 38 | = ??? 39 | 40 | private[this] def locallyPrivateMethod: Int //unexpected 41 | = ??? 42 | 43 | protected def protectedMethod: Int 44 | = ??? 45 | 46 | protected[tests] def protectedInOuterPackageMethod: Int //unexpected 47 | = ??? 48 | 49 | protected[visibility] def protectedInInnerPackageMethod: Int //unexpected 50 | = ??? 51 | 52 | protected[InClassVisibility] def protectedInClassMethod: Int 53 | = ??? 54 | 55 | protected[this] def locallyProtectedMethod: Int //unexpected 56 | = ??? 57 | } 58 | 59 | trait InTraitVisibility 60 | { 61 | protected[InTraitVisibility] def protectedInTraitMethod: Int 62 | = ??? 63 | } 64 | 65 | object InObjectVisibility 66 | { 67 | protected def protectedObjectMethod: Int //unexpected 68 | = ??? 69 | 70 | protected[InObjectVisibility] def protectedInObjectScopeMethod: Int //unexpected 71 | = ??? 72 | } 73 | -------------------------------------------------------------------------------- /src/main/scala/tests/wiki-tests.scala: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | /** Wiki list syntax tests. 4 | * 5 | * - a 6 | * - b 7 | * - c 8 | * 9 | * 1. a 10 | * 1. b 11 | * 1. c 12 | * 13 | * a. a 14 | * a. b 15 | * a. c 16 | * 17 | * i. a 18 | * i. b 19 | * i. c 20 | * 21 | * 22 | * - a 23 | * - a.a 24 | * - a.b 25 | * - a.c 26 | * - b 27 | * 1. b.1 28 | * 1. b.2 29 | * 1. b.3 30 | * a. b.3.a 31 | * a. b.3.b 32 | * a. b.3.c 33 | * 34 | * @syntax wiki 35 | */ 36 | class WikiLists 37 | -------------------------------------------------------------------------------- /src/test/scala/dotty/dokka/SignatureTests.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | class GenericSignatures extends SingleFileTest("genericSignatures", Seq("class")) 4 | 5 | class ObjectSignatures extends SingleFileTest("objectSignatures", Seq("object")) 6 | 7 | class TraitSignatures extends SingleFileTest("traitSignatures", Seq("trait")) 8 | 9 | 10 | // We do not support companion objects properly in tests 11 | class ClassSignatureTestSourceTest extends SingleFileTest("classSignatureTestSource", 12 | SingleFileTest.all.filterNot(Seq("val", "var", "object").contains)) 13 | 14 | // TODO we still cannot filter out all constructor-based fields 15 | class SignatureTestSourceTest extends SingleFileTest("signatureTestSource", SingleFileTest.all) 16 | 17 | class ModifiersSignatureTest extends SingleFileTest("modifiersSignatureTestSource", SingleFileTest.all) 18 | 19 | class Visibility extends SingleFileTest("visibility", SingleFileTest.all) 20 | 21 | 22 | class GenericMethodsTest extends SingleFileTest("genericMethods", Seq("def")) 23 | 24 | class MethodsAndConstructors extends SingleFileTest("methodsAndConstructors", Seq("def")) 25 | 26 | class TypesSignatures extends SingleFileTest("typesSignatures", SingleFileTest.all) 27 | 28 | class FieldsSignatures extends SingleFileTest("fieldsSignatures", SingleFileTest.all.filter(_ != "object")) 29 | 30 | class NestedSignatures extends SingleFileTest("nested", SingleFileTest.all) 31 | 32 | class CompanionObjectSignatures extends SingleFileTest("companionObjectSignatures", SingleFileTest.all) 33 | 34 | class PackageSymbolSignatures extends SingleFileTest("packageSymbolSignatures", SingleFileTest.all) 35 | 36 | class PackageObjectSymbolSignatures extends SingleFileTest("packageObjectSymbolSignatures", SingleFileTest.all.filter(_ != "object")) 37 | 38 | class MergedPackageSignatures extends MultipleFileTest(List("mergedPackage1", "mergedPackage2", "mergedPackage3"), List("mergedPackage"), SingleFileTest.all.filter(_ != "object")) 39 | 40 | class ExtensionMethodSignature extends SingleFileTest("extensionMethodSignatures", SingleFileTest.all) 41 | 42 | class ClassModifiers extends SingleFileTest("classModifiers", SingleFileTest.classlikeKinds) 43 | 44 | // class EnumSignatures extends SingleFileTest("enumSignatures", SingleFileTest.all) 45 | 46 | class StructuralTypes extends SingleFileTest("structuralTypes", SingleFileTest.members) 47 | 48 | class OpaqueTypes extends SingleFileTest("opaqueTypes", SingleFileTest.all) 49 | 50 | // class GivenSignatures extends SingleFileTest("givenSignatures", SingleFileTest.all) 51 | 52 | class Annotations extends SingleFileTest("annotations", SingleFileTest.all) 53 | 54 | class ImplicitConversions extends MultipleFileTest(List("implicitConversions/A"), List("implicitConversions"), SingleFileTest.all) 55 | 56 | class ImplicitClasslikes extends SingleFileTest("implicitClasslikes", SingleFileTest.classlikeKinds) 57 | -------------------------------------------------------------------------------- /src/test/scala/dotty/dokka/SingleFileTest.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | import org.junit.{Test, Rule} 4 | import org.junit.Assert._ 5 | import org.junit.rules.ErrorCollector 6 | import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest$TestBuilder 7 | import scala.io.Source 8 | import org.jetbrains.dokka.pages._ 9 | import org.jetbrains.dokka.pages.ContentNodesKt 10 | import org.jetbrains.dokka._ 11 | import scala.jdk.CollectionConverters._ 12 | import scala.math.max 13 | 14 | object SingleFileTest { 15 | val classlikeKinds = Seq("class", "object", "trait", "enum") // TODO add docs for packages 16 | val members = Seq("type", "def", "val", "var") 17 | val all = classlikeKinds ++ members 18 | } 19 | 20 | abstract class SingleFileTest( 21 | val fileName: String, 22 | signatureKinds: Seq[String], 23 | ignoreUndocumentedSignatures: Boolean = false 24 | ) extends MultipleFileTest( 25 | List(fileName), 26 | List(fileName), 27 | signatureKinds, 28 | ignoreUndocumentedSignatures 29 | ) 30 | 31 | -------------------------------------------------------------------------------- /src/test/scala/dotty/dokka/TestUtils.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka 2 | 3 | object TestUtils { 4 | val Scala3docClassRoot = 5 | // set from SBT 6 | sys.env("scala3doc.classroot") 7 | } 8 | -------------------------------------------------------------------------------- /src/test/scala/dotty/dokka/tasty/comments/MarkdownConverterTests.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | import org.junit.{Test, Rule} 4 | import org.junit.Assert.{assertSame, assertTrue, assertEquals} 5 | 6 | class MarkdownConverterTests { 7 | @Test def test(): Unit = { 8 | assertEquals(("a", "b c d"), MarkdownConverter.splitWikiLink("a b c d")) 9 | assertEquals(("a", "b\\ c d"), MarkdownConverter.splitWikiLink("a b\\ c d")) 10 | assertEquals(("a\\ b", "c d"), MarkdownConverter.splitWikiLink("a\\ b c d")) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/scala/dotty/dokka/tasty/comments/QueryParserTests.scala: -------------------------------------------------------------------------------- 1 | package dotty.dokka.tasty.comments 2 | 3 | import org.junit.{Test, Rule} 4 | import org.junit.Assert.{assertSame, assertTrue, assertEquals} 5 | 6 | class QueryParserTests { 7 | @Test def test() = { 8 | import Query._ 9 | 10 | def l2q(shorthand: ((String | Qual), Char)*)(last: String): QuerySegment = { 11 | if shorthand.isEmpty then Query.Id(last) else { 12 | val head = shorthand.head 13 | val tail = shorthand.tail 14 | head match { 15 | case ((id: String), ch) => Query.QualifiedId(Query.Qual.Id(id), ch, l2q(tail : _*)(last)) 16 | case ((qual: Qual), ch) => Query.QualifiedId(qual, ch, l2q(tail : _*)(last)) 17 | } 18 | } 19 | } 20 | 21 | extension [A <: String | Qual](self: A) def dot = (self, '.') 22 | extension [A <: String | Qual](self: A) def hash = (self, '#') 23 | 24 | testSuccess("#abc", StrictMemberId("abc")) 25 | testSuccess("a.b.c#d", l2q("a".dot, "b".dot, "c".hash)("d")) 26 | 27 | testSuccess("`a.b c#d`", Id("a.b c#d")) 28 | testSuccess("#`a.b c#d`", StrictMemberId("a.b c#d")) 29 | 30 | testSuccess("a.`b.c#d e`.g", l2q("a".dot, "b.c#d e".dot)("g")) 31 | testSuccess("a.`b.c#d e`#g", l2q("a".dot, "b.c#d e".hash)("g")) 32 | 33 | testSuccess("this.foo", l2q(Qual.This.dot)("foo")) 34 | testSuccess("package.foo", l2q(Qual.Package.dot)("foo")) 35 | 36 | testSuccess("`this`.foo", l2q("this".dot)("foo")) 37 | testSuccess("`package`.foo", l2q("package".dot)("foo")) 38 | 39 | testSuccess("#foo(ignoredOverloadDefinition*", StrictMemberId("foo")) 40 | testSuccess("#bar[ignoredOverloadDefinition*", StrictMemberId("bar")) 41 | 42 | testSuccess("\\#abc", Id("#abc")) 43 | testSuccess("a\\.b", Id("a.b")) 44 | testSuccess("a\\#b", Id("a#b")) 45 | testSuccess("ab\\ ", Id("ab ")) 46 | 47 | testSuccess("#foo\\(ignoredOverloadDefinition*", StrictMemberId("foo(ignoredOverloadDefinition*")) 48 | testSuccess("#bar\\[ignoredOverloadDefinition*", StrictMemberId("bar[ignoredOverloadDefinition*")) 49 | 50 | testFailAt("#", 1) 51 | testFailAt("#`", 2) 52 | testFailAt("``", 2) 53 | testFailAt("`abc", 4) 54 | 55 | testFailAt("ab..cd", 3) 56 | testFailAt("ab.#cd", 3) 57 | testFailAt("ab#.cd", 3) 58 | 59 | testFailAt("\\`", 1) 60 | testFailAt("ab\\`", 3) 61 | } 62 | 63 | private def parse(input: String) = QueryParser(input).tryReadQuery() 64 | 65 | private def testSuccess(input: String, expected: Query) = { 66 | val Right(got) = parse(input) 67 | assertEquals(expected, got) 68 | } 69 | 70 | private def testFailAt(input: String, char: Int) = { 71 | val Left(err) = parse(input) 72 | assertEquals(s"expected to fail at $char : $input", char, err.at) 73 | } 74 | } 75 | --------------------------------------------------------------------------------