Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tpolecat committed Jan 4, 2021
0 parents commit 2b4e5d5
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Release
on:
push:
branches: [cli]
tags: ["*"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: olafurpg/setup-scala@v10
- uses: coursier/cache-action@v3
- uses: olafurpg/setup-gpg@v3
- run: sbt ci-release
env:
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
PGP_SECRET: ${{ secrets.PGP_SECRET }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
10 changes: 10 additions & 0 deletions .github/workflows/scala.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: olafurpg/setup-scala@v10
- uses: coursier/cache-action@v3
- run: sbt clean headerCheck +test
52 changes: 52 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
*.class
*.log

# these are moved into the doc project by the build
modules/docs/src/main/tut/changelog.md
modules/docs/src/main/tut/license.md

# sbt specific
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/
project/hydra.sbt

# Scala-IDE specific
.scala_dependencies
.cache
.classpath
.project
.worksheet/
.settings/

# OS X
.DS_Store

# Ctags
.tags

# ENSIME
.ensime
.ensime_cache/

# IntelliJ
.idea/

# Mill
out/

# Bloop/Metals/vscode
.bloop/
.metals/
.vscode/
metals.sbt

# Transient workspace
modules/docs/src/main/scala/
*.worksheet.sc

# bsp
.bsp/
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2020 by Rob Norris

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SourcePos

This is a Scala micro-library that provides:

- a `SourcePos` class that specifies a source file and line number, and
- an implicit macro that forges a `SourcePos` at the call site if none is available.

SourcePos is compiled for Scala **2.12**, **2.13**, and **3.0** (see release notes for exact versions).


```scala
libraryDependencies += "org.tpolecat" %% "sourcepos" % <version>
```

#### Example

If you want to know where a method call originated, demand an implicit `SourcePos`. It has fields for both `file` and `line`, and a `toString` that prints them as `<file>:<line>`, which most editors will hyperlink for you.

```scala
import org.tpolecat.sourcepos._

object Example {

def method(n: Int)(implicit sp: SourcePos): String =
s"You called me with $n from $sp"

def main(args: Array[String]): Unit =
println(method(42))

}
```

Running this program on my computer yields:

```
You called me with 42 from /Users/rnorris/Scala/SourcePos/src/test/scala/Example.scala:9
```


73 changes: 73 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

// Our Scala versions.
lazy val `scala-3.0` = "3.0.0-M3"
lazy val `scala-3.0-prev` = "3.0.0-M2"
lazy val `scala-2.12` = "2.12.12"
lazy val `scala-2.13` = "2.13.3"

// Publishing
name := "sourcepos"
organization := "org.tpolecat"
licenses ++= Seq(("MIT", url("http://opensource.org/licenses/MIT")))
homepage := Some(url("https://github.com/tpolecat/sourcepos"))
developers := List(
Developer("tpolecat", "Rob Norris", "[email protected]", url("http://www.tpolecat.org"))
)

// Headers
headerMappings := headerMappings.value + (HeaderFileType.scala -> HeaderCommentStyle.cppStyleLineComment)
headerLicense := Some(HeaderLicense.Custom(
"""|Copyright (c) 2020 by Rob Norris
|This software is licensed under the MIT License (MIT).
|For more information see LICENSE or https://opensource.org/licenses/MIT
|""".stripMargin
)
)

// Compilation
scalaVersion := `scala-2.13`
crossScalaVersions := Seq(`scala-2.12`, `scala-2.13`, `scala-3.0-prev`, `scala-3.0`)
Compile / doc / scalacOptions --= Seq("-Xfatal-warnings")
Compile / doc / scalacOptions ++= Seq(
"-groups",
"-sourcepath", (baseDirectory in LocalRootProject).value.getAbsolutePath,
"-doc-source-url", "https://github.com/tpolecat/sourcepos/blob/v" + version.value + "€{FILE_PATH}.scala",
)

// MUnit
libraryDependencies += "org.scalameta" %% "munit" % "0.7.20" % Test
testFrameworks += new TestFramework("munit.Framework")

// Scala 2 needs scala-reflect
libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value).filterNot(_ => isDotty.value)

// Add some more source directories
unmanagedSourceDirectories in Compile ++= {
val sourceDir = (sourceDirectory in Compile).value
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq(sourceDir / "scala-3")
case Some((2, _)) => Seq(sourceDir / "scala-2")
case _ => Seq()
}
}

