- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Scala plugin
Tue, 2011-11-08, 10:35
Hi,
I'm trying to write a simple static checker for regular expressions. The idea is to look for calls to the r method where the receiver is a constant String and to check that the string contains a well-formed regular expression. I've read the tutorial in scala-lang.org, but I can't find any documentation on how to chane it to achive my goal. I will be greatful if anybody can help.
cheers,
Ali
Tue, 2011-11-08, 20:17
#2
Re: Scala plugin
Dear Paul, Thank you very much, It was very helpful. cheers,
On Tue, Nov 8, 2011 at 2:04 PM, Paul Phillips <paulp@improving.org> wrote:
On Tue, Nov 8, 2011 at 2:04 PM, Paul Phillips <paulp@improving.org> wrote:
On Sat, Nov 5, 2011 at 6:29 AM, Ali ektefa <ali.ektefa@gmail.com> wrote:
> I'm trying to write a simple static checker for regular expressions. The
> idea is to look for calls to the r method where the receiver is a constant
> String and to check that the string contains a well-formed regular
> expression. I've read the tutorial in scala-lang.org, but I can't find any
> documentation on how to chane it to achive my goal. I will be greatful if
> anybody can help.
See this part?
def apply(unit: CompilationUnit) {
for ( tree @ Apply(Select(rcvr, nme.DIV),
List(Literal(Constant(0)))) <- unit.body;
if rcvr.tpe <:< definitions.IntClass.tpe)
{
unit.error(tree.pos, "definitely division by zero")
}
}
You instead write something like this. ("Something like" chosen
specifically because this isn't tested and there are a lot of little
things one can do to make things not work.)
def apply(unit: CompilationUnit) {
import definitions._
// the symbol of the implicit in Predef which installs the r method
val augmentMethod = getMember(PredefModule, "augmentString")
// iterating over all subtrees looking for calls to the r method
unit.body foreach {
// which should look about like this for the case you're interested in
case Apply(fn, Literal(Constant(value: String)) :: Nil) if
fn.symbol == augmentMethod =>
println("My logic to check \"" + value + "\" for regex
goodness goes here.")
case _ =>
}
}
}
Wed, 2011-11-09, 04:07
#3
Re: Scala plugin
Maybe this example can give you some help.
This plugin runs after the "parser" phase. $ type RegexPlugin.scala
import scala.tools.nsc.{Global, Phase}
import scala.tools.nsc.plugins.{Plugin, PluginComponent}
class RegexPlugin(override val global: Global) extends Plugin {
override val name = "regex"
override val description = "emits warnings about too short regexps"
override val components = List(new RegexPluginComponent(global))
class RegexPluginComponent(override val global: Global)
extends PluginComponent {
import global._
override val phaseName = name
override val runsAfter = List("parser")
override val runsBefore = List("namer")
override def newPhase(prev: Phase) = new StdPhase(prev) {
override def apply(unit: CompilationUnit) {
for (tree <- unit.body) tree match {
case Select(Literal(Constant(regex: String)),symb)
if symb.toString == "r" =>
regexWarning(regex, tree).map{ unit.warning(tree.pos, _) }
case _ => }
def regexWarning(regex: String, tree: Tree): Option[String] =
if (regex.length <= 2) Some("The regex "+regex+" is too short")
else None
}
}
}
} $ type scalac-plugin.xml
<plugin>
<name>regex</name>
<classname>RegexPlugin</classname>
</plugin> $ scalac RegexPlugin.scala $ jar -cf regex.jar RegexPlugin*.class scalac-plugin.xml $ type Example.scala
object Example {
val r1 = "0+".r
val r2 = "[0-9]+".r
} $ scalac -Xplugin:regex.jar Example.scala
Example.scala:2: warning: The regex 0+ is too short
val r1 = "0+".r
^
one warning found
When trying to figure out the proper pattern match expression, the following might be helpful. $ scalac -Xprint:parser -Yshow-trees Example.scala
[[syntax trees at end of parser]]// Scala source: Example.scala
(...)
Select( // sym=<none>, sym.tpe=<notype>, tpe=null
Literal(Constant([0-9]+)),
"r")
(...) Regards,
Grzegorz Balcerek
This plugin runs after the "parser" phase. $ type RegexPlugin.scala
import scala.tools.nsc.{Global, Phase}
import scala.tools.nsc.plugins.{Plugin, PluginComponent}
class RegexPlugin(override val global: Global) extends Plugin {
override val name = "regex"
override val description = "emits warnings about too short regexps"
override val components = List(new RegexPluginComponent(global))
class RegexPluginComponent(override val global: Global)
extends PluginComponent {
import global._
override val phaseName = name
override val runsAfter = List("parser")
override val runsBefore = List("namer")
override def newPhase(prev: Phase) = new StdPhase(prev) {
override def apply(unit: CompilationUnit) {
for (tree <- unit.body) tree match {
case Select(Literal(Constant(regex: String)),symb)
if symb.toString == "r" =>
regexWarning(regex, tree).map{ unit.warning(tree.pos, _) }
case _ => }
def regexWarning(regex: String, tree: Tree): Option[String] =
if (regex.length <= 2) Some("The regex "+regex+" is too short")
else None
}
}
}
} $ type scalac-plugin.xml
<plugin>
<name>regex</name>
<classname>RegexPlugin</classname>
</plugin> $ scalac RegexPlugin.scala $ jar -cf regex.jar RegexPlugin*.class scalac-plugin.xml $ type Example.scala
object Example {
val r1 = "0+".r
val r2 = "[0-9]+".r
} $ scalac -Xplugin:regex.jar Example.scala
Example.scala:2: warning: The regex 0+ is too short
val r1 = "0+".r
^
one warning found
When trying to figure out the proper pattern match expression, the following might be helpful. $ scalac -Xprint:parser -Yshow-trees Example.scala
[[syntax trees at end of parser]]// Scala source: Example.scala
(...)
Select( // sym=<none>, sym.tpe=<notype>, tpe=null
Literal(Constant([0-9]+)),
"r")
(...) Regards,
Grzegorz Balcerek
----- Original Message ----- From: ali [dot] ektefa [at] gmail [dot] com" href="mailto:ali.ektefa@gmail.com" rel="nofollow">Ali ektefa To: scala-internals@googlegroups.com Sent: Saturday, November 05, 2011 6:29 AM Subject: [scala-internals] Scala plugin
Hi,
I'm trying to write a simple static checker for regular expressions. The idea is to look for calls to the r method where the receiver is a constant String and to check that the string contains a well-formed regular expression. I've read the tutorial in scala-lang.org, but I can't find any documentation on how to chane it to achive my goal. I will be greatful if anybody can help.
cheers,
Ali
On Sat, Nov 5, 2011 at 6:29 AM, Ali ektefa wrote:
> I'm trying to write a simple static checker for regular expressions. The
> idea is to look for calls to the r method where the receiver is a constant
> String and to check that the string contains a well-formed regular
> expression. I've read the tutorial in scala-lang.org, but I can't find any
> documentation on how to chane it to achive my goal. I will be greatful if
> anybody can help.
See this part?
def apply(unit: CompilationUnit) {
for ( tree @ Apply(Select(rcvr, nme.DIV),
List(Literal(Constant(0)))) <- unit.body;
if rcvr.tpe <:< definitions.IntClass.tpe)
{
unit.error(tree.pos, "definitely division by zero")
}
}
You instead write something like this. ("Something like" chosen
specifically because this isn't tested and there are a lot of little
things one can do to make things not work.)
def apply(unit: CompilationUnit) {
import definitions._
// the symbol of the implicit in Predef which installs the r method
val augmentMethod = getMember(PredefModule, "augmentString")
// iterating over all subtrees looking for calls to the r method
unit.body foreach {
// which should look about like this for the case you're interested in
case Apply(fn, Literal(Constant(value: String)) :: Nil) if
fn.symbol == augmentMethod =>
println("My logic to check \"" + value + "\" for regex
goodness goes here.")
case _ =>
}
}
}