Есть идеи, как удалить комментарии из кода Scala, чтобы:
Вот пример кода с комментариями:
object TestCode {
val a = "A" // a = "AA"
val b = "B" /* b = "BB" */
val c = "C" /* multi line comment
/* c = "CC" nested */ // FOO
*/ // c = "CCC"
val d = """D""" // d = """DD /* """
val e = '"' // e = '"' = char literal
val f = '\"' // f = '\"' = char literal
val codeStr = " \" \"\" \"\"\"/* This is literal */\"\"\" val x = \"\"\"5\"\"\" \" "
"/* This is a literal */" // This is a comment 3
"// This is a literal with extra comment end string */" // This is a comment 4
"/* This is a litral with extra comment begin string" // This is a comment 5
}
Код компилируется (с предупреждениями о чистых выражениях).
Препроцессор C подходит довольно близко, но не справляется с вложенными комментариями.
object TestCode {
val a = "A"
val b = "B"
val c = "C"
*/
val d = """D"""
val e = '"'
val f = '\"'
val codeStr = " \" \"\" \"\"\"/* This is literal */\"\"\" val x = \"\"\"5\"\"\" \" "
"/* This is a literal */"
"// This is a literal with extra comment end string */"
"/* This is a litral with extra comment begin string"
}
Я также попробовал это решение для регулярных выражений, но, похоже, оно не работает в случае символьных литералов кавычек и вложенных комментариев, как вы видите:
str.replaceAll("//.*|/\\*(?s:.*?)\\*/|(\"(?:(?<!\\\\)(?:\\\\\\\\)*\\\\\"|[^\r\n\"])*\")", "$1")
res1: String = """object TestCode {
val a = "A"
val b = "B"
val c = "C"
*/
val d = """D"""
val e = '"' // e = '"' = char literal
val f = '\"' // f = '\"' = char literal
val codeStr = " \" \"\" \"\"\"/* This is literal */\"\"\" val x = \"\"\"5\"\"\" \" "
"/* This is a literal */"
"// This is a literal with extra comment end string */"
"/* This is a literal with extra comment begin string"
}"""
Компилятор Scala может выполнить эту работу, но, насколько я понимаю, у компилятора нет возможности просто удалять комментарии.
Я бы использовал scalameta для анализа кода и удаления комментариев из ast. Или используйте собственное правило scalafix.
Пробовали ли вы что-нибудь с Scalafix/Scalameta или Wartremover?
@GuruStron Ну, предварительная обработка - это стандартная техника C/C++ :)
Я использовал предложение Матеуша Кубушока и использовал ScalaMeta для реализации.
Это файл сценария scala-cli: SourceCodeCommentRemover.scala
//> using scala "2.13.5"
//> using lib "org.scalameta::scalameta:4.9.7"
import scala.meta._
import java.io.{File, PrintWriter}
object CommentRemover {
def main(args: Array[String]): Unit = {
if (args.length != 2) {
println("Usage: CommentRemover <input file> <output file>")
sys.exit(1)
}
val inputFile = new File(args(0))
val outputFile = new File(args(1))
if (!inputFile.exists()) {
println(s"Input file ${inputFile.getAbsolutePath} does not exist.")
sys.exit(1)
}
val sourceCode = {
import scala.io.Source
Source.fromFile(inputFile).mkString
}
println(s"Original source: BEGIN\n${sourceCode}\nEND")
val tree = sourceCode.parse[Source] match {
case parsers.Parsed.Success(tree) => tree
case parsers.Parsed.Error(_, msg, _) =>
println(s"Failed to parse the input file: $msg")
sys.exit(1)
}
val codeWithoutComments = tree.tokens.collect {
case token if !token.is[Token.Comment] => token.text
}.mkString
println(s"Comments removed: BEGIN\n${codeWithoutComments}\nEND")
val writer = new PrintWriter(outputFile)
try {
writer.write(codeWithoutComments)
} finally {
writer.close()
}
println(s"Comments removed. Output written to ${outputFile.getAbsolutePath}.")
}
}
Это тестовый входной файл: StackOverflowTestCode.scala
object TestCode {
val a = "A" // a = "AA"
val b = "B" /* b = "BB" */
val c = "C" /* multi line comment
/* c = "CC" nested */ // FOO
*/ // c = "CCC"
val d = """D""" // d = """DD /* """
val e = '"' // e = '"' = char literal
val f = '\"' // f = '\"' = char literal
val codeStr = " \" \"\" \"\"\"/* This is literal */\"\"\" val x = \"\"\"5\"\"\" \" "
"/* This is a literal */" // This is a comment 3
"// This is a literal with extra comment end string */" // This is a comment 4
"/* This is a litral with extra comment begin string" // This is a comment 5
}
Запустите скрипт:
scala-cli run SourceCodeCommentRemover.scala -- StackOverflowTestCode.scala out.scala
cat out.scala
object TestCode {
val a = "A"
val b = "B"
val c = "C"
val d = """D"""
val e = '"'
val f = '\"'
val codeStr = " \" \"\" \"\"\"/* This is literal */\"\"\" val x = \"\"\"5\"\"\" \" "
"/* This is a literal */"
"// This is a literal with extra comment end string */"
"/* This is a litral with extra comment begin string"
}
Версия Scala-cli:
scala-cli --version
Scala CLI version: 1.4.1
Scala version (default): 3.4.2
Удален тег
c++
, так как он показался неактуальным.