Skip to content

[POC][WIP] - using zinc's Dependency analysis for rules_scala strict deps #439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions third_party/plugin/src/main/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ load("//scala:scala.bzl", "scala_library", "scala_library_for_plugin_bootstrappi

scala_library_for_plugin_bootstrapping(
name = "dependency_analyzer",
srcs = ["io/bazel/rulesscala/dependencyanalyzer/DependencyAnalyzer.scala",
],
srcs = glob(["**/*.scala"]),
resources = ["resources/scalac-plugin.xml"],
visibility = ["//visibility:public"],
deps = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Zinc - The incremental compiler for Scala.
* Copyright 2011 - 2017, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* This software is released under the terms written in LICENSE.
*/

package third_party.plugin.src.main.io.bazel.rulesscala.dependencyanalyzer

import scala.tools.nsc.Global

/**
* Utility methods for creating (source|binary) class names for a Symbol.
*/
trait ClassName {
val global: Global
import global._

/**
* Creates a flat (binary) name for a class symbol `s`.
*/
protected def flatname(s: Symbol, separator: Char) =
enteringPhase(currentRun.flattenPhase.next) { s fullName separator }

/**
* Create a (source) name for a class symbol `s`.
*/
protected def className(s: Symbol): Name = pickledName(s)

/**
* Create a String (source) name for a class symbol `s`.
*/
protected def classNameAsString(s: Symbol): String = pickledNameAsString(s)

/**
* Given a class symbol `cls`, construct a name representing this constructor.
* For a class:
*
* a.b.Foo
*
* this is:
*
* a;b;Foo;init;
*
* The prefix is important to avoid name hashing all constructors together
* (see #97), the weird format is necessary to avoid scalac or zinc trying to
* interpret this name (in particular we should not use '.' and we should not
* use '<init>'), we use ';' because it is one of the few characters that
* cannot appear in a valid JVM name.
*/
protected def constructorName(cls: Symbol): Name =
newTermName(constructorNameAsString(cls))

protected def constructorNameAsString(cls: Symbol): String =
cls.fullName(';') ++ ";init;"

/**
* Mangle a JVM symbol name in a format better suited for internal uses by sbt.
*/
protected def mangledName(s: Symbol): Name =
if (s.name == nme.CONSTRUCTOR)
constructorName(s.enclClass)
else
s.name

/**
* Create a (source) name for the class symbol `s` with a prefix determined by the class symbol `in`.
*
* If `s` represents a package object `pkg3`, then the returned name will be `pkg1.pkg2.pkg3.package`.
* If `s` represents a class `Foo` nested in package object `pkg3` then the returned name is `pkg1.pkg2.pk3.Foo`.
*
* Note that some objects with special access rights are encoded in names
* (like qualified privates `private[qualifier]`). In order to get the right
* original names, we need to use `unexpandedName`.
*/
protected def classNameAsSeenIn(in: Symbol, s: Symbol): String =
enteringPhase(currentRun.picklerPhase.next) {
if (in.isRoot || in.isRootPackage || in == NoSymbol || in.isEffectiveRoot)
s.simpleName.toString
else if (in.isPackageObjectOrClass)
in.owner.fullName + "." + s.unexpandedName
else
in.fullName + "." + s.unexpandedName
}

private def pickledName(s: Symbol): Name =
enteringPhase(currentRun.picklerPhase.next) { s.fullNameAsName('.') }

private def pickledNameAsString(s: Symbol): String =
enteringPhase(currentRun.picklerPhase.next) { s.fullName }

protected def isTopLevelModule(sym: Symbol): Boolean =
enteringPhase(currentRun.picklerPhase.next) {
sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass
}

protected def flatclassName(s: Symbol, sep: Char, dollarRequired: Boolean): String =
flatname(s, sep) + (if (dollarRequired) "$" else "")
}
Loading