@@ -203,7 +203,7 @@ object StringContextMacro {
203203 case p :: parts1 => p :: parts1.map((part : String ) => {
204204 if (! part.startsWith(" %" )) {
205205 val index = part.indexOf('%' )
206- if (index != - 1 ) {
206+ if (! reporter.hasReported() && index != - 1 ) {
207207 reporter.partError(" conversions must follow a splice; use %% for literal %, %n for newline" , parts.indexOf(part), index)
208208 " %s" + part
209209 } else " %s" + part
@@ -311,7 +311,7 @@ object StringContextMacro {
311311
312312 // relative indexing
313313 val hasRelative = conversion < l && part.charAt(conversion) == '<'
314- val relativeIndex = conversion + 1
314+ val relativeIndex = conversion
315315 if (hasRelative)
316316 conversion += 1
317317
@@ -333,13 +333,13 @@ object StringContextMacro {
333333 conversion += 1
334334 }
335335 if (oldConversion == conversion) {
336- reporter.partError(" Missing conversion operator in '" + part.substring(pos, oldConversion - 1 ) + " '; use %% for literal %, %n for newline" , partIndex, 0 )
336+ reporter.partError(" Missing conversion operator in '" + part.substring(pos, oldConversion - 1 ) + " '; use %% for literal %, %n for newline" , partIndex, pos )
337337 hasPrecision = false
338338 }
339339 }
340340
341341 // conversion
342- if (conversion >= l || (! part.charAt(conversion).isLetter && part.charAt(conversion) != '%' ))
342+ if (( conversion >= l || (! part.charAt(conversion).isLetter && part.charAt(conversion) != '%' )) && ! reporter.hasReported( ))
343343 reporter.partError(" Missing conversion operator in '" + part.substring(pos, conversion) + " '; use %% for literal %, %n for newline" , partIndex, pos)
344344
345345 val hasWidth = (hasWidth1 && ! hasArgumentIndex) || hasWidth2
@@ -358,7 +358,7 @@ object StringContextMacro {
358358 */
359359 def checkSubtype (actualType : Type , expectedType : String , argIndex : Int , possibilities : Type * ) = {
360360 if (possibilities.find(actualType <:< _).isEmpty)
361- reporter.argError(" type mismatch;\n found : " + actualType.widen.show.stripPrefix(" scala.Predef." ) + " \n required: " + expectedType, argIndex)
361+ reporter.argError(" type mismatch;\n found : " + actualType.widen.show.stripPrefix(" scala.Predef." ).stripPrefix( " scala. " ) + " \n required: " + expectedType, argIndex)
362362 }
363363
364364 /** Checks whether a given argument index, relative or not, is in the correct bounds
@@ -379,7 +379,7 @@ object StringContextMacro {
379379 if (argumentIndex > maxArgumentIndex || argumentIndex <= 0 )
380380 reporter.partError(" Argument index out of range" , partIndex, offset)
381381
382- if (expectedArgumentIndex != argumentIndex)
382+ if (expectedArgumentIndex != argumentIndex && ! reporter.hasReported() )
383383 reporter.partWarning(" Index is not this arg" , partIndex, offset)
384384 }
385385
@@ -545,10 +545,10 @@ object StringContextMacro {
545545 */
546546 def checkSpecials (partIndex : Int , conversionChar : Char , hasPrecision : Boolean , precision : Int , hasWidth : Boolean , width : Int ) = conversionChar match {
547547 case 'n' => {
548- checkNotAllowedParameter(hasPrecision, partIndex, precision + 1 , " precision" )
548+ checkNotAllowedParameter(hasPrecision, partIndex, precision, " precision" )
549549 checkNotAllowedParameter(hasWidth, partIndex, width, " width" )
550550 }
551- case '%' => checkNotAllowedParameter(hasPrecision, partIndex, precision + 1 , " precision" )
551+ case '%' => checkNotAllowedParameter(hasPrecision, partIndex, precision, " precision" )
552552 case _ => // OK
553553 }
554554
@@ -597,13 +597,14 @@ object StringContextMacro {
597597 * @param conversionChar the character used for the conversion
598598 * @param argument an option containing the type and index of the argument, None if there is no argument
599599 * @param flags the flags used for the formatting
600+ * @param formattingStart the index in the part where the formatting substring starts, i.e. where the '%' is
600601 * @return reports an error/warning if the formatting parameters are not allowed/wrong depending on the type, nothing otherwise
601602 */
602- def checkArgTypeWithConversion (partIndex : Int , conversionChar : Char , argument : Option [(Type , Int )], flags : List [(Char , Int )]) = {
603+ def checkArgTypeWithConversion (partIndex : Int , conversionChar : Char , argument : Option [(Type , Int )], flags : List [(Char , Int )], formattingStart : Int ) = {
603604 if (argument.nonEmpty)
604605 checkTypeWithArgs(argument.get, conversionChar, partIndex, flags)
605606 else
606- checkTypeWithoutArgs(conversionChar, partIndex, flags)
607+ checkTypeWithoutArgs(conversionChar, partIndex, flags, formattingStart )
607608 }
608609
609610 /** Checks whether the argument type checks with the formatting parameters
@@ -628,9 +629,9 @@ object StringContextMacro {
628629 case 'd' | 'o' | 'x' | 'X' => {
629630 checkSubtype(argType, " Int" , argIndex, integral : _* )
630631 if (conversionChar != 'd' ) {
631- val notAllowedFlagOnCondition = List (('+' , ! (argType <:< typeOf[java.math.BigInteger ]), " Only use '+' for BigInt conversions to o, x, X" ),
632- (' ' , ! (argType <:< typeOf[java.math.BigInteger ]), " Only use ' ' for BigInt conversions to o, x, X" ),
633- ('(' , ! (argType <:< typeOf[java.math.BigInteger ]), " Only use '(' for BigInt conversions to o, x, X" ),
632+ val notAllowedFlagOnCondition = List (('+' , ! (argType <:< typeOf[java.math.BigInteger ]), " only use '+' for BigInt conversions to o, x, X" ),
633+ (' ' , ! (argType <:< typeOf[java.math.BigInteger ]), " only use ' ' for BigInt conversions to o, x, X" ),
634+ ('(' , ! (argType <:< typeOf[java.math.BigInteger ]), " only use '(' for BigInt conversions to o, x, X" ),
634635 (',' , true , " ',' only allowed for d conversion of integral types" ))
635636 checkFlags(partIndex, flags, notAllowedFlagOnCondition : _* )
636637 }
@@ -641,7 +642,7 @@ object StringContextMacro {
641642 case 'h' | 'H' | 'S' | 's' =>
642643 if (! (argType <:< typeOf[java.util.Formattable ]))
643644 for {flag <- flags ; if (flag._1 == '#' )}
644- reporter.argError(" type mismatch;\n found :" + argType.widen.show.stripPrefix(" scala.Predef." ) + " \n required: java.util.Formattable" , argIndex)
645+ reporter.argError(" type mismatch;\n found : " + argType.widen.show.stripPrefix(" scala.Predef. " ).stripPrefix( " scala ." ) + " \n required: java.util.Formattable" , argIndex)
645646 case 'n' | '%' =>
646647 case illegal =>
647648 }
@@ -652,23 +653,21 @@ object StringContextMacro {
652653 * @param conversionChar the conversion parameter inside the formatting String
653654 * @param partIndex index of the part inside the String Context
654655 * @param flags the list of flags, and their index, used inside the formatting String
656+ * @param formattingStart the index in the part where the formatting substring starts, i.e. where the '%' is
655657 * @return reports an error if the formatting parameter refer to the type of the parameter but no parameter is given
656658 * nothing otherwise
657659 */
658- def checkTypeWithoutArgs (conversionChar : Char , partIndex : Int , flags : List [(Char , Int )]) = {
660+ def checkTypeWithoutArgs (conversionChar : Char , partIndex : Int , flags : List [(Char , Int )], formattingStart : Int ) = {
659661 conversionChar match {
660662 case 'o' | 'x' | 'X' => {
661- val notAllowedFlagOnCondition = List (('+' , true , " Only use '+' for BigInt conversions to o, x, X" ),
662- (' ' , true , " Only use ' ' for BigInt conversions to o, x, X" ),
663- ('(' , true , " Only use '(' for BigInt conversions to o, x, X" ),
663+ val notAllowedFlagOnCondition = List (('+' , true , " only use '+' for BigInt conversions to o, x, X" ),
664+ (' ' , true , " only use ' ' for BigInt conversions to o, x, X" ),
665+ ('(' , true , " only use '(' for BigInt conversions to o, x, X" ),
664666 (',' , true , " ',' only allowed for d conversion of integral types" ))
665667 checkFlags(partIndex, flags, notAllowedFlagOnCondition : _* )
666668 }
667669 case _ => // OK
668670 }
669-
670- if (! reporter.hasReported() && conversionChar != '%' && conversionChar != 'n' )
671- reporter.partError(" conversions must follow a splice; use %% for literal %, %n for newline" , partIndex, 0 )
672671 }
673672
674673 /** Checks that a given part of the String Context respects every formatting constraint per parameter
@@ -699,14 +698,14 @@ object StringContextMacro {
699698 case None => {
700699 val (hasArgumentIndex, argumentIndex, flags, hasWidth, width, hasPrecision, precision, hasRelative, relativeIndex, conversion) = getFormatSpecifiers(part, 0 , 0 , true , formattingStart)
701700 if (hasArgumentIndex && ! (part.charAt(argumentIndex).asDigit == 1 && (part.charAt(conversion) == 'n' || part.charAt(conversion) == '%' )))
702- reporter.partError(" Argument index out of range" , 0 , argumentIndex + 1 )
701+ reporter.partError(" Argument index out of range" , 0 , argumentIndex)
703702 if (hasRelative)
704703 reporter.partError(" No last arg" , 0 , relativeIndex)
705704 if (! reporter.hasReported()){
706705 val conversionWithType = checkFormatSpecifiers(0 , hasArgumentIndex, argumentIndex, None , maxArgumentIndex, hasRelative, hasWidth, width, hasPrecision, precision, flags, conversion, None , part)
707706 nextStart = conversion + 1
708707 if (! reporter.hasReported() && part.charAt(conversion) != '%' && part.charAt(conversion) != 'n' )
709- reporter.partError(" conversions must follow a splice; use %% for literal %, %n for newline" , 0 , 0 )
708+ reporter.partError(" conversions must follow a splice; use %% for literal %, %n for newline" , 0 , part.indexOf( '%' ) )
710709 conversionWithType :: checkPart(part, nextStart, argument, maxArgumentIndex)
711710 } else checkPart(part, conversion + 1 , argument, maxArgumentIndex)
712711 }
@@ -730,16 +729,15 @@ object StringContextMacro {
730729 val argTypeWithConversion = checkPart(parts.head, 0 , None , None )
731730 if (! reporter.hasReported())
732731 for ((argument, conversionChar, flags) <- argTypeWithConversion)
733- checkArgTypeWithConversion(0 , conversionChar, argument, flags)
734- }
735- else {
732+ checkArgTypeWithConversion(0 , conversionChar, argument, flags, parts.head.indexOf('%' ))
733+ } else {
736734 val partWithArgs = parts.tail.zip(args)
737735 for (i <- (0 until args.size)){
738736 val (part, arg) = partWithArgs(i)
739737 val argTypeWithConversion = checkPart(part, 0 , Some ((i, arg)), Some (args.size))
740738 if (! reporter.hasReported())
741739 for ((argument, conversionChar, flags) <- argTypeWithConversion)
742- checkArgTypeWithConversion(0 , conversionChar, argument, flags)
740+ checkArgTypeWithConversion(i + 1 , conversionChar, argument, flags, parts(i).indexOf( '%' ) )
743741 }
744742 }
745743 }
0 commit comments