// Also for test
unmanagedSourceDirectories in Test ++= {
val sourceDir = (sourceDirectory in Test).value
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq(sourceDir / "scala-3")
case Some((2, _)) => Seq(sourceDir / "scala-2")
case _ => Seq()
}
}

// dottydoc really doesn't work at all right now
Compile / doc / sources := {
val old = (Compile / doc / sources).value
if (isDotty.value)
Seq()
else
old
}

enablePlugins(AutomateHeaderPlugin)
1 change: 1 addition & 0 deletions project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.4.6
10 changes: 10 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.5")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0")
addSbtPlugin("com.lightbend.paradox" % "sbt-paradox" % "0.9.1")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.1")
addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.16")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.14")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1")
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.1")
1 change: 1 addition & 0 deletions project/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.4.3")
21 changes: 21 additions & 0 deletions src/main/scala-2/SourcePosPlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package org.tpolecat.sourcepos

import scala.reflect.macros.blackbox

trait SourcePosPlatform {
implicit def instance: SourcePos =
macro SourcePosPlatform.sourcePos_impl
}

object SourcePosPlatform {
def sourcePos_impl(c: blackbox.Context): c.Tree = {
import c.universe._
val file = c.enclosingPosition.source.path
val line = c.enclosingPosition.line
q"_root_.org.tpolecat.sourcepos.SourcePos($file, $line)"
}
}
25 changes: 25 additions & 0 deletions src/main/scala-3.0.0-M2/SourcPosPlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package org.tpolecat.sourcepos

import scala.quoted._

trait SourcePosPlatform {

implicit inline def instance: SourcePos =
${SourcePosPlatform.sourcePos_impl}

}

object SourcePosPlatform {

def sourcePos_impl(using ctx: Quotes): Expr[SourcePos] = {
val rootPosition = ctx.reflect.Position.ofMacroExpansion
val file = Expr(rootPosition.sourceFile.jpath.toString)
val line = Expr(rootPosition.startLine + 1)
'{SourcePos($file, $line)}
}

}
25 changes: 25 additions & 0 deletions src/main/scala-3.0.0-M3/SourcPosPlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package org.tpolecat.sourcepos

import scala.quoted._

trait SourcePosPlatform {

implicit inline def instance: SourcePos =
${SourcePosPlatform.sourcePos_impl}

}

object SourcePosPlatform {

def sourcePos_impl(using ctx: Quotes): Expr[SourcePos] = {
val rootPosition = ctx.reflect.Position.ofMacroExpansion
val file = Expr(rootPosition.sourceFile.jpath.toString)
val line = Expr(rootPosition.startLine + 1)
'{SourcePos($file, $line)}
}

}
12 changes: 12 additions & 0 deletions src/main/scala/SourcePos.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package org.tpolecat.sourcepos

final case class SourcePos(file: String, line: Int) {
override def toString =
s"$file:$line"
}

object SourcePos extends SourcePosPlatform
15 changes: 15 additions & 0 deletions src/test/scala/Example.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

import org.tpolecat.sourcepos._

object Example {

def method(n: Int)(implicit sp: SourcePos): String =
s"You called me with $n from $sp"

def main(args: Array[String]): Unit =
println(method(42))

}
17 changes: 17 additions & 0 deletions src/test/scala/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package test

import org.tpolecat.sourcepos._

class Test extends munit.FunSuite {

test("pos") {
val pos = implicitly[SourcePos]
assert(pos.file.endsWith("src/test/scala/Test.scala"))
assert(pos.line == 12)
}

}

0 comments on commit 2b4e5d5

Please sign in to comment.