Skip to content

Commit

Permalink
Merge pull request #1982 from lvitaly/feature/lift-mapper-scala-2.13
Browse files Browse the repository at this point in the history
Lift-mapper with Scala 2.13 support
  • Loading branch information
farmdawgnation committed Jun 11, 2020
2 parents d221782 + 8f76920 commit 2c522a3
Show file tree
Hide file tree
Showing 65 changed files with 1,792 additions and 667 deletions.
12 changes: 6 additions & 6 deletions .travis.yml
Expand Up @@ -3,8 +3,8 @@ dist: trusty
sudo: false
scala:
- 2.11.12
- 2.12.10
- 2.13.1
- 2.12.11
- 2.13.2
cache:
directories:
- '$HOME/node_modules'
Expand All @@ -15,16 +15,16 @@ jdk:
- openjdk8
matrix:
include:
- scala: 2.12.10
- scala: 2.12.11
jdk: openjdk11
env: DISABLE_PUBLISH=true
- scala: 2.12.10
- scala: 2.12.11
jdk: openjdk12
env: DISABLE_PUBLISH=true
- scala: 2.13.1
- scala: 2.13.2
jdk: openjdk11
env: DISABLE_PUBLISH=true
- scala: 2.13.1
- scala: 2.13.2
jdk: openjdk12
env: DISABLE_PUBLISH=true
script: ./travis.sh
Expand Down
15 changes: 9 additions & 6 deletions build.sbt
Expand Up @@ -9,16 +9,18 @@ startYear in ThisBuild := Some(2006)
organizationName in ThisBuild := "WorldWide Conferencing, LLC"

val scala211Version = "2.11.12"
val scala212Version = "2.12.10"
val scala213Version = "2.13.1"
val scala212Version = "2.12.11"
val scala213Version = "2.13.2"

val crossUpTo212 = Seq(scala212Version, scala211Version)
val crossUpTo213 = scala213Version +: crossUpTo212

scalaVersion in ThisBuild := scala212Version
crossScalaVersions in ThisBuild := crossUpTo212 // default everyone to 2.12 for now

libraryDependencies in ThisBuild ++= Seq(specs2, specs2Matchers, specs2Mock, scalacheck, scalatest)
libraryDependencies in ThisBuild ++= Seq(specs2, specs2Matchers, specs2Mock, scalacheck, scalactic, scalatest)

scalacOptions in ThisBuild ++= Seq("-deprecation")

// Settings for Sonatype compliance
pomIncludeRepository in ThisBuild := { _ => false }
Expand Down Expand Up @@ -77,7 +79,7 @@ lazy val markdown =
.settings(
description := "Markdown Parser",
parallelExecution in Test := false,
libraryDependencies ++= Seq(scalatest, junit, scala_xml, scala_parser)
libraryDependencies ++= Seq(scalatest, scalatest_junit, scala_xml, scala_parser)
)
.settings(crossScalaVersions := crossUpTo213)

Expand Down Expand Up @@ -160,7 +162,7 @@ lazy val webkit =
specs2MatchersProv,
jetty6,
jwebunit,
mockito_all,
mockito_scalatest,
jquery,
jasmineCore,
jasmineAjax
Expand Down Expand Up @@ -216,7 +218,7 @@ lazy val persistence: Seq[ProjectReference] =
lazy val db =
persistenceProject("db")
.dependsOn(util, webkit)
.settings(libraryDependencies += mockito_all)
.settings(libraryDependencies += mockito_scalatest)
.settings(crossScalaVersions := crossUpTo213)

lazy val proto =
Expand All @@ -238,6 +240,7 @@ lazy val mapper =
)
}
)
.settings(crossScalaVersions := crossUpTo213)

lazy val record =
persistenceProject("record")
Expand Down
Expand Up @@ -19,7 +19,7 @@ package net.liftweb.markdown
* Christoph Henkelmann http://henkelmann.eu/
*/

import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import collection.SortedMap
Expand Down Expand Up @@ -71,4 +71,4 @@ class BaseParsersTest extends FlatSpec with Matchers with BaseParsers{
an [IllegalArgumentException] should be thrownBy(apply(p, "<"))
}

}
}
Expand Up @@ -20,7 +20,7 @@ package net.liftweb.markdown
*/

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner
import org.scalatest.{Matchers,FlatSpec}
import scala.xml.{Group, NodeSeq}

Expand Down
Expand Up @@ -22,7 +22,7 @@ package net.liftweb.markdown
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner

