diff --git a/std/StringTools.hx b/std/StringTools.hx index 3f9d2f93026..b9a44311f78 100644 --- a/std/StringTools.hx +++ b/std/StringTools.hx @@ -464,7 +464,7 @@ class StringTools { #elseif java return (index < s.length) ? cast(_charAt(s, index), Int) : -1; #elseif js - return (cast s).charCodeAt(index); + return js.lib.NativeStringTools.charCodeAt(s, index); #elseif python return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index)); #elseif hl @@ -501,7 +501,7 @@ class StringTools { #elseif java return cast(_charAt(s, index), Int); #elseif js - return (cast s).charCodeAt(index); + return js.lib.NativeStringTools.charCodeAt(s, index); #elseif python return python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index)); #elseif hl diff --git a/std/js/_std/EReg.hx b/std/js/_std/EReg.hx index ae91f2ff697..574e3b97f81 100644 --- a/std/js/_std/EReg.hx +++ b/std/js/_std/EReg.hx @@ -84,7 +84,7 @@ } public inline function replace(s:String, by:String):String { - return (cast s).replace(r, by); + return js.lib.NativeStringTools.replace(s, r, by); } public function map(s:String, f:EReg->String):String { @@ -112,7 +112,7 @@ } public static inline function escape(s:String):String { - return (cast s).replace(escapeRe, "\\$&"); + return js.lib.NativeStringTools.replace(s, escapeRe, "\\$&"); } static var escapeRe = new js.lib.RegExp("[.*+?^${}()|[\\]\\\\]", "g"); diff --git a/std/js/_std/HxOverrides.hx b/std/js/_std/HxOverrides.hx index 8f55624dec0..337090d2c25 100644 --- a/std/js/_std/HxOverrides.hx +++ b/std/js/_std/HxOverrides.hx @@ -56,7 +56,7 @@ class HxOverrides { @:pure static function cca(s:String, index:Int):Null { - var x = (cast s).charCodeAt(index); + var x = js.lib.NativeStringTools.charCodeAt(s, index); if (x != x) // fast isNaN return js.Lib.undefined; // isNaN will still return true return x; diff --git a/std/js/lib/NativeStringTools.hx b/std/js/lib/NativeStringTools.hx new file mode 100644 index 00000000000..fab302646af --- /dev/null +++ b/std/js/lib/NativeStringTools.hx @@ -0,0 +1,131 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.lib; + +import haxe.extern.EitherType; +import js.Lib.undefined; +import js.Syntax; +import js.lib.intl.Collator.CollatorOptions; + +/** + Documentation [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). +**/ +class NativeStringTools { + /** + Returns the Unicode Normalization Form of the calling string value. + */ + public static inline function normalize(string:String, form:NormalizationForm):String { + return Syntax.code("{0}.normalize({1})", string, form); + } + + /** + Returns a number indicating whether a reference string comes before or after or is + the same as the given string in sort order. + */ + public static inline function localeCompare(string:String, compareString:String, ?locales:EitherType>, ?options:CollatorOptions):Bool { + return Syntax.code( + "{0}.localeCompare({1}, {2}, {3})", + string, + (compareString != null) ? compareString : undefined, + (locales != null) ? locales : undefined, + (options != null) ? options : undefined + ); + } + + /** + The characters within a string are converted to lower case while respecting the current locale. + For most languages, this will return the same as toLowerCase(). + */ + public static inline function toLocaleLowerCase(string:String, ?locales:EitherType>):String { + return Syntax.code( + "{0}.toLocaleLowerCase({1})", + string, + (locales != null) ? locales : undefined + ); + } + + /** + The characters within a string are converted to upper case while respecting the current locale. + For most languages, this will return the same as toUpperCase(). + */ + public static inline function toLocaleUpperCase(string:String, ?locales:EitherType>):String { + return Syntax.code( + "{0}.toLocaleUpperCase({1})", + string, + (locales != null) ? locales : undefined + ); + } + + /** + The `charCodeAt()` method of String values returns an integer between 0 + and 65535 representing the UTF-16 code unit at the given index. + + If `index` is out of range of `0` – `str.length - 1`, returns `NaN`. + + See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt + */ + public static inline function charCodeAt(string:String, index:Int):Int { + return Syntax.code("{0}.charCodeAt({1})", string, index); + } + + /** + The `replace()` method of String values returns a new string with one, + some, or all matches of a pattern replaced by a replacement. + + The pattern can be a `String` or a `js.lib.RegExp`, and the replacement + can be a string or a function called for each match. + + If pattern is a string, only the first occurrence will be replaced. The + original string is left unchanged. + + See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace + */ + @:overload(function(str:String, pattern:RegExp, replacement:String):String {}) + @:overload(function(str:String, pattern:RegExp, replacement:String->String):String {}) + @:overload(function(str:String, pattern:String, replacement:String->String):String {}) + public static function replace(string:String, pattern:String, replacement:String):String { + return Syntax.code("{0}.replace({1}, {2})", string, pattern, replacement); + } +} + +enum abstract NormalizationForm(String) { + /** + Normalization Form Canonical Composition. + */ + var NFC; + + /** + Normalization Form Canonical Decomposition. + */ + var NFD; + + /** + Normalization Form Compatibility Composition. + */ + var NFKC; + + /** + Normalization Form Compatibility Decomposition. + */ + var NFKD; +} diff --git a/tests/server/src/cases/issues/Issue11904.hx b/tests/server/src/cases/issues/Issue11904.hx new file mode 100644 index 00000000000..388d7e7173c --- /dev/null +++ b/tests/server/src/cases/issues/Issue11904.hx @@ -0,0 +1,30 @@ +package cases.issues; + +import haxe.display.Diagnostic; + +class Issue11904 extends TestCase { + function test(_) { + vfs.putContent("Issue11904.hx", getTemplate("issues/Issue11904.hx")); + var args = ["-main", "Issue11904", "--js", "no.js", "--no-output"]; + runHaxe(args); + runHaxeJson([], ServerMethods.Invalidate, {file: new FsPath("Issue11904.hx")}); + runHaxeJsonCb(args, DisplayMethods.Diagnostics, {file: new FsPath("Issue11904.hx")}, res -> { + Assert.equals(1, res.length); + Assert.equals(2, res[0].diagnostics.length); + + function check(d:Diagnostic) { + switch (d.kind) { + case ReplaceableCode: + Assert.equals("Unused variable", d.args.description); + + case _: + // trace(d); + Assert.fail("Unexpected diagnostics kind: " + d.kind); + } + } + + var diag = res[0].diagnostics; + for (d in diag) check(d); + }); + } +} diff --git a/tests/server/test/templates/issues/Issue11904.hx b/tests/server/test/templates/issues/Issue11904.hx new file mode 100644 index 00000000000..0a3fc17219c --- /dev/null +++ b/tests/server/test/templates/issues/Issue11904.hx @@ -0,0 +1,9 @@ +using StringTools; + +@:nullSafety +class Issue11904 { + static function main() {} + static function extractReturnType(hint:String):Void { + for (i => code in hint) {} + } +}