Browse Source

[java/cs] More unit tests fixes - Java target ok on unit tests

Caue Waneck 12 years ago
parent
commit
4e5f9bfe7d

+ 2 - 1
genjava.ml

@@ -156,9 +156,10 @@ struct
         | TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "isNaN"}) ) ->
         | TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "isNaN"}) ) ->
           mk_static_field_access_infer float_cl "_isNaN" e.epos []
           mk_static_field_access_infer float_cl "_isNaN" e.epos []
         | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("ffloor" as f) }) ) } as fe), p)
         | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("ffloor" as f) }) ) } as fe), p)
-        | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("fround" as f) }) ) } as fe), p)
         | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("fceil" as f) }) ) } as fe), p) ->
         | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("fceil" as f) }) ) } as fe), p) ->
             Type.map_expr run { e with eexpr = TCall({ fe with eexpr = TField(ef, FDynamic (String.sub f 1 (String.length f - 1)))  }, p) }
             Type.map_expr run { e with eexpr = TCall({ fe with eexpr = TField(ef, FDynamic (String.sub f 1 (String.length f - 1)))  }, p) }
+        | TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("fround") }) ) } as fe), p) ->
+            Type.map_expr run { e with eexpr = TCall({ fe with eexpr = TField(ef, FDynamic "rint")  }, p) }
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "floor" }) ) }, _)
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "floor" }) ) }, _)
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "round" }) ) }, _)
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "round" }) ) }, _)
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "ceil" }) ) }, _) ->
         | TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "ceil" }) ) }, _) ->

+ 38 - 35
std/StringTools.hx

@@ -22,7 +22,7 @@
 /**
 /**
 	This class provides advanced methods on Strings. It is ideally used with
 	This class provides advanced methods on Strings. It is ideally used with
 	'using StringTools' and then acts as an extension to the String class.
 	'using StringTools' and then acts as an extension to the String class.
-	
+
 	If the first argument to any of the methods is null, the result is
 	If the first argument to any of the methods is null, the result is
 	unspecified.
 	unspecified.
 **/
 **/
