-
Notifications
You must be signed in to change notification settings - Fork 183
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
Simplifify api for import patches #48
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,29 @@ | ||
package scalafix.rewrite | ||
import scala.meta.Tree | ||
import scala.meta.tokens.Tokens | ||
import scalafix.ScalafixConfig | ||
import scalafix.util.AssociatedComments | ||
import scalafix.util.TokenList | ||
|
||
case class RewriteCtx( | ||
config: ScalafixConfig, | ||
tokens: Tokens, | ||
tokenList: TokenList, | ||
comments: AssociatedComments, | ||
semantic: Option[SemanticApi] | ||
) | ||
|
||
object RewriteCtx { | ||
def fromCode(ast: Tree, | ||
config: ScalafixConfig = ScalafixConfig(), | ||
semanticApi: Option[SemanticApi] = None): RewriteCtx = { | ||
val tokens = ast.tokens(config.dialect) | ||
RewriteCtx( | ||
config, | ||
tokens, | ||
new TokenList(tokens), | ||
AssociatedComments(tokens), | ||
semanticApi | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,15 +160,14 @@ private[this] class OrganizeImports private (implicit ctx: RewriteCtx) { | |
.mkString("\n\n") | ||
} | ||
|
||
def getRemovePatches(oldImports: Seq[Import], | ||
tokens: Tokens): Seq[TokenPatch.Remove] = { | ||
def getRemovePatches(oldImports: Seq[Import]): Seq[TokenPatch.Remove] = { | ||
val toRemove = for { | ||
firstImport <- oldImports.headOption | ||
first <- firstImport.tokens.headOption | ||
lastImport <- oldImports.lastOption | ||
last <- lastImport.tokens.lastOption | ||
} yield { | ||
tokens.toIterator | ||
ctx.tokens.toIterator | ||
.dropWhile(_.start < first.start) | ||
.takeWhile { x => | ||
x.end <= last.end | ||
|
@@ -186,9 +185,9 @@ private[this] class OrganizeImports private (implicit ctx: RewriteCtx) { | |
patch match { | ||
case _: AddGlobalImport => | ||
if (is.exists(_.supersedes(patch))) is | ||
else is :+ patch.importer | ||
else is ++ getCanonicalImports(patch.toImport) | ||
case remove: RemoveGlobalImport => | ||
is.filter(_.structure == remove.importer.structure) | ||
is.filterNot(_.structure == remove.importer.structure) | ||
} | ||
patches.foldLeft(removeUnused(globalImports))(combine) | ||
} | ||
|
@@ -200,14 +199,13 @@ private[this] class OrganizeImports private (implicit ctx: RewriteCtx) { | |
val oldImports = getGlobalImports(code) | ||
val globalImports = oldImports.flatMap(getCanonicalImports) | ||
val cleanedUpImports = cleanUpImports(globalImports, patches) | ||
val tokens = code.tokens | ||
val tokenToEdit = | ||
oldImports.headOption | ||
.map(_.tokens.head) | ||
.getOrElse(tokens.head) | ||
.getOrElse(ctx.tokens.head) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we know ctx.tokens is non-empty here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tree nodes that return empty tokens are incredibly few (if any) and I would say it was a truly exceptional case if those were passed in here. Top level trees always have a beginning of file token. There's an interesting ongoing discussion in scalameta about validating trees for a given dialect. I would be interested to start a similar discussion about the possibility to use a non empty list type Where applicable. The challenge is try and encode as much as possible on the type level without burdening syntax too heavily. Quasi quotes help a lot here. |
||
val toInsert = prettyPrint(cleanedUpImports) | ||
TokenPatch.AddLeft(tokenToEdit, toInsert) +: | ||
getRemovePatches(oldImports, tokens) | ||
getRemovePatches(oldImports) | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,3 +85,4 @@ object logger { | |
s"$line\n=> $t\n$line" | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Small worksheet to demonstrate usage of import patches | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ShaneDelmore I got this working on my laptop |
||
import scala.collection.immutable.Seq | ||
import scala.meta._ | ||
import scalafix.rewrite.RewriteCtx | ||
import scalafix.util.Patch | ||
import scalafix.util.TreePatch.AddGlobalImport | ||
import scalafix.util.TreePatch.RemoveGlobalImport | ||
import scala.meta._ | ||
import scalafix.util.logger | ||
val code = | ||
"""import scala.language.higherKinds | ||
|import java.{util => ju} | ||
|import scala.collection.mutable._ | ||
| | ||
|object a | ||
""".stripMargin.parse[Source].get | ||
implicit val ctx: RewriteCtx = RewriteCtx.fromCode(code) | ||
val add = AddGlobalImport(importer"cats.data.EitherT") | ||
val addRedundant = AddGlobalImport(importer"scala.collection.mutable._") | ||
val remove = RemoveGlobalImport(importer"scala.language.higherKinds") | ||
|
||
val x = Patch.apply(code, Seq(add, addRedundant, remove)) | ||
logger.elem(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if no SemanticApi is supplied? Is a new one created, or is functionality diminished in some way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. It depends on what rewrite is used, some rewrites like procedure syntax work 100% without the semantic api, organize imports works without it but can't handle relative imports in that case, explicit implicit will error.
I guess this could be better documented.