/**
* Tests Inline Parsing, i.e. emphasis , strong text, links, escapes etc.
Expand Down
Expand Up @@ -21,7 +21,7 @@ package net.liftweb.markdown

import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner

/**
* tests parsing of individual lines
Expand Down
Expand Up @@ -21,7 +21,7 @@ package net.liftweb.markdown

import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner

/**
* Tests the Line Tokenizer that prepares input for parsing.
Expand Down
Expand Up @@ -21,7 +21,7 @@ package net.liftweb.markdown

import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatestplus.junit.JUnitRunner

/**
* Tests the behavior of the complete parser, i.e. all parsing steps together.
Expand Down
12 changes: 5 additions & 7 deletions persistence/db/src/test/scala/net/liftweb/db/DBSpec.scala
Expand Up @@ -19,12 +19,10 @@ package db

import org.specs2.mutable.Specification
import org.specs2.mock.Mockito
import org.mockito.Matchers._

import net.liftweb.common._
import net.liftweb.db._
import net.liftweb.util.DefaultConnectionIdentifier
import net.liftweb.util.ControlHelpers._
import common._
import util.DefaultConnectionIdentifier
import util.ControlHelpers._

import java.sql._

Expand All @@ -35,8 +33,8 @@ class DBSpec extends Specification with Mockito {
def f(success: Boolean): Unit
}

def dBVendor(connection: Connection) = new ProtoDBVendor {
def createOne = {
def dBVendor(connection: Connection): ProtoDBVendor = new ProtoDBVendor {
def createOne: Box[Connection] = {
connection.createStatement returns mock[PreparedStatement]
Full(connection)
}
Expand Down
@@ -0,0 +1,107 @@
/*
* Copyright 2006-2011 WorldWide Conferencing, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.liftweb
package mapper

import scala.reflect.{ClassTag, classTag}

class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: common.Logger) {

import java.lang.reflect._

logger.debug("Created FieldFinder for " + classTag[T].runtimeClass)

def isMagicObject(m: Method): Boolean = m.getReturnType.getName.endsWith("$" + m.getName + "$") && m.getParameterTypes.length == 0

def typeFilter: Class[_] => Boolean = classTag[T].runtimeClass.isAssignableFrom

/**
* Find the magic mapper fields on the superclass
*/
def findMagicFields(onMagic: AnyRef, startingClass: Class[_]): List[Method] = {
// If a class name ends in $module, it's a subclass created for scala object instances
def deMod(in: String): String =
if (in.endsWith("$module")) in.substring(0, in.length - 7)
else in

// find the magic fields for the given superclass
def findForClass(clz: Class[_]): List[Method] = clz match {
case null => Nil
case c =>
// get the names of fields that represent the type we want

val fields = Map(c.getDeclaredFields
.filter { f =>
val ret = typeFilter(f.getType)
logger.trace("typeFilter(" + f.getType + "); T=" + classTag[T].runtimeClass)
ret
}
.map(f => (deMod(f.getName), f)): _*)

logger.trace("fields: " + fields)

// this method will find all the super classes and super-interfaces
def getAllSupers(clz: Class[_]): List[Class[_]] = clz match {
case null => Nil
case c =>
c :: c.getInterfaces.toList.flatMap(getAllSupers) :::
getAllSupers(c.getSuperclass)
}

// does the method return an actual instance of an actual class that's
// associated with this Mapper class
def validActualType(meth: Method): Boolean = {
try {
// invoke the method
meth.invoke(onMagic) match {
case null =>
logger.debug("Not a valid mapped field: %s".format(meth.getName))
false
case inst =>
// do we get a T of some sort back?
if (!typeFilter(inst.getClass)) false
else {
// find out if the class name of the actual thing starts
// with the name of this class or some superclass...
// basically, is an inner class of this class
getAllSupers(clz).exists(c => inst.getClass.getName.startsWith(c.getName))
}
}

} catch {
case e: Exception =>
logger.debug("Not a valid mapped field: %s, got exception: %s".format(meth.getName, e))
false
}
}

// find all the declared methods
val meths = c.getDeclaredMethods.toList.
filter(_.getParameterTypes.length == 0). // that take no parameters
filter(m => Modifier.isPublic(m.getModifiers)). // that are public
filter(m => fields.contains(m.getName) && // that are associated with private fields
fields(m.getName).getType == m.getReturnType).
filter(validActualType) // and have a validated type

meths ::: findForClass(clz.getSuperclass)
}

findForClass(startingClass).distinct
}

lazy val accessorMethods = findMagicFields(metaMapper, metaMapper.getClass.getSuperclass)
}

0 comments on commit 2c522a3

Please sign in to comment.