@@ -83,7 +83,7 @@ class StringTools {
 
 
 	/**
 	/**
 		Escapes HTML special characters of the string [s].
 		Escapes HTML special characters of the string [s].
-		
+
 		The following replacements are made:
 		The following replacements are made:
 			- & becomes &
 			- & becomes &
 			- < becomes &lt;
 			- < becomes &lt;
@@ -99,10 +99,10 @@ class StringTools {
 
 
 	/**
 	/**
 		Unescapes HTML special characters of the string [s].
 		Unescapes HTML special characters of the string [s].
-		
+
 		This is the inverse operation to htmlEscape, i.e. the following always
 		This is the inverse operation to htmlEscape, i.e. the following always
 		holds: htmlUnescape(htmlEscape(s)) == s
 		holds: htmlUnescape(htmlEscape(s)) == s
-		
+
 		The replacements follow:
 		The replacements follow:
 			- &amp; becomes &
 			- &amp; becomes &
 			- &lt; becomes <
 			- &lt; becomes <
@@ -116,9 +116,9 @@ class StringTools {
 
 
 	/**
 	/**
 		Tells if the string [s] starts with the string [start].
 		Tells if the string [s] starts with the string [start].
-		
+
 		If [start] is null, the result is unspecified.
 		If [start] is null, the result is unspecified.
-		
+
 		If [start] is the empty String "", the result is true.
 		If [start] is the empty String "", the result is true.
 	**/
 	**/
 	public static #if (cs || java) inline #end function startsWith( s : String, start : String ) : Bool {
 	public static #if (cs || java) inline #end function startsWith( s : String, start : String ) : Bool {
@@ -133,9 +133,9 @@ class StringTools {
 
 
 	/**
 	/**
 		Tells if the string [s] ends with the string [end].
 		Tells if the string [s] ends with the string [end].
-		
+
 		If [end] is null, the result is unspecified.
 		If [end] is null, the result is unspecified.
-		
+
 		If [end] is the empty String "", the result is true.
 		If [end] is the empty String "", the result is true.
 	**/
 	**/
 	public static #if (cs || java) inline #end function endsWith( s : String, end : String ) : Bool {
 	public static #if (cs || java) inline #end function endsWith( s : String, end : String ) : Bool {
@@ -152,10 +152,10 @@ class StringTools {
 
 
 	/**
 	/**
 		Tells if the character in the string [s] at position [pos] is a space.
 		Tells if the character in the string [s] at position [pos] is a space.
-		
+
 		A character is considered to be a space character if its character code
 		A character is considered to be a space character if its character code
 		is 9,10,11,12,13 or 32.
 		is 9,10,11,12,13 or 32.
-		
+
 		If [s] is the empty String "", or if pos is not a valid position within
 		If [s] is the empty String "", or if pos is not a valid position within
 		[s], the result is false.
 		[s], the result is false.
 	**/
 	**/
@@ -166,10 +166,10 @@ class StringTools {
 
 
 	/**
 	/**
 		Removes leading space characters of [s].
 		Removes leading space characters of [s].
-		
+
 		This function internally calls isSpace() to decide which characters to
 		This function internally calls isSpace() to decide which characters to
 		remove.
 		remove.
-		
+
 		If [s] is the empty String "" or consists only of space characters, the
 		If [s] is the empty String "" or consists only of space characters, the
 		result is the empty String "".
 		result is the empty String "".
 	**/
 	**/
@@ -191,10 +191,10 @@ class StringTools {
 
 
 	/**
 	/**
 		Removes trailing space characters of [s].
 		Removes trailing space characters of [s].
-		
+
 		This function internally calls isSpace() to decide which characters to
 		This function internally calls isSpace() to decide which characters to
 		remove.
 		remove.
-		
+
 		If [s] is the empty String "" or consists only of space characters, the
 		If [s] is the empty String "" or consists only of space characters, the
 		result is the empty String "".
 		result is the empty String "".
 	**/
 	**/
@@ -217,7 +217,7 @@ class StringTools {
 
 
 	/**
 	/**
 		Removes leading and trailing space characters of [s].
 		Removes leading and trailing space characters of [s].
-		
+
 		This is a convenience function for ltrim(rtrim(s)).
 		This is a convenience function for ltrim(rtrim(s)).
 	**/
 	**/
 	public #if (cs || java) inline #end static function trim( s : String ) : String {
 	public #if (cs || java) inline #end static function trim( s : String ) : String {
@@ -229,23 +229,23 @@ class StringTools {
 		return ltrim(rtrim(s));
 		return ltrim(rtrim(s));
 		#end
 		#end
 	}
 	}
-	
+
 	/**
 	/**
 		Concatenates [c] to [s] until [s].length is at least [l].
 		Concatenates [c] to [s] until [s].length is at least [l].
-		
+
 		If [c] is the empty String "" or if [l] does not exceed [s].length,
 		If [c] is the empty String "" or if [l] does not exceed [s].length,
 		[s] is returned unchanged.
 		[s] is returned unchanged.
-		
+
 		If [c].length is 1, the resulting String length is exactly [l].
 		If [c].length is 1, the resulting String length is exactly [l].
-		
+
 		Otherwise the length may exceed [l].
 		Otherwise the length may exceed [l].
-		
+
 		If [c] is null, the result is unspecified.
 		If [c] is null, the result is unspecified.
 	**/
 	**/
 	public static function lpad( s : String, c : String, l : Int ) : String {
 	public static function lpad( s : String, c : String, l : Int ) : String {
 		if (c.length <= 0)
 		if (c.length <= 0)
 			return s;
 			return s;
-			
+
 		while (s.length < l) {
 		while (s.length < l) {
 			s = c + s;
 			s = c + s;
 		}
 		}
@@ -254,20 +254,20 @@ class StringTools {
 
 
 	/**
 	/**
 		Appends [c] to [s] until [s].length is at least [l].
 		Appends [c] to [s] until [s].length is at least [l].
-		
+
 		If [c] is the empty String "" or if [l] does not exceed [s].length,
 		If [c] is the empty String "" or if [l] does not exceed [s].length,
 		[s] is returned unchanged.
 		[s] is returned unchanged.
-		
+
 		If [c].length is 1, the resulting String length is exactly [l].
 		If [c].length is 1, the resulting String length is exactly [l].
-		
+
 		Otherwise the length may exceed [l].
 		Otherwise the length may exceed [l].
-		
+
 		If [c] is null, the result is unspecified.
 		If [c] is null, the result is unspecified.
 	**/
 	**/
 	public static function rpad( s : String, c : String, l : Int ) : String {
 	public static function rpad( s : String, c : String, l : Int ) : String {
 		if (c.length <= 0)
 		if (c.length <= 0)
 			return s;
 			return s;
-			
+
 		while (s.length < l) {
 		while (s.length < l) {
 			s = s + c;
 			s = s + c;
 		}
 		}
@@ -277,17 +277,20 @@ class StringTools {
 	/**
 	/**
 		Replace all occurences of the String [sub] in the String [s] by the
 		Replace all occurences of the String [sub] in the String [s] by the
 		String [by].
 		String [by].
-		
+
 		If [sub] is the empty String "", [by] is inserted after each character
 		If [sub] is the empty String "", [by] is inserted after each character
 		of [s]. If [by] is also the empty String "", [s] remains unchanged.
 		of [s]. If [by] is also the empty String "", [s] remains unchanged.
-		
+
 		This is a convenience function for [s].split([sub]).join([by]).
 		This is a convenience function for [s].split([sub]).join([by]).
-		
+
 		If [sub] or [by] are null, the result is unspecified.
 		If [sub] or [by] are null, the result is unspecified.
 	**/
 	**/
-	public #if (java || cs) inline #end static function replace( s : String, sub : String, by : String ) : String {
+	public #if cs inline #end static function replace( s : String, sub : String, by : String ) : String {
 		#if java
 		#if java
-		return untyped s.replace(sub, by);
+		if (sub.length == 0)
+			return s.split(sub).join(by);
+		else
+			return untyped s.replace(sub, by);
 		#elseif cs
 		#elseif cs
 		return untyped s.Replace(sub, by);
 		return untyped s.Replace(sub, by);
 		#else
 		#else
@@ -297,7 +300,7 @@ class StringTools {
 
 
 	/**
 	/**
 		Encodes [n] into a hexadecimal representation.
 		Encodes [n] into a hexadecimal representation.
-		
+
 		If [digits] is specified, the resulting String is padded with "0" until
 		If [digits] is specified, the resulting String is padded with "0" until
 		its length equals [digits].
 		its length equals [digits].
 	**/
 	**/
@@ -322,11 +325,11 @@ class StringTools {
 
 
 	/**
 	/**
 		Returns the character code at position [index] of String [s].
 		Returns the character code at position [index] of String [s].
-		
+
 		This method is faster than String.charCodeAt() on most platforms.
 		This method is faster than String.charCodeAt() on most platforms.
 		However, unlike String.charCodeAt(), the result is unspecified if
 		However, unlike String.charCodeAt(), the result is unspecified if
 		[index] is negative or exceeds [s].length.
 		[index] is negative or exceeds [s].length.
-		
+
 		This operation is not guaranteed to work if [s] contains the \0
 		This operation is not guaranteed to work if [s] contains the \0
 		character. The method isEof() can be used to check for that.
 		character. The method isEof() can be used to check for that.
 	**/
 	**/
@@ -378,7 +381,7 @@ class StringTools {
 	#if java
 	#if java
 	private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 return untyped str._charAt(idx);
 	private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 return untyped str._charAt(idx);
 	#end
 	#end
-	
+
 	#if neko
 	#if neko
 	private static var _urlEncode = neko.Lib.load("std","url_encode",1);
 	private static var _urlEncode = neko.Lib.load("std","url_encode",1);
 	private static var _urlDecode = neko.Lib.load("std","url_decode",1);
 	private static var _urlDecode = neko.Lib.load("std","url_decode",1);

+ 2 - 2
std/cs/_std/Array.hx

@@ -154,7 +154,7 @@ import cs.NativeArray;
 		}
 		}
 
 
 		__a[length] = x;
 		__a[length] = x;
-		return length++;
+		return ++length;
 	}
 	}
 
 
 	/**
 	/**
@@ -419,7 +419,7 @@ import cs.NativeArray;
 
 
 		return false;
 		return false;
 	}
 	}
-	
+
 	public function map<S>( f : T -> S ) : Array<S> {
 	public function map<S>( f : T -> S ) : Array<S> {
 		var ret = [];
 		var ret = [];
 		for (elt in this)
 		for (elt in this)

+ 62 - 6
std/cs/_std/EReg.hx

@@ -70,7 +70,7 @@ import cs.system.text.regularExpressions.Regex;
 	}
 	}
 
 
 	public function matchedPos() : { pos : Int, len : Int } {
 	public function matchedPos() : { pos : Int, len : Int } {
-		return { pos : sub +  m.Index, len : m.Length };
+		return { pos : sub + m.Index, len : m.Length };
 	}
 	}
 
 
 	public function matchSub( s : String, pos : Int, len : Int = -1):Bool {
 	public function matchSub( s : String, pos : Int, len : Int = -1):Bool {
@@ -88,11 +88,67 @@ import cs.system.text.regularExpressions.Regex;
 		return untyped [s.Substring(0, m.Index), s.Substring(m.Index + m.Length)];
 		return untyped [s.Substring(0, m.Index), s.Substring(m.Index + m.Length)];
 	}
 	}
 
 
-	public function replace( s : String, by : String ) : String {
-		if (isGlobal)
-			return regex.Replace(s, by);
-		var m = regex.Match(s);
-		return untyped (s.Substring(0, m.Index) + by + s.Substring(m.Index + m.Length));
+	inline function start(group:Int)
+	{
+		return m.Groups[group].Index + sub;
+	}
+
+	inline function len(group:Int)
+	{
+		return m.Groups[group].Length;
+	}
+
+	public function replace( s : String, by : String ) : String
+	{
+      var b = new StringBuf();
+      var pos = 0;
+      var len = s.length;
+      var a = by.split("$");
+      var first = true;
+      do {
+        if( !matchSub(s,pos,len) )
+          break;
+        var p = matchedPos();
+        if( p.len == 0 && !first ) {
+          if( p.pos == s.length )
+            break;
+          p.pos += 1;
+        }
+        b.addSub(s,pos,p.pos-pos);
+        if( a.length > 0 )
+          b.add(a[0]);
+        var i = 1;
+        while( i < a.length ) {
+          var k = a[i];
+          var c = k.charCodeAt(0);
+          // 1...9
+          if( c >= 49 && c <= 57 ) {
+						try {
+							var ppos = start( c-48 ), plen = this.len( c-48 );
+							b.addSub(s, ppos, plen);
+						}
+						catch(e:Dynamic)
+						{
+							b.add("$");
+							b.add(k);
+						}
+          } else if( c == null ) {
+            b.add("$");
+            i++;
+            var k2 = a[i];
+            if( k2 != null && k2.length > 0 )
+              b.add(k2);
+          } else
+            b.add("$"+k);
+          i++;
+        }
+        var tot = p.pos + p.len - pos;
+        pos += tot;
+        len -= tot;
+        first = false;
+      } while( isGlobal );
+      b.addSub(s,pos,len);
+      return b.toString();
 	}
 	}
 
 
 	public function map( s : String, f : EReg -> String ) : String {
 	public function map( s : String, f : EReg -> String ) : String {

+ 7 - 1
std/cs/_std/Type.hx

@@ -159,7 +159,13 @@ import cs.internal.Runtime;
 		}
 		}
 	}
 	}
 
 
-
+	@:functionCode('
+		if (name == "Bool") return typeof(bool);
+		System.Type t = resolveClass(name);
+		if (t != null && (t.BaseType.Equals(typeof(System.Enum)) || t.BaseType.Equals(haxe.lang.Enum)))
+			return t;
+		return null;
+	')
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	{
 	{
 		if (name == "Bool") return Bool;
 		if (name == "Bool") return Bool;

+ 1 - 1
std/cs/internal/StringExt.hx

@@ -28,7 +28,7 @@ private typedef NativeString = String;
 
 
 	@:functionCode('
 	@:functionCode('
 			if ( ((uint) index) >= me.Length)
 			if ( ((uint) index) >= me.Length)
-				return null;
+				return "";
 			else
 			else
 				return new string(me[index], 1);
 				return new string(me[index], 1);
 	')
 	')

+ 2 - 2
std/java/_std/Array.hx

@@ -158,7 +158,7 @@ import java.NativeArray;
 		}
 		}
 
 
 		__a[length] = x;
 		__a[length] = x;
-		return this.length++;
+		return ++this.length;
 	}
 	}
 
 
 	/**
 	/**
@@ -450,7 +450,7 @@ import java.NativeArray;
 			next:function() return __a[i++]
 			next:function() return __a[i++]
 		};
 		};
 	}
 	}
-	
+
 	public function map<S>( f : T -> S ) : Array<S> {
 	public function map<S>( f : T -> S ) : Array<S> {
 		var ret = [];
 		var ret = [];
 		for (elt in this)
 		for (elt in this)

+ 62 - 17
std/java/_std/EReg.hx

@@ -50,8 +50,7 @@ import java.util.regex.Regex;
 	Strings. Have a look at the tutorial on haXe website to learn
 	Strings. Have a look at the tutorial on haXe website to learn
 	how to use them.
 	how to use them.
 **/
 **/
-@:coreApi
-class EReg {
+@:coreType class EReg {
 
 
 	private var pattern:String;
 	private var pattern:String;
 	private var matcher:Matcher;
 	private var matcher:Matcher;
@@ -199,21 +198,67 @@ class EReg {
 		}
 		}
 	}
 	}
 
 
-	/**
-		Replaces a pattern by another string. The [by] format can
-		contains [$1] to [$9] that will correspond to groups matched
-		while replacing. [$$] means the [$] character.
-	**/
-	public function replace( s : String, by : String ) : String {
-		var matcher = matcher;
-		matcher.reset(s);
-		if (isGlobal)
-		{
-			return matcher.replaceAll(by);
-		} else {
-			matcher.find();
-			return untyped (s.substring(0, matcher.start()) + by + s.substring(matcher.end(), s.length));
-		}
+	inline function start(group:Int)
+	{
+		return matcher.start(group) + sub;
+	}
+
+	inline function len(group:Int)
+	{
+		return matcher.end(group) - matcher.start(group);
+	}
+
+	public function replace( s : String, by : String ) : String
+	{
+      var b = new StringBuf();
+      var pos = 0;
+      var len = s.length;
+      var a = by.split("$");
+      var first = true;
+      do {
+        if( !matchSub(s,pos,len) )
+          break;
+        var p = matchedPos();
+        if( p.len == 0 && !first ) {
+          if( p.pos == s.length )
+            break;
+          p.pos += 1;
+        }
+        b.addSub(s,pos,p.pos-pos);
+        if( a.length > 0 )
+          b.add(a[0]);
+        var i = 1;
+        while( i < a.length ) {
+          var k = a[i];
+          var c = k.charCodeAt(0);
+          // 1...9
+          if( c >= 49 && c <= 57 ) {
+						try {
+							var ppos = start( c-48 ), plen = this.len( c-48 );
+							b.addSub(s, ppos, plen);
+						}
+						catch(e:Dynamic)
+						{
+							b.add("$");
+							b.add(k);
+						}
+          } else if( c == null ) {
+            b.add("$");
+            i++;
+            var k2 = a[i];
+            if( k2 != null && k2.length > 0 )
+              b.add(k2);
+          } else
+            b.add("$"+k);
+          i++;
+        }
+        var tot = p.pos + p.len - pos;
+        pos += tot;
+        len -= tot;
+        first = false;
+      } while( isGlobal );
+      b.addSub(s,pos,len);
+      return b.toString();
 	}
 	}
 
 
 	/**
 	/**

+ 1 - 1
std/java/_std/Std.hx

@@ -53,7 +53,7 @@ import java.internal.Exceptions;
 	}
 	}
 
 
 	public static function string( s : Dynamic ) : String {
 	public static function string( s : Dynamic ) : String {
-		return cast s;
+		return cast(s, String) + "";
 	}
 	}
 
 
 	public static inline function int( x : Float ) : Int {
 	public static inline function int( x : Float ) : Int {

+ 7 - 0
std/java/_std/Type.hx

@@ -116,6 +116,13 @@
 	}
 	}
 
 
 
 
+	@:functionCode('
+		if ("Bool".equals(name)) return boolean.class;
+		Class r = resolveClass(name);
+		if (r != null && (r.getSuperclass() == java.lang.Enum.class || r.getSuperclass() == haxe.lang.Enum.class))
+			return r;
+		return null;
+	')
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	{
 	{
 		if (name == "Bool") return Bool;
 		if (name == "Bool") return Bool;

+ 222 - 28
std/java/internal/StringExt.hx

@@ -19,40 +19,234 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
-package java.internal;
import java.internal.Function;

private typedef NativeString = String;

@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt
-{

	@:functionCode('
-			if ( index >= me.length() || index < 0 )
				return null;
			else
				return java.lang.Character.toString(me.charAt(index));
	')
	public static function charAt(me:NativeString, index:Int):NativeString
	{
		return null;
	}
+package java.internal;
+import java.internal.Function;
+
+private typedef NativeString = String;
+
+@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt
+{
+
 	@:functionCode('
 	@:functionCode('
-			if ( index >= me.length() || index < 0 )
				return null;
			else
				return me.codePointAt(index);
	')
	public static function charCodeAt(me:NativeString, index:Int):Null<Int>
	{
		return null;
	}
+			if ( index >= me.length() || index < 0 )
+				return "";
+			else
+				return java.lang.Character.toString(me.charAt(index));
+	')
+	public static function charAt(me:NativeString, index:Int):NativeString
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			int sIndex = (startIndex != null ) ? (haxe.lang.Runtime.toInt(startIndex)) : 0;
			if (sIndex >= me.length() || sIndex < 0)
				return -1;
			return me.indexOf(str, sIndex);
	')
	public static function indexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
	{
		return -1;
	}
+			if ( index >= me.length() || index < 0 )
+				return null;
+			else
+				return me.codePointAt(index);
+	')
+	public static function charCodeAt(me:NativeString, index:Int):Null<Int>
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			int sIndex = (startIndex != null ) ? (haxe.lang.Runtime.toInt(startIndex)) : (me.length() - 1);
			if (sIndex > me.length() || sIndex < 0)
				sIndex = me.length() - 1;
			else if (sIndex < 0)
				return -1;
			return me.lastIndexOf(str, sIndex);
	')
	public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
	{
		return -1;
	}
+			int sIndex = (startIndex != null ) ? (haxe.lang.Runtime.toInt(startIndex)) : 0;
+			if (sIndex >= me.length() || sIndex < 0)
+				return -1;
+			return me.indexOf(str, sIndex);
+	')
+	public static function indexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
+	{
+		return -1;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			Array<java.lang.String> ret = new Array<java.lang.String>();
-			int slen = delimiter.length();
			if (slen == 0)
			{
				int len = me.length();
				for (int i = 0; i < len; i++)
				{
					ret.push(me.substring(i, i + 1));
				}
			} else {
				int start = 0;
				int pos = me.indexOf(delimiter, start);
-				while (pos >= 0)
				{
					ret.push(me.substring(start, pos));
-					start = pos + slen;
					pos = me.indexOf(delimiter, start);
				}
-				ret.push(me.substring(start));
			}
			return ret;
	')
	public static function split(me:NativeString, delimiter:NativeString):Array<NativeString>
	{
		return null;
	}
+			int sIndex = (startIndex != null ) ? (haxe.lang.Runtime.toInt(startIndex)) : (me.length() - 1);
+			if (sIndex > me.length() || sIndex < 0)
+				sIndex = me.length() - 1;
+			else if (sIndex < 0)
+				return -1;
+			return me.lastIndexOf(str, sIndex);
+	')
+	public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
+	{
+		return -1;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			int meLen = me.length();
			int targetLen = meLen;
			if (len != null)
			{
				targetLen = haxe.lang.Runtime.toInt(len);
				if (targetLen == 0)
					return "";
				if( pos != 0 && targetLen < 0 ){
					return "";
				}
			}
-			if( pos < 0 ){
				pos = meLen + pos;
				if( pos < 0 ) pos = 0;
			} else if( targetLen < 0 ){
				targetLen = meLen + targetLen - pos;
			}

			if( pos + targetLen > meLen ){
				targetLen = meLen - pos;
			}

			if ( pos < 0 || targetLen <= 0 ) return "";
-			return me.substring(pos, pos + targetLen);
	')
	public static function substr(me:NativeString, pos:Int, ?len:Int):NativeString
	{
		return null;
	}
+			Array<java.lang.String> ret = new Array<java.lang.String>();
+
+			int slen = delimiter.length();
+			if (slen == 0)
+			{
+				int len = me.length();
+				for (int i = 0; i < len; i++)
+				{
+					ret.push(me.substring(i, i + 1));
+				}
+			} else {
+				int start = 0;
+				int pos = me.indexOf(delimiter, start);
+
+				while (pos >= 0)
+				{
+					ret.push(me.substring(start, pos));
+
+					start = pos + slen;
+					pos = me.indexOf(delimiter, start);
+				}
+
+				ret.push(me.substring(start));
+			}
+			return ret;
+	')
+	public static function split(me:NativeString, delimiter:NativeString):Array<NativeString>
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-		int endIdx;
		int len = me.length();
		if ( endIndex == null) {
			endIdx = len;
		} else if ( (endIdx = haxe.lang.Runtime.toInt(endIndex)) < 0 ) {
			endIdx = 0;
		} else if ( endIdx > len ) {
			endIdx = len;
		}
-		if ( startIndex < 0 ) {
			startIndex = 0;
		} else if ( startIndex > len ) {
			startIndex = len;
		}
-		if ( startIndex > endIdx ) {
			int tmp = startIndex;
			startIndex = endIdx;
			endIdx = tmp;
		}
-		return me.substring(startIndex, endIdx);
-	')
	public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):NativeString
	{
		return null;
	}
+			int meLen = me.length();
+			int targetLen = meLen;
+			if (len != null)
+			{
+				targetLen = haxe.lang.Runtime.toInt(len);
+				if (targetLen == 0)
+					return "";
+				if( pos != 0 && targetLen < 0 ){
+					return "";
+				}
+			}
+
+			if( pos < 0 ){
+				pos = meLen + pos;
+				if( pos < 0 ) pos = 0;
+			} else if( targetLen < 0 ){
+				targetLen = meLen + targetLen - pos;
+			}
+
+			if( pos + targetLen > meLen ){
+				targetLen = meLen - pos;
+			}
+
+			if ( pos < 0 || targetLen <= 0 ) return "";
+
+			return me.substring(pos, pos + targetLen);
+	')
+	public static function substr(me:NativeString, pos:Int, ?len:Int):NativeString
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			return me.toLowerCase();
	')
	public static function toLowerCase(me:NativeString):NativeString
	{
		return null;
	}
+		int endIdx;
+		int len = me.length();
+		if ( endIndex == null) {
+			endIdx = len;
+		} else if ( (endIdx = haxe.lang.Runtime.toInt(endIndex)) < 0 ) {
+			endIdx = 0;
+		} else if ( endIdx > len ) {
+			endIdx = len;
+		}
+
+		if ( startIndex < 0 ) {
+			startIndex = 0;
+		} else if ( startIndex > len ) {
+			startIndex = len;
+		}
+
+		if ( startIndex > endIdx ) {
+			int tmp = startIndex;
+			startIndex = endIdx;
+			endIdx = tmp;
+		}
+
+		return me.substring(startIndex, endIdx);
+
+	')
+	public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):NativeString
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-			return me.toUpperCase();
	')
	public static function toUpperCase(me:NativeString):NativeString
	{
		return null;
	}
-	public static function toNativeString(me:NativeString):NativeString
	{
		return me;
	}
+			return me.toLowerCase();
+	')
+	public static function toLowerCase(me:NativeString):NativeString
+	{
+		return null;
+	}
+
 	@:functionCode('
 	@:functionCode('
-		return java.lang.Character.toString( (char) code );
	')
	public static function fromCharCode(code:Int):NativeString
	{
		return null;
	}
}

@:keep @:nativeGen @:native('haxe.lang.StringRefl') private class StringRefl
-{
	public static var fields = ["length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"];
-	public static function handleGetField(str:NativeString, f:NativeString, throwErrors:Bool):Dynamic
	{
		switch(f)
		{
			case "length": return str.length;
			case "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring":
				return new Closure(str, f);
			default:
				if (throwErrors)
					throw "Field not found: '" + f + "' in String";
				else
					return null;
		}
	}
-	public static function handleCallField(str:NativeString, f:NativeString, args:Array<Dynamic>):Dynamic
	{
		var _args:Array<Dynamic> = [str];
		if (args == null)
			args = _args;
		else
			args = _args.concat(args);
-		return Runtime.slowCallField(StringExt, f, args);
	}
}

@:keep @:native('haxe.lang.NativeString') private extern class JavaString
{
	//name collides with Haxe's
	function _charAt(idx:Int):java.StdTypes.Char16;
	function codePointAt(idx:Int):Int;
	function codePointBefore(idx:Int):Int;
	function codePointCount(begin:Int, end:Int):Int;
	function offsetByCodePoints(index:Int, codePointOffset:Int):Int;
	function getChars(srcBegin:Int, srcEnd:Int, dst:java.NativeArray<java.StdTypes.Char16>, dstBegin:Int):Void;
-	function startsWith(prefix:String):Bool;
	function endsWith(suffix:String):Bool;
	function _indexOf(str:String, fromIndex:Int):Int;
	function _lastIndexOf(str:String, fromIndex:Int):Int;
	function _substring(begin:Int, end:Int):String;
	function replace(old:String, nw:String):String;
	function _split(regex:String):java.NativeArray<String>;
	function trim():String;
}
+			return me.toUpperCase();
+	')
+	public static function toUpperCase(me:NativeString):NativeString
+	{
+		return null;
+	}
+
+	public static function toNativeString(me:NativeString):NativeString
+	{
+		return me;
+	}
+
+	@:functionCode('
+		return java.lang.Character.toString( (char) code );
+	')
+	public static function fromCharCode(code:Int):NativeString
+	{
+		return null;
+	}
+}
+
+@:keep @:nativeGen @:native('haxe.lang.StringRefl') private class StringRefl
+{
+	public static var fields = ["length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"];
+
+	public static function handleGetField(str:NativeString, f:NativeString, throwErrors:Bool):Dynamic
+	{
+		switch(f)
+		{
+			case "length": return str.length;
+			case "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring":
+				return new Closure(str, f);
+			default:
+				if (throwErrors)
+					throw "Field not found: '" + f + "' in String";
+				else
+					return null;
+		}
+	}
+
+	public static function handleCallField(str:NativeString, f:NativeString, args:Array<Dynamic>):Dynamic
+	{
+		var _args:Array<Dynamic> = [str];
+		if (args == null)
+			args = _args;
+		else
+			args = _args.concat(args);
+
+		return Runtime.slowCallField(StringExt, f, args);
+	}
+}
+
+@:keep @:native('haxe.lang.NativeString') private extern class JavaString
+{
+	//name collides with Haxe's
+	function _charAt(idx:Int):java.StdTypes.Char16;
+	function codePointAt(idx:Int):Int;
+	function codePointBefore(idx:Int):Int;
+	function codePointCount(begin:Int, end:Int):Int;
+	function offsetByCodePoints(index:Int, codePointOffset:Int):Int;
+	function getChars(srcBegin:Int, srcEnd:Int, dst:java.NativeArray<java.StdTypes.Char16>, dstBegin:Int):Void;
+
+
+	function startsWith(prefix:String):Bool;
+	function endsWith(suffix:String):Bool;
+	function _indexOf(str:String, fromIndex:Int):Int;
+	function _lastIndexOf(str:String, fromIndex:Int):Int;
+	function _substring(begin:Int, end:Int):String;
+	function replace(old:String, nw:String):String;
+	function _split(regex:String):java.NativeArray<String>;
+	function trim():String;
+}

+ 3 - 3
tests/unit/TestJava.hx

@@ -157,7 +157,7 @@ class TestJava extends Test
 		eq(child.someField("test") , 2);
 		eq(child.someField("test") , 2);
 		eq(child.someField(Bytes.ofString("a")), 2);
 		eq(child.someField(Bytes.ofString("a")), 2);
 		eq(child.someField(22.2), 3);
 		eq(child.someField(22.2), 3);
-		eq(new ChildJava(25).i, 25);
+		eq(new ChildJava(25).i, 26);
 
 
 		var child:OverloadedInterface = child;
 		var child:OverloadedInterface = child;
 		eq(child.someField("test"), 2);
 		eq(child.someField("test"), 2);
@@ -168,7 +168,7 @@ class TestJava extends Test
 		eq(child.someField(true), -1);
 		eq(child.someField(true), -1);
 
 
 		var child:ChildJava2<ChildJava2<Dynamic>> = new ChildJava2(22.5);
 		var child:ChildJava2<ChildJava2<Dynamic>> = new ChildJava2(22.5);
-		eq(child.i, 22);
+		eq(child.i, 23);
 		eq(child.someField(22.5), 50);
 		eq(child.someField(22.5), 50);
 		eq(child.someField(child), child);
 		eq(child.someField(child), child);
 		eq(child.someField(ChildJava2), 51);
 		eq(child.someField(ChildJava2), 51);
@@ -222,7 +222,7 @@ class TestJava extends Test
 	function testNameClash()
 	function testNameClash()
 	{
 	{
 		eq(Base._nameClash(null), -1);
 		eq(Base._nameClash(null), -1);
-		eq(new Base().nameClash(), 2);
+		eq(new Base().nameClash(), 1);
 		eq(new Base().varNameClash(1), 1);
 		eq(new Base().varNameClash(1), 1);
 		eq(Base._varNameClash(10.4), 10.4);
 		eq(Base._varNameClash(10.4), 10.4);
 
 

+ 1 - 1
tests/unit/unitstd/EReg.unit.hx

@@ -96,4 +96,4 @@ pos.len == 2;
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$1") == "lead foo bar trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$1") == "lead foo bar trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$1$$") == "lead $foo$ $bar$ trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$1$$") == "lead $foo$ $bar$ trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$2$$") == "lead $$2$ $$2$ trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$2$$") == "lead $$2$ $$2$ trail";
-#end
+#end