All Downloads are FREE. Search and download functionalities are using the official Maven repository.

airyfotr.linter_2.11.0.1.17.source-code.Utils.scala Maven / Gradle / Ivy

The newest version!
/**
 *   Copyright 2012 Foursquare Labs, Inc.
 *
 *   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 org.psywerx.hairyfotr

import scala.collection.mutable
import scala.tools.nsc.{ Global, Properties }

final object Utils {
  var linterOptions = LinterOptions()
  val nowarnPositions = mutable.HashSet[Global#Position]()
  val nowarnMergeNestedIfsPositions = mutable.HashSet[Global#Position]() //TODO: hack

  def warn(tree: Global#Tree, warning: Warning)(implicit unit: Global#CompilationUnit): Unit = {
    warn(tree.pos, warning)(unit)
  }
  def warn(tree: Global#Position, warning: Warning)(implicit unit: Global#CompilationUnit): Unit = {
    val checkSep = "([+:]|[,] )"
    val partSep = "[ :]"
    val checkReg = "[A-Z][a-zA-Z]+"
    if((linterOptions.disabledWarningNames contains warning.name)
    || (tree.pos.lineContent matches s".*// *linter${partSep}(nowarn|ignore|disable)(${partSep}(${checkReg}${checkSep})*${warning.name}(${checkSep}${checkReg})*)? *(//.*)?")
    || (nowarnPositions contains tree.pos)) {
      // skip
    } else {
      // scalastyle:off regex
      //TODO: after 2.10: CompilationUnit is deprecated, call global.reporter.warning
      unit.warning(tree.pos, if (linterOptions.printWarningNames) s"[${warning.name}] ${warning.message}" else warning.message)
      // scalastyle:on regex
    }
  }

  def toBang(b: Boolean): String = if (b) "!" else ""

  def staticSelect(prefix: String, suffix: String): String = {
    if (Properties.versionString.contains("2.10")
    ||  Properties.versionString.contains("2.11")) {
      s"$prefix.this.$suffix"
    } else {
      s"$prefix.$suffix"
    }
  }

}

// Put only those that need the right global here:
class Utils[G <: Global](val global: G) {
  import global._
  global.definitions.init

  def isUsed(t: Tree, name: String, filter: String = ""): Boolean = {
    val tree = t.asInstanceOf[Tree]
    var used = 0
    for (Ident(id) <- tree; if id.toString == name) used += 1
    //TODO: Only for select types, also, maybe this doesn't belong in all uses of isUsed (e.g. Assignment right after declaration)
    // isSideEffectFreeFor(...)
    if (filter != "") {
      for (Select(Ident(id), func) <- tree; if (func.toString matches filter) && (id.toString == name)) used -= 1
    }

    (used > 0)
  }

  def getUsed(tree: Tree): Set[String] = {
    var used = Set.empty[String]
    for (Ident(id) <- tree) used += id.toString
    used
  }

  import definitions.{ AnyClass, OptionClass }
  val JavaConversionsModule: Symbol = rootMirror.getModuleByName(newTermName("scala.collection.JavaConversions"))
  val SeqLikeClass: Symbol = rootMirror.getClassByName(newTermName("scala.collection.SeqLike"))
  val SeqLikeContains: Symbol = SeqLikeClass.info.member(newTermName("contains"))
  val SeqLikeApply: Symbol = SeqLikeClass.info.member(newTermName("apply"))

  val OptionGet: Symbol = OptionClass.info.member(nme.get)

  val IsInstanceOf = AnyClass.info.member(nme.isInstanceOf_)
  val AsInstanceOf = AnyClass.info.member(nme.asInstanceOf_)
  val ToString: Symbol = AnyClass.info.member(nme.toString_)

  def seqMemberType(seenFrom: Type): Type = {
    SeqLikeClass.tpe.typeArgs.head.asSeenFrom(seenFrom, SeqLikeClass)
  }

  def isSubtype(x: Tree, y: Tree): Boolean = { x.tpe.widen <:< y.tpe.widen }
  def isSubtype(x: Tree, y: Type): Boolean = { x.tpe.widen <:< y.widen }

  def methodImplements(method: Symbol, target: Symbol): Boolean =
    try { method == target || method.allOverriddenSymbols.contains(target) } catch { case e: NullPointerException => false }

  def isGlobalImport(selector: ImportSelector): Boolean = {
    selector.name == nme.WILDCARD && selector.renamePos == -1
  }

  def isOptionOption(t: Tree): Boolean =
    (t.tpe.widen.baseClasses.exists(_.tpe =:= OptionClass.tpe)
    && t.tpe.widen.typeArgs.exists(_.widen.baseClasses.exists(_.tpe =:= OptionClass.tpe)))

  def isLiteral(t: Tree): Boolean = t match {
    case Literal(_) => true
    case _ => false
  }

  def getAssigned(tree: Tree): Set[String] = {
    (for (Assign(Ident(id), _) <- tree) yield id.toString).toSet
    //TODO: non-local stuff (for (Apply(Select(id, setter), List(_)) <- tree; if setter.toString endsWith "_$eq") yield setter.dropRight(4)).toSet
  }

  def isAssigned(tree: Tree, name: String): Boolean = {
    for (Assign(Ident(id), _) <- tree; if id.toString == name)
      return true

    false
  }

  def returnCount(tree: Tree): Int = {
    var used = 0
    for (Return(id) <- tree) used += 1
    used
  }
  def throwsCount(tree: Tree): Int = {
    var used = 0
    for (Throw(id) <- tree) used += 1
    used
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy