Skip to content

Commit 2911c99

Browse files
authored
Merge pull request #321 from AVSystem/dimplicit
Minimalistic dependency injection with parallel initialization
2 parents a5f89ed + cff0ea7 commit 2911c99

File tree

27 files changed

+1071
-39
lines changed

27 files changed

+1071
-39
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
strategy:
2525
matrix:
2626
os: [ubuntu-latest]
27-
scala: [2.13.4, 2.12.13]
27+
scala: [2.13.4, 2.12.12]
2828
java: [adopt@1.11]
2929
runs-on: ${{ matrix.os }}
3030
steps:
@@ -127,12 +127,12 @@ jobs:
127127
tar xf targets.tar
128128
rm targets.tar
129129
130-
- name: Download target directories (2.12.13)
130+
- name: Download target directories (2.12.12)
131131
uses: actions/download-artifact@v2
132132
with:
133-
name: target-${{ matrix.os }}-2.12.13-${{ matrix.java }}
133+
name: target-${{ matrix.os }}-2.12.12-${{ matrix.java }}
134134

135-
- name: Inflate target directories (2.12.13)
135+
- name: Inflate target directories (2.12.12)
136136
run: |
137137
tar xf targets.tar
138138
rm targets.tar

.idea/codeStyles/Project.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ inThisBuild(Seq(
5353
Developer("ghik", "Roman Janusz", "r.janusz@avsystem.com", url("https://github.com/ghik")),
5454
),
5555

56-
crossScalaVersions := Seq("2.13.4", "2.12.13"),
56+
crossScalaVersions := Seq("2.13.4", "2.12.12"),
5757
scalaVersion := crossScalaVersions.value.head,
5858
compileOrder := CompileOrder.Mixed,
5959

commons-analyzer/src/main/scala/com/avsystem/commons/analyzer/AnalyzerPlugin.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ final class AnalyzerPlugin(val global: Global) extends Plugin { plugin =>
5555
new CheckBincompat(global),
5656
new Any2StringAdd(global),
5757
new ThrowableObjects(global),
58-
new DiscardedMonixTask(global)
58+
new DiscardedMonixTask(global),
59+
new BadSingletonComponent(global)
5960
)
6061

6162
private lazy val rulesByName = rules.map(r => (r.name, r)).toMap
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.avsystem.commons
2+
package analyzer
3+
4+
import scala.annotation.tailrec
5+
import scala.tools.nsc.Global
6+
7+
class BadSingletonComponent(g: Global) extends AnalyzerRule(g, "badSingletonComponent") {
8+
9+
import global._
10+
11+
lazy val componentsTpe: Type = classType("com.avsystem.commons.di.Components")
12+
lazy val cachedSym: Symbol = componentsTpe.member(TermName("cached"))
13+
14+
object UnwrapApply {
15+
@tailrec def unapply(tree: Tree): Some[Tree] = tree match {
16+
case Apply(fun, _) => unapply(fun)
17+
case TypeApply(fun, _) => unapply(fun)
18+
case t => Some(t)
19+
}
20+
}
21+
22+
object Unwrap {
23+
@tailrec def unapply(t: Tree): Some[Tree] = t match {
24+
case Block(Nil, expr) => unapply(expr)
25+
case Typed(expr, _) => unapply(expr)
26+
case Annotated(_, expr) => unapply(expr)
27+
case UnwrapApply(Select(prefix, _)) if prefix.tpe =:= t.tpe => unapply(prefix)
28+
case _ => Some(t)
29+
}
30+
}
31+
32+
def analyze(unit: CompilationUnit): Unit =
33+
if (componentsTpe != NoType) {
34+
object traverser extends Traverser {
35+
override def traverse(tree: Tree): Unit = tree match {
36+
case mdef@DefDef(_, _, Nil, Nil, _, Unwrap(app@Apply(_, List(arg, _))))
37+
if app.symbol == cachedSym && mdef.symbol.owner.isClass && ThisType(mdef.symbol.owner) <:< componentsTpe =>
38+
traverse(arg)
39+
case t if t.symbol == cachedSym =>
40+
report(t.pos, "singleton(...) macro can only be used as a body of a parameterless method in a Components trait implementation")
41+
case _ =>
42+
super.traverse(tree)
43+
}
44+
}
45+
46+
traverser.traverse(unit.body)
47+
}
48+
}

commons-analyzer/src/test/scala/com/avsystem/commons/analyzer/AnalyzerTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import scala.tools.nsc.{Global, Settings}
1111
trait AnalyzerTest { this: Assertions =>
1212
val settings = new Settings
1313
settings.usejavacp.value = true
14+
settings.Yrangepos.value = true
1415
settings.pluginOptions.value ++= List("AVSystemAnalyzer:+_")
1516

1617
val compiler: Global = new Global(settings) { global =>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.avsystem.commons
2+
package analyzer
3+
4+
import org.scalatest.funsuite.AnyFunSuite
5+
6+
class BadSingletonComponentTest extends AnyFunSuite with AnalyzerTest {
7+
test("general") {
8+
assertErrors(5,
9+
"""
10+
|import com.avsystem.commons.di._
11+
|
12+
|object test extends Components {
13+
| singleton(123)
14+
| val notDef = singleton(123)
15+
| def hasParams(param: Int) = singleton(param)
16+
| def hasTypeParams[T]: Component[T] = singleton(???)
17+
| def outerMethod: Component[Int] = {
18+
| def innerMethod = singleton(123)
19+
| innerMethod
20+
| }
21+
|
22+
| def good: Component[Int] = singleton(123)
23+
| def alsoGood: Component[Int] = { singleton(123) }
24+
| def goodAsWell: Component[Int] = singleton(123).dependsOn(good)
25+
|}
26+
""".stripMargin
27+
)
28+
}
29+
}

commons-core/jvm/src/main/scala/com/avsystem/commons/concurrent/BlockingUtils.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ abstract class BlockingUtils {
5555
runAndAwait(task, FiniteDuration(timeout, unit))
5656

5757
def runAndAwait[T](task: Task[T], timeout: Duration): T =
58-
Await.result(task.runToFuture, timeout)
58+
task.runSyncUnsafe(timeout)
5959

6060
// overloading instead of using default value so that it's usable from Java
6161
def toIterator[T](observable: Observable[T]): CloseableIterator[T] =

commons-core/src/main/scala/com/avsystem/commons/SharedExtensions.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,14 @@ object SharedExtensionsUtils extends SharedExtensions {
240240
def stripCommonIndent: String =
241241
if (str.isEmpty) str
242242
else {
243-
val commonIndentLength = str.linesIterator.map(_.indexWhere(_ != ' ')).min
244-
str.linesIterator.map(_.substring(commonIndentLength)).mkString("\n")
243+
val commonIndentLength = str.linesIterator
244+
.map(l => l.indexWhere(_ != ' '))
245+
.map(i => if (i < 0) Int.MaxValue else i)
246+
.min
247+
248+
str.linesIterator
249+
.map(l => l.substring(math.min(commonIndentLength, l.length)))
250+
.mkString("\n")
245251
}
246252
}
247253

0 commit comments

Comments
 (0)