Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Bartosz Bąbol
    @BBartosz

    @BBartosz you can generate programs by constructing trees and printing them with Scalameta. Macros allow you to do roughly the same thing, except you do it during the compilation of your program

    How exactly you generate them? I understand that you use quasiquotes to build your tree and then you save it to file, kinda like string?

    Roman Janusz
    @ghik
    @BBartosz yes, this way. You cannot generate programs with scalameta "on the fly", that is in compile time like macros.
    Bartosz Bąbol
    @BBartosz

    @BBartosz yes, this way. You cannot generate programs with scalameta "on the fly", that is in compile time like macros.

    yeah thx i was wondering whats the way to do it. I was using quasiquotes and macros but generating the code and saving it to file might also work for me

    sandeshyapuram
    @pandareen
    Is there a better way to kick off code generation? I am using Scala Annotations for pointing it towards scalameta to generate new codee.
    Ólafur Páll Geirsson
    @olafurpg
    @pandareen if you are generating source code as strings, I would recommend using something like treehugger instead http://eed3si9n.com/treehugger/
    vito-c
    @vito-c
    @olafurpg would treehugger be something we could use for refactoring as well? right now I am using patch like this:
            Patch.replaceTree(
              someTree,
              "val foo:SomeType = new Thing(1, 2,3)"
            )
    Charlie Hills
    @contagnas

    Hi all, wondering if someone could clarify the behavior of the semanticdb-scalac plugin for me. I'm running this command:

    $ ~/Downloads/scala-2.13.1/bin/scalac -Xplugin:$(realpath ~/Downloads/semanticdb-scalac_2.13.1-4.3.0.jar) -Yrangepos -Xplugin-require:semanticdb HelloWorld.scala

    I'm expecting to see semanticdb files in META-INF/semanticdb, but I do not. In fact, if I create the META-INF/semanticdb directory before running the above command, the semanticdb directory is deleted.

    Ondra Pelech
    @sideeffffect
    Hello, is there an integration between ScalaMeta/SemanticDB and Kythe?
    Muhammad Tabaza
    @Tabzz98
    Hi guys!
    Is there a way pass a Source to scala.tools.reflect.ToolBox.eval()?
    sandeshyapuram
    @pandareen
    Hello guys, what is the latest method to design frameworks that overcome Type Erasures? Does scalameta aim to solve this?
    I wouldn't want to use scala reflection as it's experimental
    Ólafur Páll Geirsson
    @olafurpg
    @contagnas it looks like you need the targetroot option as well
    ❯ cs launch scala:2.13.1 -- -Xplugin:$(cs fetch --intransitive org.scalameta:semanticdb-scalac_2.13.1:4.3.7) -Yrangepos -Xplugin-require:semanticdb -P:semanticdb:targetroot:$(pwd) foo.scala
    ❯ tree
    .
    ├── foo.scala
    └── META-INF
       └── semanticdb
          └── foo.scala.semanticdb
    where cs is coursier from https://get-coursier.io/docs/cli-overview
    @sideeffffect there's no published integration with kythe, i recall somebody implemented something a couple years ago but it didn't end up going anywhere I think
    @Tabzz98 Source.toString gives you the code that you can feed to eval
    @pandareen scalameta does not provide any features for runtime reflection. The only alternatives I'm aware of are scala/java runtime reflection
    Muhammad Tabaza
    @Tabzz98
    @olafurpg Ah, of course. I don't know why I didn't consider a solution where the parsing is done twice. All I had in mind was converting the whole tree. Thanks a lot!
    Ondra Pelech
    @sideeffffect
    @olafurpg thanks for the info
    Dale Wijnand
    @dwijnand
    Am I right in saying that there's information missing in the following, to link an eta-expansion to the method it expands?
    trait NullaryEtaExpansionScala[A] {
      def prop: A
      def meth(): A
    
      def def_prop = prop _
      def def_meth = meth _
    }
    $ type metac
    metac is aliased to `coursier launch org.scalameta:metac_2.12.11:4.3.7 -- -cp /Users/dnw/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.11/scala-library-2.12.11.jar'
    
    $ type metap
    metap is aliased to `coursier launch -M scala.meta.cli.Metap org.scalameta:scalameta_2.12:4.3.7 --'
    
    $ metac -P:semanticdb:synthetics:on NullaryEtaExpansionScala.scala
    
    $ tree META-INF/
    META-INF/
    └── semanticdb
        └── NullaryEtaExpansionScala.scala.semanticdb
    
    1 directory, 1 file
    
    $ metap .
    NullaryEtaExpansionScala.scala
    ------------------------------
    
    Summary:
    Schema => SemanticDB v4
    Uri => NullaryEtaExpansionScala.scala
    Text => empty
    Language => Scala
    Symbols => 6 entries
    Occurrences => 10 entries
    
    Symbols:
    _empty_/NullaryEtaExpansionScala# => trait NullaryEtaExpansionScala[A] extends AnyRef { +4 decls }
    _empty_/NullaryEtaExpansionScala#[A] => typeparam A
    _empty_/NullaryEtaExpansionScala#def_meth(). => method def_meth: Function0[A]
    _empty_/NullaryEtaExpansionScala#def_prop(). => method def_prop: Function0[A]
    _empty_/NullaryEtaExpansionScala#meth(). => abstract method meth(): A
    _empty_/NullaryEtaExpansionScala#prop(). => abstract method prop: A
    
    Occurrences:
    [0:6..0:30) <= _empty_/NullaryEtaExpansionScala#
    [0:31..0:32) <= _empty_/NullaryEtaExpansionScala#[A]
    [1:6..1:10) <= _empty_/NullaryEtaExpansionScala#prop().
    [1:12..1:13) => _empty_/NullaryEtaExpansionScala#[A]
    [2:6..2:10) <= _empty_/NullaryEtaExpansionScala#meth().
    [2:14..2:15) => _empty_/NullaryEtaExpansionScala#[A]
    [4:6..4:14) <= _empty_/NullaryEtaExpansionScala#def_prop().
    [4:17..4:21) => local0
    [5:6..5:14) <= _empty_/NullaryEtaExpansionScala#def_meth().
    [5:17..5:21) => local1
    $
    There's no reference occurrence of prop(). and no link from symbol local0, right?
    Damien Favre
    @benderpremier

    Hi :wave: , I am wondering if it's possible to generate type parameters that are literal type.
    I am trying to do

    Type.Apply(Type.Name("Bytes"), List(Type.Name("32")))

    but when calling .syntax I am getting

    Bytes[`32`] 
    \\instead of 
    Bytes[32]
    Ólafur Páll Geirsson
    @olafurpg
    @benderpremier what happens if you use Lit.Int(32)?
    Dale Wijnand
    @dwijnand
    $ m Foo.java
    package pkg;
    
    interface Foo {
      String foo();
    }
    
    $ m scratch.scala
    package pkg
    
    class CM extends Foo { def foo() = "" }
    class CP extends Foo { def foo   = "" }
    
    $ l
    .
    ├── [  48]  Foo.java
    └── [  93]  scratch.scala
    
    0 directories, 2 files
    
    $ metac Foo.java scratch.scala
    
    $ metap .
    scratch.scala
    -------------
    
    Summary:
    Schema => SemanticDB v4
    Uri => scratch.scala
    Text => empty
    Language => Scala
    Symbols => 6 entries
    Occurrences => 11 entries
    
    Symbols:
    pkg/CM# => class CM extends Object with Foo { +2 decls }
    pkg/CM#`<init>`(). => primary ctor <init>()
    pkg/CM#foo(). => method foo(): String
    pkg/CP# => class CP extends Object with Foo { +2 decls }
    pkg/CP#`<init>`(). => primary ctor <init>()
    pkg/CP#foo(). => method foo(): String
    
    Occurrences:
    [0:8..0:11) <= pkg/
    [2:6..2:8) <= pkg/CM#
    [2:9..2:9) <= pkg/CM#`<init>`().
    [2:17..2:20) => pkg/Foo#
    [2:21..2:21) => java/lang/Object#`<init>`().
    [2:27..2:30) <= pkg/CM#foo().
    [3:6..3:8) <= pkg/CP#
    [3:9..3:9) <= pkg/CP#`<init>`().
    [3:17..3:20) => pkg/Foo#
    [3:21..3:21) => java/lang/Object#`<init>`().
    [3:27..3:30) <= pkg/CP#foo().
    Is there no information in the Semanticdb that that the foo method in CM and CP is implementing/overridingFoo#foo().?
    Even in the all-Scala, 1-file version:
    $ m scratch.scala
    package pkg
    
    trait Foo { def foo(): String }
    
    class CM extends Foo { def foo() = "" }
    class CP extends Foo { def foo   = "" }
    
    $ metap .
    scratch.scala
    -------------
    
    Summary:
    Schema => SemanticDB v4
    Uri => scratch.scala
    Text => empty
    Language => Scala
    Symbols => 8 entries
    Occurrences => 14 entries
    
    Symbols:
    pkg/CM# => class CM extends AnyRef with Foo { +2 decls }
    pkg/CM#`<init>`(). => primary ctor <init>()
    pkg/CM#foo(). => method foo(): String
    pkg/CP# => class CP extends AnyRef with Foo { +2 decls }
    pkg/CP#`<init>`(). => primary ctor <init>()
    pkg/CP#foo(). => method foo(): String
    pkg/Foo# => trait Foo extends AnyRef { +1 decls }
    pkg/Foo#foo(). => abstract method foo(): String
    
    Occurrences:
    [0:8..0:11) <= pkg/
    [2:6..2:9) <= pkg/Foo#
    [2:16..2:19) <= pkg/Foo#foo().
    [2:23..2:29) => scala/Predef.String#
    [4:6..4:8) <= pkg/CM#
    [4:9..4:9) <= pkg/CM#`<init>`().
    [4:17..4:20) => pkg/Foo#
    [4:21..4:21) => java/lang/Object#`<init>`().
    [4:27..4:30) <= pkg/CM#foo().
    [5:6..5:8) <= pkg/CP#
    [5:9..5:9) <= pkg/CP#`<init>`().
    [5:17..5:20) => pkg/Foo#
    [5:21..5:21) => java/lang/Object#`<init>`().
    [5:27..5:30) <= pkg/CP#foo().
    I'm assuming metap outputs all the information available.
    Is it up to the client to traverse [4:17..4:20) => pkg/Foo# to determine if the method is implementing/overriding??
    Dale Wijnand
    @dwijnand
    I say "traverse [4:17..4:20) => pkg/Foo#" but I mean that using the existing scalameta/scalafix infrastructure, is the logic client-side?
    Damien Favre
    @benderpremier
    @olafurpg if I use Type.Apply(Type.Name("Bytes"), List(Lit.Int(32))) I get that exception
    Exception in thread "main" org.scalameta.invariants.InvariantFailedException: invariant failed:
    when verifying og.categories.intersect[String](ig.categories).nonEmpty
    found that og.categories.intersect[String](ig.categories).nonEmpty is false
    where ig = Literal
    where og = Typ
    Ólafur Páll Geirsson
    @olafurpg
    @dwijnand SemanticDB doesn't include override information at the moment
    Metals builds a symbol table and computes the overrides on the fly to power symbol rename and find references.
    That doesn't help you in Scalafix however
    I am tempted introduce it at some point in the near-ish future to unblock remote language servers https://scalameta.org/metals/docs/contributors/remote-language-server.html
    another alternative is to spin up a presentation compiler to query overrides
    but it has the caveat that it currently only works with 2.12.11 (not 2.13.x or even 2.12.10)
    Dale Wijnand
    @dwijnand
    So that's: it only works when the code is compiled with scalac 2.12.11? That might be ok, I think. Thanks for the link!
    @olafurpg how about the eta-expansion one, do you know if/how I can get the info on the thing being eta-expanded?
    Ólafur Páll Geirsson
    @olafurpg
    @dwijnand I'm able to reproduce the eta expansion issue
    it's probably an easy fix
    if somebody want to contribute :wink:
    Dale Wijnand
    @dwijnand
    Can you share your reproduction and where the easy fix is? I'm happy to try to push it over the line.
    Ólafur Páll Geirsson
    @olafurpg
    @dwijnand
    metals/target/scrooge on 🌱 ttl took 5s
    ❯ cat repro.scala
    trait NullaryEtaExpansionScala[A] {
      def prop: A
      def meth(): A
    
      def def_prop = prop _
      def def_meth = meth _
    }
    
    metals/target/scrooge on 🌱 ttl
    ❯ cs launch scala:2.12.11 -- -Xplugin:$(cs fetch --intransitive org.scalameta:semanticdb-scalac_2.12.11:4.3.7) -Yrangepos -Xplugin-require:semanticdb -P:semanticdb:targetroot:$(pwd) $(pwd)/repro.scala
    
    metals/target/scrooge on 🌱 ttl
    ❯ cs launch metap -- .
    repro.scala
    -----------
    
    Summary:
    Schema => SemanticDB v4
    Uri => repro.scala
    Text => empty
    Language => Scala
    Symbols => 6 entries
    Occurrences => 10 entries
    
    Symbols:
    _empty_/NullaryEtaExpansionScala# => trait NullaryEtaExpansionScala[A] extends AnyRef { +4 decls }
    _empty_/NullaryEtaExpansionScala#[A] => typeparam A
    _empty_/NullaryEtaExpansionScala#def_meth(). => method def_meth: Function0[A]
    _empty_/NullaryEtaExpansionScala#def_prop(). => method def_prop: Function0[A]
    _empty_/NullaryEtaExpansionScala#meth(). => abstract method meth(): A
    _empty_/NullaryEtaExpansionScala#prop(). => abstract method prop: A
    
    Occurrences:
    [0:6..0:30) <= _empty_/NullaryEtaExpansionScala#
    [0:31..0:32) <= _empty_/NullaryEtaExpansionScala#[A]
    [1:6..1:10) <= _empty_/NullaryEtaExpansionScala#prop().
    [1:12..1:13) => _empty_/NullaryEtaExpansionScala#[A]
    [2:6..2:10) <= _empty_/NullaryEtaExpansionScala#meth().
    [2:14..2:15) => _empty_/NullaryEtaExpansionScala#[A]
    [4:6..4:14) <= _empty_/NullaryEtaExpansionScala#def_prop().
    [4:17..4:21) => local0
    [5:6..5:14) <= _empty_/NullaryEtaExpansionScala#def_meth().
    [5:17..5:21) => local1
    And expected behavior
    
    Occurrences:
    [0:6..0:30) <= _empty_/NullaryEtaExpansionScala#
    [0:31..0:32) <= _empty_/NullaryEtaExpansionScala#[A]
    [1:6..1:10) <= _empty_/NullaryEtaExpansionScala#prop().
    [1:12..1:13) => _empty_/NullaryEtaExpansionScala#[A]
    [2:6..2:10) <= _empty_/NullaryEtaExpansionScala#meth().
    [2:14..2:15) => _empty_/NullaryEtaExpansionScala#[A]
    [4:6..4:14) <= _empty_/NullaryEtaExpansionScala#def_prop().
    -[4:17..4:21) => local0
    +[4:17..4:21) => _empty_/NullaryEtaExpansionScala#prop().
    [5:6..5:14) <= _empty_/NullaryEtaExpansionScala#def_meth().
    -[4:17..4:21) => local1
    +[4:17..4:21) => _empty_/NullaryEtaExpansionScala#prop().
    TextDocumentOps.scala would be the place to look at
    Dale Wijnand
    @dwijnand
    Cool, thanks.
    then once it's fixed, add some tests for ExpectSuite
    Dale Wijnand
    @dwijnand
    Excellent, thanks.
    Cheng Lian
    @liancheng

    Hi everyone! Got a question about pretty-printing. By default, when printing a importer with multiple importees, scalameta inserts spaces within the braces:

    import $ivy.`org.scalameta::scalameta:4.3.7`, scala.meta._
    
    q"import java.time.{Clock, Duration}".syntax
    // res13: String = "import java.time.{ Clock, Duration }"

    How can I customize the pretty-printer to remove those two spaces? I tried to override the syntaxImportee implicit function defined here, but got "ambiguous implicit values" errors:

    import $ivy.`org.scalameta::scalameta:4.3.7`, scala.meta._
    
    import scala.meta.prettyprinters.Show.{repeat, sequence}
    import scala.meta.prettyprinters.Syntax
    
    implicit def syntaxImporter: Syntax[List[Importee]] = Syntax {
      case (t: Importee.Name) :: Nil     => sequence(t)
      case (t: Importee.Wildcard) :: Nil => sequence(t)
      case (t: Importee.Rename) :: Nil   => sequence("{", t, "}")
      case importees                     => sequence("{", repeat(importees, ", "), "}")
    }
    
    q"import java.time.{Clock, Duration}".syntax
    // cmd18.sc:2: ambiguous implicit values:
    //  both method showStructure in object Tree of type [T <: scala.meta.Tree]=> scala.meta.prettyprinters.Structure[T]
    //  and method showSyntax in object Tree of type [T <: scala.meta.Tree](implicit dialect: scala.meta.Dialect)scala.meta.prettyprinters.Syntax[T]
    //  match expected type scala.meta.prettyprinters.Show[scala.meta.Importee.Name]
    //   case (t: Importee.Name) :: Nil     => sequence(t)
    //        ^
    // cmd18.sc:2: don't know how to print value of type scala.meta.Importee.Name
    //   case (t: Importee.Name) :: Nil     => sequence(t)
    //
    // ...

    Kinda lost in the forest of implicits...

    Ólafur Páll Geirsson
    @olafurpg
    @liancheng there’s no way to customize the pretty printer. You can run Scalafmt on the output code to tweak the formatting.