@@ -91,6 +91,7 @@ public class GroovyPageParser implements Tokens {
9191 private GSPWriter out ;
9292 private String className ;
9393 private String packageName ;
94+ private String sourceName ; // last segment of the file name (eg- index.gsp)
9495 private boolean finalPass = false ;
9596 private int tagIndex ;
9697 private Map <Object , Object > tagContext ;
@@ -227,6 +228,7 @@ public GroovyPageParser(String name, String uri, String filename, InputStream in
227228 pageName = uri ;
228229 environment = Environment .getCurrent ();
229230 makeName (name );
231+ makeSourceName (filename );
230232 }
231233
232234 private Map <String , String > parseDirectives (String gspSource ) {
@@ -683,6 +685,22 @@ else if (ix == 0 && c >= '0' && c <= '9') {
683685 className = buf .toString ();
684686 }
685687
688+ /**
689+ * find the simple name of this gsp
690+ * @param filename the fully qualified file name
691+ */
692+ private void makeSourceName (String filename ) {
693+ if (filename != null ) {
694+ int lastSegmentStart = filename .lastIndexOf ('/' );
695+ if (lastSegmentStart == -1 ) {
696+ lastSegmentStart = filename .lastIndexOf ('\\' );
697+ }
698+ sourceName = filename .substring (lastSegmentStart + 1 );
699+ } else {
700+ sourceName = className ;
701+ }
702+ }
703+
686704 private static boolean match (CharSequence pat , CharSequence text , int start ) {
687705 int ix = start , ixz = text .length (), ixy = start + pat .length ();
688706 if (ixz > ixy ) {
@@ -831,6 +849,10 @@ private void page() {
831849 out .println ("null" );
832850 }
833851 out .println ("}" );
852+
853+ if (shouldAddLineNumbers ()) {
854+ addLineNumbers ();
855+ }
834856 }
835857 else {
836858 for (int i = 0 ; i < DEFAULT_IMPORTS .length ; i ++) {
@@ -839,6 +861,64 @@ private void page() {
839861 }
840862 }
841863 }
864+
865+ /**
866+ * Determines if the line numbers array should be added to the generated Groovy class.
867+ * @return true if they should
868+ */
869+ private boolean shouldAddLineNumbers () {
870+ try {
871+ // for now, we support this through a system property.
872+ String prop = System .getenv ("GROOVY_PAGE_ADD_LINE_NUMBERS" );
873+ return Boolean .valueOf (prop ).booleanValue ();
874+ } catch (Exception e ) {
875+ // something wild happened
876+ return false ;
877+ }
878+ }
879+
880+ /**
881+ * Adds the line numbers array to the end of the generated Groovy ModuleNode
882+ * in a way suitable for the LineNumberTransform AST transform to operate on it
883+ */
884+ private void addLineNumbers () {
885+ out .println ();
886+ out .println ("@org.codehaus.groovy.grails.web.transform.LineNumber(" );
887+ out .print ("\t lines = [" );
888+ // get the line numbers here. this will mean that the last 2 lines will not be captured in the
889+ // line number information, but that's OK since a user cannot set a breakpoint there anyway.
890+ int [] lineNumbers = filterTrailing0s (out .getLineNumbers ());
891+
892+ for (int i = 0 ; i < lineNumbers .length ; i ++) {
893+ out .print (lineNumbers [i ]);
894+ if (i < lineNumbers .length - 1 ) {
895+ out .print (", " );
896+ }
897+ }
898+ out .println ("]," );
899+ out .println ("\t sourceName = \" " + sourceName + "\" " );
900+ out .println (")" );
901+ out .println ("class ___LineNumberPlaceholder { }" );
902+ }
903+
904+ /**
905+ * Filters trailing 0s from the line number array
906+ * @param lineNumbers the line number array
907+ * @return a new array that removes all 0s from the end of it
908+ */
909+ private int [] filterTrailing0s (int [] lineNumbers ) {
910+ int startLocation = lineNumbers .length - 1 ;
911+ for (int i = lineNumbers .length -1 ; i >= 0 ; i --) {
912+ if (lineNumbers [i ] > 0 ) {
913+ startLocation = i + 1 ;
914+ break ;
915+ }
916+ }
917+
918+ int [] newLineNumbers = new int [startLocation ];
919+ System .arraycopy (lineNumbers , 0 , newLineNumbers , 0 , startLocation );
920+ return newLineNumbers ;
921+ }
842922
843923 private void endTag () {
844924 if (!finalPass ) return ;
0 commit comments