Split to small methods

This commit is contained in:
andrzej.jozwik@gmail.com 2014-09-30 19:53:51 +02:00 committed by Eugene Yokota
parent dac3edb546
commit 97a96d5bf8
1 changed files with 68 additions and 46 deletions

View File

@ -4,26 +4,28 @@ package parser
import java.io.File
import SplitExpressionsNoBlankies._
import sbt.internals.parser.SplitExpressionsNoBlankies._
import scala.annotation.tailrec
import scala.reflect.runtime.universe._
private[sbt] object SplitExpressionsNoBlankies {
val END_OF_LINE_CHAR = '\n'
val END_OF_LINE = String.valueOf(END_OF_LINE_CHAR)
private[parser] val NOT_FOUND_INDEX = -1
private[sbt] val FAKE_FILE = new File("fake")
}
private[sbt] case class SplitExpressionsNoBlankies(file: File, lines: Seq[String]) {
//settingsTrees needed for "session save"
//settingsTrees,modifiedContent needed for "session save"
val (imports, settings, settingsTrees, modifiedContent) = splitExpressions(file, lines)
private def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)], Seq[(String, Tree)], String) = {
import scala.reflect.runtime._
import sbt.internals.parser.MissingBracketHandler._
import sbt.internals.parser.XmlContent._
import scala.compat.Platform.EOL
import MissingBracketHandler._
import XmlContent._
import scala.reflect.runtime._
import scala.tools.reflect.{ ToolBox, ToolBoxError }
val mirror = universe.runtimeMirror(this.getClass.getClassLoader)
@ -83,7 +85,7 @@ private[sbt] case class SplitExpressionsNoBlankies(file: File, lines: Seq[String
if (t.pos.isDefined) {
val originalStatement = modifiedContent.substring(t.pos.start, t.pos.end)
val statement = parseStatementAgain(t, originalStatement)
val numberLines = statement.count(c => c == END_OF_LINE_CHAR)
val numberLines = countLines(statement)
Some((statement, t, LineRange(t.pos.line - 1, t.pos.line + numberLines)))
} else {
None
@ -91,11 +93,13 @@ private[sbt] case class SplitExpressionsNoBlankies(file: File, lines: Seq[String
val statementsTreeLineRange = statements flatMap convertStatement
(imports map convertImport, statementsTreeLineRange.map(t => (t._1, t._3)), statementsTreeLineRange.map(t => (t._1, t._2)), modifiedContent)
}
private def countLines(statement: String) = statement.count(c => c == END_OF_LINE_CHAR)
}
/**
* Scala parser cuts last bracket -
* @see http://stackoverflow.com/questions/25547149/scala-parser-cuts-last-bracket
* @see https://github.com/scala/scala/pull/3991
*/
private[sbt] object MissingBracketHandler {
/**
@ -105,7 +109,7 @@ private[sbt] object MissingBracketHandler {
* @param positionLine - number of start position line
* @param fileName - file name
* @param originalException - original exception
* @return
* @return missing text
*/
private[sbt] def findMissingText(content: String, positionEnd: Int, positionLine: Int, fileName: String, originalException: Throwable): String = {
findClosingBracketIndex(content, positionEnd) match {
@ -131,7 +135,7 @@ private[sbt] object MissingBracketHandler {
*/
private[sbt] def findClosingBracketIndex(content: String, from: Int): Option[Int] = {
val index = content.indexWhere(c => c == '}' || c == ')', from)
if (index == -1) {
if (index == NOT_FOUND_INDEX) {
None
} else {
Some(index)
@ -152,6 +156,17 @@ private[sbt] object MissingBracketHandler {
* </pre>
*/
private[sbt] object XmlContent {
private val OPEN_PARENTHESIS = '{'
private val OPEN_CURLY_BRACKET = '('
private val DOUBLE_SLASH = "//"
private val OPEN_BRACKET = s" $OPEN_CURLY_BRACKET "
private val CLOSE_BRACKET = " ) "
/**
*
* @param original - file content
@ -206,7 +221,7 @@ private[sbt] object XmlContent {
private def searchForTagName(text: String, startIndex: Int, endIndex: Int) = {
val subs = text.substring(startIndex, endIndex)
val spaceIndex = subs.indexWhere(c => c.isWhitespace, 1)
if (spaceIndex == -1) {
if (spaceIndex == NOT_FOUND_INDEX) {
subs
} else {
subs.substring(0, spaceIndex)
@ -222,7 +237,7 @@ private[sbt] object XmlContent {
@tailrec
private def findModifiedOpeningTags(content: String, offsetIndex: Int, acc: Seq[(String, Int, Int)]): Seq[(String, Int, Int)] = {
val endIndex = content.indexOf("/>", offsetIndex)
if (endIndex == -1) {
if (endIndex == NOT_FOUND_INDEX) {
acc
} else {
val xmlFragment = findModifiedOpeningTag(content, offsetIndex, endIndex)
@ -233,7 +248,7 @@ private[sbt] object XmlContent {
private def findModifiedOpeningTag(content: String, offsetIndex: Int, endIndex: Int): Option[(String, Int, Int)] = {
val startIndex = content.substring(offsetIndex, endIndex).lastIndexOf("<")
if (startIndex == -1) {
if (startIndex == NOT_FOUND_INDEX) {
None
} else {
val tagName = searchForTagName(content, startIndex + 1 + offsetIndex, endIndex)
@ -249,7 +264,7 @@ private[sbt] object XmlContent {
private def searchForOpeningIndex(text: String, closeTagStartIndex: Int, tagName: String) = {
val subs = text.substring(0, closeTagStartIndex)
val index = subs.lastIndexOf(s"<$tagName>")
if (index == -1) {
if (index == NOT_FOUND_INDEX) {
subs.lastIndexOf(s"<$tagName ")
} else {
index
@ -265,11 +280,11 @@ private[sbt] object XmlContent {
@tailrec
private def findNotModifiedOpeningTags(content: String, current: Int, acc: Seq[(String, Int, Int)]): Seq[(String, Int, Int)] = {
val closeTagStartIndex = content.indexOf("</", current)
if (closeTagStartIndex == -1) {
if (closeTagStartIndex == NOT_FOUND_INDEX) {
acc
} else {
val closeTagEndIndex = content.indexOf(">", closeTagStartIndex)
if (closeTagEndIndex == -1) {
if (closeTagEndIndex == NOT_FOUND_INDEX) {
findNotModifiedOpeningTags(content, closeTagStartIndex + 2, acc)
} else {
val xmlFragment = findNotModifiedOpeningTag(content, closeTagStartIndex, closeTagEndIndex)
@ -301,39 +316,46 @@ private[sbt] object XmlContent {
*/
private def addExplicitXmlContent(content: String, xmlParts: Seq[(String, Int, Int)]): String = {
val statements: Seq[(String, Boolean)] = splitFile(content, xmlParts)
val (builder, addCloseBrackets, wasXml, _) = statements.foldLeft((Seq.empty[String], false, false, "")) {
case ((bAcc, addCloseBrackets, wasXml, previous), (content, isXml)) =>
if (content.trim.isEmpty) {
(content +: bAcc, addCloseBrackets, wasXml, content)
val (correctedStmt, shouldAddCloseBrackets, wasXml, _) = addBracketsIfNecessary(statements)
val closeIfNecessaryCorrectedStmt =
if (shouldAddCloseBrackets && wasXml) {
correctedStmt.head +: CLOSE_BRACKET +: correctedStmt.tail
} else {
correctedStmt
}
closeIfNecessaryCorrectedStmt.reverse.mkString
}
def addBracketsIfNecessary(statements: Seq[(String, Boolean)]): (Seq[String], Boolean, Boolean, String) = {
statements.foldLeft((Seq.empty[String], false, false, "")) {
case ((accStmt, shouldAddCloseBracket, prvWasXml, prvStmt), (stmt, isXml)) =>
if (stmt.trim.isEmpty) {
(stmt +: accStmt, shouldAddCloseBracket, prvWasXml, stmt)
} else {
val (newAddCloseBrackets, newAcc) = if (isXml) {
if (wasXml) {
(addCloseBrackets, bAcc)
} else {
if (areBracketsNecessary(previous)) {
(true, " ( " +: bAcc)
} else {
(false, bAcc)
}
}
} else if (addCloseBrackets) {
(false, " ) " +: bAcc)
val (newShouldAddCloseBracket, newStmtAcc) = if (isXml) {
addOpenBracketIfNecessary(accStmt, shouldAddCloseBracket, prvWasXml, prvStmt)
} else if (shouldAddCloseBracket) {
(false, CLOSE_BRACKET +: accStmt)
} else {
(false, bAcc)
(false, accStmt)
}
(content +: newAcc, newAddCloseBrackets, isXml, content)
(stmt +: newStmtAcc, newShouldAddCloseBracket, isXml, stmt)
}
}
val closeIfNecessaryBuilder =
if (addCloseBrackets && wasXml) {
builder.head +: " ) " +: builder.tail
} else {
builder
}
closeIfNecessaryBuilder.reverse.mkString
}
private def addOpenBracketIfNecessary(stmtAcc: Seq[String], shouldAddCloseBracket: Boolean, prvWasXml: Boolean, prvStatement: String) =
if (prvWasXml) {
(shouldAddCloseBracket, stmtAcc)
} else {
if (areBracketsNecessary(prvStatement)) {
(true, OPEN_BRACKET +: stmtAcc)
} else {
(false, stmtAcc)
}
}
/**
* Add to head if option is not empty
* @param ts - seq
@ -348,7 +370,7 @@ private[sbt] object XmlContent {
val tagName = content.substring(closeTagStartIndex + 2, closeTagEndIndex)
if (xml.Utility.isName(tagName)) {
val openTagIndex = searchForOpeningIndex(content, closeTagStartIndex, tagName)
if (openTagIndex == -1) {
if (openTagIndex == NOT_FOUND_INDEX) {
None
} else {
xmlFragmentOption(content, openTagIndex, closeTagEndIndex + 1)
@ -379,13 +401,13 @@ private[sbt] object XmlContent {
* @return are brackets necessary?
*/
private def areBracketsNecessary(statement: String): Boolean = {
val doubleSlash = statement.indexOf("//")
val doubleSlash = statement.indexOf(DOUBLE_SLASH)
val endOfLine = statement.indexOf(END_OF_LINE)
if (doubleSlash == -1 || (doubleSlash < endOfLine)) {
val roundBrackets = statement.lastIndexOf("(")
val braces = statement.lastIndexOf("{")
if (doubleSlash == NOT_FOUND_INDEX || (doubleSlash < endOfLine)) {
val roundBrackets = statement.lastIndexOf(OPEN_CURLY_BRACKET)
val braces = statement.lastIndexOf(OPEN_PARENTHESIS)
val max = roundBrackets.max(braces)
if (max == -1) {
if (max == NOT_FOUND_INDEX) {
true
} else {
val trimmed = statement.substring(max + 1).trim