From 2997eaea439aafe5356daa53204764a086f9b070 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 9 May 2016 20:23:17 +0100 Subject: [PATCH 01/58] Reapply "Merge pull request #18 from unascribed/partial-xdg-implementation" This reverts commit d1abab770414c77f74a9a713e064640a1a82cb7b. --- .../lapis/nocturne/util/OperatingSystem.java | 64 ++++++++++++++++++- .../util/helper/PropertiesHelper.java | 4 +- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/util/OperatingSystem.java b/src/main/java/blue/lapis/nocturne/util/OperatingSystem.java index cd6c5ea..81c8df9 100644 --- a/src/main/java/blue/lapis/nocturne/util/OperatingSystem.java +++ b/src/main/java/blue/lapis/nocturne/util/OperatingSystem.java @@ -33,7 +33,28 @@ public enum OperatingSystem implements Predicate { OSX("mac"), - LINUX("nix", "nux"), + LINUX("nix", "nux") { + private final String home = System.getenv().getOrDefault("HOME", System.getProperty("user.home", "~")); + + private final String dataHome = System.getenv().getOrDefault("XDG_DATA_HOME", home + "/.local/share"); + private final String configHome = System.getenv().getOrDefault("XDG_CONFIG_HOME", home + "/.config"); + private final String cacheHome = System.getenv().getOrDefault("XDG_CACHE_HOME", home + "/.cache"); + + @Override + public String getConfigFolder() { + return configHome; + } + + @Override + public String getDataFolder() { + return dataHome; + } + + @Override + public String getCacheFolder() { + return cacheHome; + } + }, WINDOWS("win"), UNKNOWN; @@ -53,18 +74,57 @@ public boolean test(String s) { return false; } - public String getAppDataFolder() { + /** + * Returns the path to the config home, as defined by the XDG Base Directory specification. + * + *

The config home defines the base directory relative to which user specific configuration + * files should be stored. On Linux, this can be modified by the environment variable + * {@code $XDG_CONFIG_HOME}. On OS X, this is ~/Library/Application Support. On Windows, + * this is %APPDATA%. + * + * @return The path to the config home, as defined by the XDG Base Directory specification. + */ + public String getConfigFolder() { switch (this) { case OSX: return System.getProperty("user.home") + "/Library/Application Support"; case WINDOWS: return System.getenv("APPDATA"); case LINUX: + throw new AssertionError(); case UNKNOWN: default: return System.getProperty("user.home"); } } + + /** + * Returns the path to the data home, as defined by the XDG Base Directory specification. + * + *

The data home defines the base directory relative to which user specific data + * files should be stored. On Linux, this can be modified by the environment variable + * {@code $XDG_DATA_HOME}. On other operating systems, this method is equivalent to + * {@code getConfigFolder()}. + * + * @return The path to the data home, as defined by the XDG Base Directory specification. + */ + public String getDataFolder() { + return getConfigFolder(); + } + + /** + * Returns the path to the cache home, as defined by the XDG Base Directory specification. + * + *

The cache home defines the base directory relative to which user specific + * non-essential data files should be stored. On Linux, this can be modified + * by the environment variable {@code $XDG_CACHE_HOME}. On other operating systems, + * this method is equivalent to {@code getConfigFolder()}. + * + * @return The path to the cache home, as defined by the XDG Base Directory specification. + */ + public String getCacheFolder() { + return getConfigFolder(); + } /** * Gets the operating system currently running on the user's system. diff --git a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java index 97d0d68..f5b35ff 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java @@ -89,9 +89,9 @@ public void store() throws IOException { } private File getNocturneDirectory() { - String appdata = OperatingSystem.getOs().getAppDataFolder(); + String appdata = OperatingSystem.getOs().getConfigFolder(); if (OperatingSystem.getOs() == OperatingSystem.LINUX) { - return new File(appdata, ".config" + File.separator + "nocturne"); + return new File(appdata, "nocturne"); // to maintain compatibility with earlier Nocturne versions } else { return new File(appdata, "Nocturne"); } From ca615e926a15815c063b64f092a423f4613bb51f Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 9 May 2016 20:49:38 +0100 Subject: [PATCH 02/58] Enable Enigma support --- .../io/mappings/MappingsOpenDialogHelper.java | 17 +++++++++++++++-- .../mapping/io/reader/MappingReaderType.java | 6 +++--- src/main/resources/lang/de_DE.properties | 3 +++ src/main/resources/lang/en_US.properties | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index 24c5f1f..0ed9f7d 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -32,6 +32,8 @@ import blue.lapis.nocturne.mapping.io.reader.MappingsReader; import blue.lapis.nocturne.util.helper.PropertiesHelper; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; import java.io.BufferedReader; @@ -73,8 +75,19 @@ public static void openMappings() throws IOException { Path selectedPath = selectedFile.toPath(); if (Files.exists(selectedPath)) { //TODO: isn't this redundant? - try (MappingsReader reader = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()) - .constructReader(new BufferedReader(new FileReader(selectedFile)))) { + MappingReaderType type = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); + try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { + if (type == MappingReaderType.ENIGMA) { + Alert confirmEngima = new Alert(Alert.AlertType.CONFIRMATION, + Main.getResourceBundle().getString("enigma.support_notice"), + ButtonType.YES, ButtonType.NO); + confirmEngima.showAndWait(); + + if (confirmEngima.getResult() == ButtonType.NO) { + return; + } + } + MappingContext context = reader.read(); Main.getMappingContext().assimilate(context); MainController.INSTANCE.updateClassViews(); diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java index 1ccb576..04c59b9 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java @@ -39,9 +39,9 @@ public enum MappingReaderType { SRG(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_srg"), "*.srg"), - SrgReader.class); - /*ENIGMA(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_enigma"), "*.*"), - EnigmaReader.class);*/ + SrgReader.class), + ENIGMA(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_enigma"), "*.*"), + EnigmaReader.class); private static final Map filterToType = Maps.newHashMap(); diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index db6a2b5..2845f22 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -45,6 +45,9 @@ filechooser.save_mapping=Zieldatei ausw\u00e4hlen filechooser.dirty.title=Speichern? filechooser.dirty.content=M\u00f6chtest du die gegenw\u00e4rtig Zuordnungen speichern? +enigma.support_notice=The parsing of Enigma files, is a flawed part of Nocturne however is provided to allow people \ + to convert their mappings. It may very well fail! + exception.title=Och N\u00f6\! exception.header=Etwas in Nocturne is kaputt\! \:( exception.dialog1=Du kannst "OK" zum Fortfahren oder "Schlie\u00dfen" zum Beenden klicken. diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 9454894..688822e 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -44,6 +44,9 @@ filechooser.save_mapping=Select Destination File filechooser.dirty.title=Save? filechooser.dirty.content=Would you like to save the current mappings? +enigma.support_notice=The parsing of Enigma files, is a flawed part of Nocturne however is provided to allow people \ + to convert their mappings. It may very well fail! + exception.title=Aw, rats! exception.header=Something has broken inside Nocturne! :( exception.dialog1=You may click "OK" to continue work within the program, or "Close" to exit. From 208b8a3b7ed261a028b952d3c3935c629e4f40c1 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 9 May 2016 20:55:21 +0100 Subject: [PATCH 03/58] Update Gradle wrapper to 2.13 --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 41d28ba..f60afbe 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ defaultTasks 'clean', 'licenseFormat', 'build' // Project information allprojects { group = 'blue.lapis.nocturne' - version = '1.0.3-SNAPSHOT' + version = '1.1.0-SNAPSHOT' sourceCompatibility = '1.8' targetCompatibility = '1.8' @@ -125,5 +125,5 @@ artifacts { } task wrapper(type: Wrapper) { - gradleVersion = '2.12' + gradleVersion = '2.13' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8d4e470..a8201e2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Mar 27 23:56:52 BST 2016 +#Mon May 09 20:53:41 BST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip From 5026e126dee34a6ddca91dd9a9b3495bc8a6c0f3 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 14 Aug 2016 17:23:05 +0100 Subject: [PATCH 04/58] Update Gradle wrapper to 2.14 --- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 53324 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 46 ++++++++++++----------- gradlew.bat | 8 ++-- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index f60afbe..d99d3fa 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'net.minecrell.gitpatcher' version '0.8' - id 'net.minecrell.licenser' version '0.1.5' + id 'net.minecrell.licenser' version '0.2.1' id 'com.github.johnrengelman.shadow' version '1.2.3' } @@ -125,5 +125,5 @@ artifacts { } task wrapper(type: Wrapper) { - gradleVersion = '2.13' + gradleVersion = '2.14' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 941144813d241db74e1bf25b6804c679fbe7f0a3..3baa851b28c65f87dd36a6748e1a85cf360c1301 100644 GIT binary patch delta 5484 zcmaJ_2{=@3`yazZ*_W|38vDM7tSS2*QuZxlDND8xF`-n}>Le1PNJ_RD^oqoo!Prt+ zlAY{{O4j%vGv4~<`>yMMuIpUqKKJ~7_x3!`eV%8oJ)!Q%qh_)+rKULqfzZ)GX!O4u z-C+`8+4D&9{4}IzhZy;}CP#V#l2l_P z0mB3hhLTm+Xr{@k0N4|<3InHOJ3!V+F%3YO_AH?yJ4Wx)KpVGaNfA z#;O7cV!e`)V?ot5M{7AF5v(MKFdQmESLiY?kS%&6A!MS>nCjx{rh_ZOdp`amQ&l?076d~96&$-X*_=`N)WdI1q^p#8+T1JUV?qGEQ)ab)`_iz*yw^qIdzIM* zty0Ht&eOqX@S;n`cdRR5r$tf4Mw3FY>O=+v%pSg$|6+i^Bxf*vGcPaB8IGJ}hd-J) z3V$>in<%$j7*}R<1)Xw{=D?{DYp6_mhTRF7!W91ijxwpw+bRo|m#I(-?IDM<)xy$$ zrRzmZNJt6Aw}qOWGlcf8oy#NI2rE0q%2j{HEW5NwW=3d0drt@+@I_gkv$q)Rt6qF~ zWoLD9Cv&NFGGinnYYJ!Qb-T>GV(wFt=knc_yqANLdBRm@Hlt{Fx|#<_;%V(jPX|eM zZ|xP&>YR?}bX)3xb2mqS_yIv>`(Tl&Te82Iw+tUBr`I2F z>hk3eEF^qqhc*9D?M5nI%}9zww$NwyHg=cYW~Tlk;-G_o8Fr5yZ~k`KNZT`dWY+Mi zwG2f5>d90_?k0J(m6PPe#I#t%Z%SLj7T_wY|_>Jy)AH0+2EJK4Z~oc zvHlv`OG7g7hOM?Ekxy<|_A~Y9{VcAYMmTUkR=!bvCmO5G)0IC7$$|FVq0Z)vxVB(Z zOG6lr31{*i+*S+KZd&e{`Ueq7(28NMdh||hYHiBddrs@E8k+0u+Kw7`Bm>vRtl{lj zv_Wdxn+gd*O7Df3k@^~6>?4AhI;Seq88+Kok@gES-Z!x{YN=L-#bn&sFo~=K*yH?9 zn0Z!dcicB%Wn;F<)5cEcu*XB$;8U{hKUu;b4C;ome=>~puS?8WR+Q)sjF&Q;6RE)tDEv3zTgd{+X;$dhYpb?>XWy`7|qLNnT})xy4j>v6ef z*g4B_VwiryL&*SqAi`0>uN^(JTp@n^2u^Idjr;g@F8xhxVt4EICvJ<$5XCDlcz?L- z&50xh;bm(MSGF&5?aOe5pJ(p8;l%fQ?ig^4CQmpjTsb_-IwNPeGA#Z^Ow9G{N;F*C zGSIIUTgoM7-cr?BmFSDUFAa0(t7M3J{7fTtTwL|iw%D z*FA?-Jo)?*h8TfoTScZ}0+X+aLzSz+pURJh)V@|AJX0w?|DmU1DyDzpt50L#+K-AX zKhFgTv=_F&QwQItA0E0aQ_oa)D{$N|x(p7J>BNRUGx(vjki-{O+$`^h zE+itIVDHahO59X7rqPS_@v4p}mzM*0sanj*TZql~x-xZG%_|Wf0ul9YW?3*?5d7zc zNos{lg?YFJ@OkUlD$e(Fsg3vNsvy`Q56y~}`Hy|IR!r-+RCDP?`&3j+kEImL^p_*j zrf+|#cygOj#I!4}V=H@=wp9k#Dc$MKOlLpqRGG9Y_@>N!(i8pE`DC&|%L9S5-#hW2 zd~DE0Y{Yo_!o>Q3R#B;FSH_gqgN#oiY;d$eR(L61(Pdr6{$*@Jk^BpRr1LIQ_4k#x z>B5yXX>)9AdGHZ<>1jqsT$=uj*t!Hyo6q`#5`&cx#s-$Tj8{*_wl&HED^{f74Sn+Q z_9OE{Q$mt4PsY(T>p6*|zU$OG&&E%!W8!3)2ShtP37tB9!6|Whn@Qry6J>EehK(zn z56-^(FpyJbSNhNS#SKjOV;hNS_Oor~e&zD)PtTOTI@q9O(ERH~a%R)$ayVo7N>;*i zy(_jumsF0OU{oIR_#WRyNV0W5dbsUjbt2j)!kJAz(YY@dh2A+ASC}rJqlb?iksKDx zY<9FVdX(bk)gQpUP{+#L(AnOGYipdopgHofmr&2UU{YN&@AXBk?5@xRktoF-;~1_k zE-_~ra9-e5y!S)i0D9f_ogDYH?+OR#kvO~dvvmzGYrdD)H2OvrTLo_J{^V&8L)EYO z<=A!cAvR)Do})1vGzahGj@6V|23zvl6Sz|RYl4U#-B_6M8VsJ{p{GIMVQ#scl92u&G{hTSNRRWKBGE}mGrux>!S{pKEKhTA5qGVxWnIaJDiWQptD>0;ZkE?4vMXn2pVym+NB(O3rX;eA zU=JU`-T&_Yv4Sx|mE%;__q)%=sirjj{J$T7jeJ|q&PLpNRC|LqICMbksNO}b*Q)hw zf{#adH`QsMM+A!1BsH6CGaT*RP4M1eIK5LEJ(LoJFr@WZLRD_fZAeGczgbh*p^H?w zk+!UdrrmhZ0a^97ldAPVz_*tZ z!;CHyE=s2qPk+E>3r%8jcdwzVm-6Y6tD4U~+BKdjYu%V*S+6XX35#rP(fvojxbbb_ zadpHX&pf@BEgr|1CdR|VZJHV6lUx7{Okzh`(I%&ceVKFJ5q?3cv1iK8DY*!)$k~sF z8;|XZ3J z*;HCs<%x{GuV&|YX*R0#D~fMUxG#>OBx>eIN1hFztHD{m*Th}Qa{`qSMwI^yJ9(>* zK1vTGOR1`Gda_ic`|A){%C{KWKN7^AIk10BNV2t|W8C|=PF{cKdIUU^Ab>?zNfjw^ zVz-I8tVFfBoQYYRaj$t-+mxhar&L>qc@^wG0$2i>?bkb=hJ(x$2oU3jM7P&7HSu$t z7|*d)IRDCRgU4>j$>}F->5GoAM4`mTnVR_A6;mcY&vD!0V&)P@OSWX}SV51)=Oj(` zie3jo4)s<6L}|+`n4l)emQS_7r=Zq_Sjm2y^!|}l!0%y$)>l7;kDvcm`107I#Iu8? z?AvoeHYQul4S)6wFvwm^K!m##&7OcMa=!s(-IEkuJ=30oVa|fLIM5R+40xbw$e1IZ zJ5aL3?=!nEG5Fr4BJs4je0E!CA&?vF;K_-^;~*k1-~4)L$&}{MBh+MRI$WKaY0s5l zWShfX7zFZw5ul2P1A%Gu7>lT9FfwZM>IM~AT8sO*Z=*Z$9od3}n^r5JVhWu-C36z=?ef8V&kWA3vb8z3Z7ri9F z+s%m?EqlCAxnAkCAI%rciG8xftL}Z>_CKe|#WSd;ThpS3K!^t+5DijXX`L{Dp$Cr1 ztuv%%+e?~x7iY@>)|L&tkr2SVM?m<`Ec)`FbB7AbLH+kk31|MeKH4>F9v(dS(^Se_TLQpe+iI1M&mxiJJ=oN=lTB{aDc@F;g8N3B4z?XrbCIu3PrZ{rg2{dR08kC{HcmRz}nxy3p zP~mu?hv-Q5Rq6NvyJiMbFdd9826sU21~?-qx%^BZ7y)GAkR;&WzY8D`c?u`nEF`N- zI0>?+!_B^k18K$ht##Ug%Fn zl1>9JN=n_RuSWO-IDLe;!DUQglp45-KSt)g26+fw5^oVNM9St<7i&Zwm@*bTJW!UE z(_-H#EnrF@57-6%3%9XU5Xf0@%Bxa1`DH@_FLN^j`2=B-<+~mxhk58A5L0FdM1TSe zu_b{^ZJ7YN7IO9fv{?{HIdAM-ffZK~z#atdEvLU-6#@ZM{c~YsYg~crEuy4#4wSX< zLQ!r&dkY`=eGz;I+<@^S9-zye7tm;BAnQ$Ad7(!vu4r^2wFEru>7`g19v?&@s1v#b^^z`p2 zbn`-kDo8aet7QI@qHYi8^gLLvE1+jh3UW^+2o?hRy7wmv)jM7&yawQVXGjWJ2JRC_ z3l86FFlFbW4m8}^j{ E2en2;ga7~l delta 5699 zcma)AcT`i$*A0;-y@e8KA|-SPRS^^-y?1z^AiW8Mj)IY@0)lu!R6tNEB1ngap-Bn7 z2|kb_RXS2cy67(?dHUu3_1(3SnYCxn-e+bGlY8jNJ{A4y6rGXoDN-sBh>{ZIcNwXf zOea8l(za}9a9jd`KxWC8O(E9b{I>i^K!2DnC(J@#Qe4|Fgl`WeaV;QDGL7q0FoONS zc<3(a0v z(w$m@x?dUT=)_Qh-4E~Gfp}4g4Cv(2^BajpqV;`%7$*fU`AP^RYhUBInI^HtQssP9 z3;X-Nj^JOgonVC*z42o%H`nVI1N#p${rlIZe*HLLyK}s6-6E0jIs}1W){xC;eI2JD zw=b}rLJo2KCM6NfEFx&0fwI_o9BYw4iqt4Rt=*^NXAqTGz}x2;a%O07O^tf83BzjJ zT>Gd_NK#2Ccf(Uk>YTPoi&(VTb5B(&cSv4bHx(F>=Zw~b$ZDeVS@sjhE7Y1|rH7c9 zW7ZOU`=Bx$eq(KGImu7qoTksa^|I3Cx2bNndkH~w&$oGLv@UR+L!~hrh?PAFR^P33 z+@5~MhZ-z}1d9IMx zELX{6p2}PMid;-Ym1MW3&|S7ie2dSj)vdQ7WibD(9F7(pjGN0}!f_vqW(0?tt%KG- zuiZ0)poX%r@~%qjeA>;oY%=N8kZrFU6J>0v80)D!zVmKA!1<$-nQKvY zZc$lBv@@dz$z62C?-4mDG` zdO1EW-_!|g@lTk)M@JE=ZOcVw3y}1RetKdTJL7=Lxit3HLA9MvWdO;=^JZVGy}jne zEHhVDq;*(qe<0_36q`uHN2IA=L-UA8!-p;LhM_Ix+eS#;_N0An)qt<`Pa{6=HiGM! zbm`bCCYCuR*sLca2-b7goQJG5*>|#Fh7;#^%>zd^O=<-mFRD^LX*1C%_rk!NoJD5ypi6; zs|@P&Rc=KW@6fA$`)Q>%^c^9aq#nO{3`X@I3+#7NCP=Dg<}FTN@v&oE-7onZrLqL1 zKiue4juv{HZ7BI7b!>H9o~0~VLLTyAc#k1HtMW!@^zQvh6koN9#@$F&yN*5fah8du z)9VY7wHQBy8OnlZ565rb% zS`}30&UU`jK<=jeo+$@OB{>vt7-?Ww;!8WLFv;zjthNt9C^pa9&h8Bx*Xf{2QmL&5 zZ)VmyUQ15$4{jc({Y621!{&xcp)D#lAaVHXvCnTc4nhF}dDDSFf&ioWIl#Mx9F=Nu z;CRN8@#pX`Bot7L^Z!&8OL=+$`Lu+U&5`GB)7jLfg47z+Ej}S?NZb$Y`9PMD9B8u|NZM{|FHr|MqA^oVq7zK z2F8Sw+`Cn{o)=*pI}g(vt#&G7!l2@jt;P?zZ1{!9Ef-8UjVDsR+Q5r6%2?Y~!}t@E zx=^lLCNwn7rSs8C!j6jdM`3Svng2@I7Xan*_JVF0k+fHHSaFw=Lz{crm^sAc)KZ7c^S)4 zj|xMjs23q?T$Ot5|L6rvUYdv#-67Z1voY!Kq8-W0O( z_Mcm9$l-#pN+&i+&psxBg@H8g;pwvjT+C<4_{HH zm+DFvsFcnW)4`0`=U&{fxNFI_lgfLEvE9F^dF-$}(3Iy|VBpZ!ASb+j4b~I;$gwZ7 z>*)L{&BJtbdgjxfuT15r9RD^6@8l5E^fpVYATlJB%RZ)VEqML;1Cb+yi4k{3xz6rO ziFBt!I=Y?C(-1aaV@&8pZcLIH&0M?4^AIH|L$4$a=NG1wdT{lK1-uHN;)Fn8Vwli^6QS+ zs!KQcBJ2WQ?PtbK&C%EGzd|HwY-vJJ%~|F}bLJ3KlO3coMDy{ogpxgrUtS>_>5k`1 zUy>5)+49J!z$e++Z_!HD@T-p2Q@gH5+2$e(K;FDyn$|?l_2QI?9K%eNva8oMU=uA< zW)tnPagDkf>+!Xyg)#DiS=u^nKhn%3wu)Alku-%h829V_yDUrKpW5D3GJOKt^*J;A zx(n2Kf${c_e9|1q@+W8X1<+=};&SxEl{F+uzTyRFmJ;*ln{Hf;mM+&+H-urNhpRh^I%JZbn>4 zzQ$EB?|ZDWHSo*b<@Q`>Xwm|oif8d12_k{V&;6LZ(B)IBQ8{}YLQ^DS zN!#HY?mdo9yA)*6CB0tu!S4sJWs}%qngHI`jf&ekZ%U#`X#7}D zAtEA#UJIj<(hvLU5@X+_hDVd}yU#1`W)D>ad>Ww>yN}{8C2f_uaUlOo*U-4{@1dt~ zs3_%wyjvoaNx8RVAXoZg~=7=KeU2INAQv@vu z1})t*G2Ah7Iz_QK_;zMki%fjgW~TCNvoyvCUB=_idHpfPhbVIwOSRgys7b1?@)F1- z+a}$PGFBAr#Xx356OS*}fZ>>hjUG=}uT=b!n;`#iXSkPi( z(T+doWoBtv;6kQY5L>tSejmJna!mTZ@N+i@mpo~N*wqx*tpqmxDb_=kuuq67UOO_9 zLC=q@FRPrG=+lrZYDZV2WmccI?ZQp|spGG6d+zW+!!0!B9rxZ3q2mf0?!SC7+YGsF z<`-8#pwhF>Mo6ZQIpjY$SmOT5xR8PVqVz-v1GPjG9z1ek*9C)5f8^HV1 z!+fl|uKGH6|Bxp8-Rw|XNp$2exiZ+94KUeEu$&2gCz|xLIuiD;~ zDP~bb!an|UUgLCvA4^?#YRHQXaMy#SjGk6nMVz|cCE<}eJk$hG{ zacyi{wckyx3S;T|^`E+>qJYPo8CP$7ey?}G6o1PEIIn=q$}BX;1h<9MK|1*b>SB z@UattoA&h@3ioQ8Yia9u_jHSO_Vmx0&&kf z*arxw_h7G`gTQA_J~B!bGD^j_gYxAPQUdjoKkf5Ms2CLpiv0zuzW4fa#N{25BdK(? z&7GlTIVZ)v@e_7pk zwz+RgTqIi8U1X+G;th?@S#sXKTxw=Oznzw}x@8|wLA;D4T7wN1X!e@@d>i&~{_tGiSN_2>QPWT}9ky(sBPr{abET`;Z(h&e9d zA$F&qc&GyEx8-!6*nJqzYs{As6ckb_g z0=8RYO5o|&J~~BvvfOqdQ+^HX5nln;8U!u=KZ#Qgmoxg4IIymM9eoMm>Uj~7UeV4T z{VH4%k$_oF{i*W-`9>MyLLUffl*45_P|^rxe}?t<@pF|l()}~IeT>+Lk0pJVizKVjqu;6GJ=8wcChHWb&4uI_DOE^>9Yd9DSVvTu-IAW|gaavXy zfVYJPM<#knCn7hpB^Lw?e^p6mj^q*0Z<}qoFy4<=72WV+Vmmhytu!)Y*tlM%&0!T#nrESsGcaL4fDxye{O+!BWykx&9%7$zQ~ix6vej>zyI;0Ocf zCBD``AZ%Q}pUMaqdqBTU@ahTa1U)&3lZPJPV80na$EqIJ@#*U7ciqX$S<=zVohWlp zCO_=>{`ewxwkh@)rGHO8IqIj^fq}M5xG>;$&PjRL!6obmMnvLw0;aq909!{&z`C6V zM>bJA&Gj0qxQG2wxJX21aK@3foH&85PCU7;NFSbzB}ZZHm5InqZaDI~KLyaxLk@6v zaN_O~K&1l;{^@}o;{>EU*nkHeGG+u=Ja@S0eAZG2ArO(WxZH~acndSLwd6%yS}w7azmothaEcS~qC`?k)l@(FFys-67~u0HSvoe;eC` zct1(O)}`%?*t(R+csUX%?UKdqRlKU4R~QKhM12YbxqJ~?7?E7@F`K%h2kx)M7elCVU)gB`uf;4AF$2@@wx;to{e<`BMe} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a8201e2..724dc93 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon May 09 20:53:41 BST 2016 +#Sun Aug 14 17:22:38 BST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip diff --git a/gradlew b/gradlew index 9d82f78..27309d9 100755 --- a/gradlew +++ b/gradlew @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..832fdb6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,7 +46,7 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args From ee248b5802f42a294a17f3ea747e4ac76c5c53e1 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 14 Aug 2016 17:40:35 +0100 Subject: [PATCH 05/58] Throw exceptions and use the correct mappings context for the Enigma reader --- .../nocturne/mapping/io/reader/EnigmaReader.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index d4f6619..177d66d 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -56,21 +56,21 @@ public MappingContext read() { switch (arr[0]) { case "CLASS": { if (arr.length < 2 || arr.length > 3) { - System.err.println("Cannot parse file: malformed class mapping on line " + lineNum); - System.exit(1); + throw new IllegalArgumentException("Cannot parse file: malformed class mapping on line " + + lineNum); } String obf = arr[1].replace("none/", ""); String deobf = arr.length == 3 ? arr[2] : obf; //TODO: handle inner classes - MappingsHelper.genClassMapping(Main.getMappingContext(), obf, deobf, false); + MappingsHelper.genClassMapping(mappings, obf, deobf, false); currentClass = obf; break; } case "FIELD": { if (arr.length != 4) { - System.err.println("Cannot parse file: malformed field mapping on line " + lineNum); - System.exit(1); + throw new IllegalArgumentException("Cannot parse file: malformed field mapping on line " + + lineNum); } if (currentClass == null) { @@ -81,7 +81,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String type = arr[3]; - MappingsHelper.genFieldMapping(Main.getMappingContext(), currentClass, obf, deobf); // TODO: type + MappingsHelper.genFieldMapping(mappings, currentClass, obf, deobf); // TODO: type break; } case "METHOD": { @@ -102,7 +102,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String sig = arr[3]; - MappingsHelper.genMethodMapping(Main.getMappingContext(), currentClass, obf, deobf, sig); + MappingsHelper.genMethodMapping(mappings, currentClass, obf, deobf, sig); break; } case "ARG": { From 2873c3976258c30bf459faccc3e979d1bdf44c1f Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 14 Aug 2016 20:51:19 +0100 Subject: [PATCH 06/58] Add types to Enigma field mappings --- .../mapping/io/reader/EnigmaReader.java | 19 ++++++++++++++----- .../nocturne/mapping/model/FieldMapping.java | 2 +- .../nocturne/util/helper/MappingsHelper.java | 7 ++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 177d66d..47bcf40 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -26,6 +26,7 @@ package blue.lapis.nocturne.mapping.io.reader; import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.util.helper.MappingsHelper; @@ -37,6 +38,11 @@ */ public class EnigmaReader extends MappingsReader { + private static final String CLASS_MAPPING_KEY = "CLASS"; + private static final String FIELD_MAPPING_KEY = "FIELD"; + private static final String METHOD_MAPPING_KEY = "METHOD"; + private static final String ARG_MAPPING_KEY = "ARG"; + public EnigmaReader(BufferedReader reader) { super(reader); } @@ -47,14 +53,17 @@ public MappingContext read() { String currentClass = null; int lineNum = 0; + for (String line : reader.lines().collect(Collectors.toList())) { lineNum++; String[] arr = line.trim().split(" "); + if (arr.length == 0) { continue; } + switch (arr[0]) { - case "CLASS": { + case CLASS_MAPPING_KEY: { if (arr.length < 2 || arr.length > 3) { throw new IllegalArgumentException("Cannot parse file: malformed class mapping on line " + lineNum); @@ -67,7 +76,7 @@ public MappingContext read() { currentClass = obf; break; } - case "FIELD": { + case FIELD_MAPPING_KEY: { if (arr.length != 4) { throw new IllegalArgumentException("Cannot parse file: malformed field mapping on line " + lineNum); @@ -81,10 +90,10 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String type = arr[3]; - MappingsHelper.genFieldMapping(mappings, currentClass, obf, deobf); // TODO: type + MappingsHelper.genFieldMapping(mappings, currentClass, obf, deobf, Type.fromString(type)); break; } - case "METHOD": { + case METHOD_MAPPING_KEY: { if (arr.length == 3) { continue; } @@ -105,7 +114,7 @@ public MappingContext read() { MappingsHelper.genMethodMapping(mappings, currentClass, obf, deobf, sig); break; } - case "ARG": { + case ARG_MAPPING_KEY: { break; } default: { diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 6f37638..b82f519 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -89,7 +89,7 @@ protected SelectableMember.MemberKey getMemberKey() { private String getQualifiedName() { return (getParent() instanceof InnerClassMapping - ? ((InnerClassMapping) getParent()).getFullObfuscatedName() + ? getParent().getFullObfuscatedName() : getParent().getObfuscatedName()) + CLASS_PATH_SEPARATOR_CHAR + getObfuscatedName(); } diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 5529631..403fddc 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -30,6 +30,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; @@ -82,6 +83,10 @@ public static void genClassMapping(MappingContext context, String obf, String de } public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf) { + genFieldMapping(context, owningClass, obf, deobf, null); + } + + public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, Type type) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for field in non-existent class \"" + owningClass + "\" - ignoring"); @@ -95,7 +100,7 @@ public static void genFieldMapping(MappingContext context, String owningClass, S if (parent.getFieldMappings().containsKey(obf)) { parent.getFieldMappings().get(obf).setDeobfuscatedName(deobf); } else { - new FieldMapping(parent, obf, deobf, null); + new FieldMapping(parent, obf, deobf, type); } } From 623e11f0ba5d26630572fae55c351c19d0aee9d4 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 14 Aug 2016 21:03:46 +0100 Subject: [PATCH 07/58] Support Enigma comments --- .../lapis/nocturne/mapping/io/reader/EnigmaReader.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 47bcf40..aa4eca0 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -56,8 +56,16 @@ public MappingContext read() { for (String line : reader.lines().collect(Collectors.toList())) { lineNum++; - String[] arr = line.trim().split(" "); + // Remove comments + final int commentPos = line.indexOf('#'); + if (commentPos >= 0) { + line = line.substring(0, commentPos); + } + + final String[] arr = line.trim().split(" "); + + // Skip empty lines if (arr.length == 0) { continue; } From 34dc4f2cbf62e1a07cb5e3b2cb07bfbbd75239da Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 14 Aug 2016 21:27:51 +0100 Subject: [PATCH 08/58] Support inner classes for Enigma --- .../mapping/io/reader/EnigmaReader.java | 31 +++++++++++++++---- .../nocturne/util/helper/MappingsHelper.java | 22 ++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index aa4eca0..6b01ec2 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -28,6 +28,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -51,7 +52,7 @@ public EnigmaReader(BufferedReader reader) { public MappingContext read() { MappingContext mappings = new MappingContext(); - String currentClass = null; + ClassMapping currentClass = null; int lineNum = 0; for (String line : reader.lines().collect(Collectors.toList())) { @@ -70,6 +71,16 @@ public MappingContext read() { continue; } + // The indentation level of the line + int indentLevel = 0; + for (int i = 0; i < line.length(); i++) { + // Check if the char is a tab + if (line.charAt(i) != '\t') { + break; + } + indentLevel++; + } + switch (arr[0]) { case CLASS_MAPPING_KEY: { if (arr.length < 2 || arr.length > 3) { @@ -79,9 +90,17 @@ public MappingContext read() { String obf = arr[1].replace("none/", ""); String deobf = arr.length == 3 ? arr[2] : obf; - //TODO: handle inner classes - MappingsHelper.genClassMapping(mappings, obf, deobf, false); - currentClass = obf; + + if (indentLevel != 0) { + if (currentClass == null) { + throw new IllegalArgumentException("Cannot parse file: found field mapping before initial " + + "class mapping on line " + lineNum); + } + obf = currentClass.getFullObfuscatedName() + "/" + obf; + deobf = currentClass.getFullDeobfuscatedName() + "/" + deobf; + } + + currentClass = MappingsHelper.genClassMapping(mappings, obf, deobf, false); break; } case FIELD_MAPPING_KEY: { @@ -98,7 +117,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String type = arr[3]; - MappingsHelper.genFieldMapping(mappings, currentClass, obf, deobf, Type.fromString(type)); + MappingsHelper.genFieldMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, Type.fromString(type)); break; } case METHOD_MAPPING_KEY: { @@ -119,7 +138,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String sig = arr[3]; - MappingsHelper.genMethodMapping(mappings, currentClass, obf, deobf, sig); + MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, sig); break; } case ARG_MAPPING_KEY: { diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 403fddc..8bf7043 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -45,13 +45,13 @@ */ public final class MappingsHelper { - public static void genClassMapping(MappingContext context, String obf, String deobf, boolean updateClassViews) { + public static ClassMapping genClassMapping(MappingContext context, String obf, String deobf, boolean updateClassViews) { if (!Main.getLoadedJar().getClass(obf).isPresent()) { Main.getLogger().warning("Discovered mapping for non-existent class \"" + obf + "\" - ignoring"); - return; + return null; } else if (!StringHelper.isJavaClassIdentifier(obf) || !StringHelper.isJavaClassIdentifier(deobf)) { Main.getLogger().warning("Discovered class mapping with illegal name - ignoring"); - return; + return null; } if (obf.contains(INNER_CLASS_SEPARATOR_CHAR + "")) { @@ -59,7 +59,7 @@ public static void genClassMapping(MappingContext context, String obf, String de String[] deobfSplit = INNER_CLASS_SEPARATOR_PATTERN.split(deobf); if (obfSplit.length != deobfSplit.length) { // non-inner mapped to inner or vice versa Main.getLogger().warning("Unsupported mapping: " + obf + " <-> " + deobf); - return; // ignore it + return null; // ignore it } // get the direct parent class to this inner class @@ -69,15 +69,21 @@ public static void genClassMapping(MappingContext context, String obf, String de String baseObfName = obfSplit[obfSplit.length - 1]; String baseDeobfname = deobfSplit[deobfSplit.length - 1]; if (parent.getInnerClassMappings().containsKey(baseObfName)) { - parent.getInnerClassMappings().get(baseObfName).setDeobfuscatedName(baseDeobfname); + InnerClassMapping mapping = parent.getInnerClassMappings().get(baseObfName); + mapping.setDeobfuscatedName(baseDeobfname); + return mapping; } else { - new InnerClassMapping(parent, baseObfName, baseDeobfname); + return new InnerClassMapping(parent, baseObfName, baseDeobfname); } } else { if (context.getMappings().containsKey(obf)) { - context.getMappings().get(obf).setDeobfuscatedName(deobf); + TopLevelClassMapping mapping = context.getMappings().get(obf); + mapping.setDeobfuscatedName(deobf); + return mapping; } else { - context.addMapping(new TopLevelClassMapping(context, obf, deobf), updateClassViews); + TopLevelClassMapping mapping = new TopLevelClassMapping(context, obf, deobf); + context.addMapping(mapping, updateClassViews); + return mapping; } } } From dfdbfa011df87fedbe9562435f11d76fb629cf0f Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 00:33:07 +0100 Subject: [PATCH 09/58] Add a writer for Enigma (still WIP) --- src/main/java/blue/lapis/nocturne/Main.java | 10 ++ .../io/mappings/MappingsSaveDialogHelper.java | 21 ++-- .../mapping/io/writer/EnigmaWriter.java | 101 ++++++++++++++++++ .../mapping/io/writer/MappingWriterType.java | 79 ++++++++++++++ .../mapping/io/writer/MappingsWriter.java | 27 ----- .../nocturne/mapping/io/writer/SrgWriter.java | 21 +++- 6 files changed, 219 insertions(+), 40 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java create mode 100644 src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java diff --git a/src/main/java/blue/lapis/nocturne/Main.java b/src/main/java/blue/lapis/nocturne/Main.java index 7ff3857..8f016d4 100644 --- a/src/main/java/blue/lapis/nocturne/Main.java +++ b/src/main/java/blue/lapis/nocturne/Main.java @@ -29,6 +29,7 @@ import blue.lapis.nocturne.gui.scene.control.WebLink; import blue.lapis.nocturne.jar.model.ClassSet; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; import blue.lapis.nocturne.util.helper.PropertiesHelper; import blue.lapis.nocturne.util.helper.SceneHelper; @@ -86,6 +87,7 @@ public class Main extends Application { private final MappingContext mappingContext = new MappingContext(); private Path currentMappingsPath; + private MappingWriterType currentWriterType; private ClassSet loadedJar; static { @@ -248,6 +250,14 @@ public static void setCurrentMappingsPath(Path path) { getInstance().currentMappingsPath = path; } + public static MappingWriterType getCurrentWriterType() { + return getInstance().currentWriterType; + } + + public static void setCurrentWriterType(MappingWriterType currentWriterType) { + getInstance().currentWriterType = currentWriterType; + } + public static ClassSet getLoadedJar() { return getInstance().loadedJar; } diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java index 0218f86..ddc9f83 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java @@ -26,9 +26,9 @@ package blue.lapis.nocturne.gui.io.mappings; import blue.lapis.nocturne.Main; -import blue.lapis.nocturne.mapping.io.writer.SrgWriter; +import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; +import blue.lapis.nocturne.mapping.io.writer.MappingsWriter; import blue.lapis.nocturne.util.helper.PropertiesHelper; - import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; @@ -38,6 +38,7 @@ import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; /** * Static utility class for dialogs for saving mappings. @@ -53,16 +54,14 @@ public static void saveMappings() throws IOException { return; } - saveMappings0(); + saveMappings0(Main.getCurrentWriterType()); } public static boolean saveMappingsAs() throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(Main.getResourceBundle().getString("filechooser.save_mapping")); - fileChooser.getExtensionFilters().addAll( - new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_srg"), "*.srg"), - new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_all"), "*.*") - ); + Arrays.asList(MappingWriterType.values()) + .forEach(t -> fileChooser.getExtensionFilters().add(t.getExtensionFilter())); String lastDir = Main.getPropertiesHelper().getProperty(PropertiesHelper.Key.LAST_MAPPINGS_DIRECTORY); if (!lastDir.isEmpty()) { @@ -88,15 +87,17 @@ public static boolean saveMappingsAs() throws IOException { Main.getMappingContext().setDirty(true); } + final MappingWriterType writerType = MappingWriterType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); Main.setCurrentMappingsPath(selectedFile.toPath()); + Main.setCurrentWriterType(writerType); - saveMappings0(); + saveMappings0(writerType); return true; } - private static void saveMappings0() throws IOException { + private static void saveMappings0(MappingWriterType writerType) throws IOException { if (Main.getMappingContext().isDirty()) { - try (SrgWriter writer = new SrgWriter(new PrintWriter(Main.getCurrentMappingsPath().toFile()))) { + try (MappingsWriter writer = writerType.constructWriter(new PrintWriter(Main.getCurrentMappingsPath().toFile()))) { writer.write(Main.getMappingContext()); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java new file mode 100644 index 0000000..4b46496 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -0,0 +1,101 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.io.writer; + +import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.FieldMapping; +import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; + +import java.io.PrintWriter; + +/** + * The mappings writer, for the Enigma format. + */ +public class EnigmaWriter extends MappingsWriter { + + /** + * Constructs a new {@link EnigmaWriter} which outputs to the given + * {@link PrintWriter}. + * + * @param outputWriter The {@link PrintWriter} to output to + */ + public EnigmaWriter(PrintWriter outputWriter) { + super(outputWriter); + } + + @Override + public void write(MappingContext mappings) { + for (TopLevelClassMapping classMapping : mappings.getMappings().values()) { + this.writeClassMapping(classMapping, 0); + } + } + + protected void writeClassMapping(ClassMapping classMapping, int depth) { + if (classMapping.getDeobfuscatedName().equals(classMapping.getObfuscatedName())) { + out.println(getIndentForDepth(depth) + "CLASS " + classMapping.getObfuscatedName()); + } else { + out.println(getIndentForDepth(depth) + "CLASS " + classMapping.getObfuscatedName() + " " + classMapping.getDeobfuscatedName()); + } + + for (ClassMapping innerClass : classMapping.getInnerClassMappings().values()) { + this.writeClassMapping(innerClass, depth + 1); + } + + for (FieldMapping fieldMapping : classMapping.getFieldMappings().values()) { + this.writeFieldMapping(fieldMapping, depth + 1); + } + + for (MethodMapping methodMapping : classMapping.getMethodMappings().values()) { + this.writeMethodMapping(methodMapping, depth + 1); + } + } + + protected void writeFieldMapping(FieldMapping fieldMapping, int depth) { + out.println(getIndentForDepth(depth) + "FIELD " + fieldMapping.getObfuscatedName() + " " + fieldMapping.getDeobfuscatedName() + " " + + fieldMapping.getType().toString()); + } + + protected void writeMethodMapping(MethodMapping methodMapping, int depth) { + if (methodMapping.getDeobfuscatedName().equals(methodMapping.getObfuscatedName())) { + out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " + + methodMapping.getObfuscatedDescriptor().toString()); + } else { + out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " + methodMapping.getDeobfuscatedName() + " " + + methodMapping.getObfuscatedDescriptor().toString()); + } + // TODO: Support argument mappings + } + + private String getIndentForDepth(int depth) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < depth; i++) { + builder.append("\t"); + } + return builder.toString(); + } +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java new file mode 100644 index 0000000..eb8e747 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java @@ -0,0 +1,79 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.io.writer; + +import blue.lapis.nocturne.Main; +import com.google.common.collect.Maps; +import javafx.stage.FileChooser; + +import java.io.PrintWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Map; + +public enum MappingWriterType { + + SRG(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_srg"), "*.srg"), + SrgWriter.class), + ENIGMA(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_enigma"), "*.*"), + EnigmaWriter.class); + + private static final Map filterToType = Maps.newHashMap(); + + static { + Arrays.asList(values()).forEach(t -> filterToType.put(t.getExtensionFilter(), t)); + } + + private final FileChooser.ExtensionFilter extensionFilter; + private final Constructor writerCtor; + + MappingWriterType(FileChooser.ExtensionFilter extensionFilter, Class readerClass) { + this.extensionFilter = extensionFilter; + try { + this.writerCtor = readerClass.getConstructor(PrintWriter.class); + } catch (NoSuchMethodException ex) { + throw new RuntimeException("Failed to initialize reader type for class " + readerClass.getName(), ex); + } + } + + public FileChooser.ExtensionFilter getExtensionFilter() { + return this.extensionFilter; + } + + public MappingsWriter constructWriter(PrintWriter writer) { + try { + return writerCtor.newInstance(writer); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException ex) { + throw new RuntimeException("Failed to construct writer with class " + + writerCtor.getDeclaringClass().getName(), ex); + } + } + + public static MappingWriterType fromExtensionFilter(FileChooser.ExtensionFilter filter) { + return filterToType.get(filter); + } +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java index 1a8d317..6971421 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java @@ -26,9 +26,6 @@ package blue.lapis.nocturne.mapping.io.writer; import blue.lapis.nocturne.mapping.MappingContext; -import blue.lapis.nocturne.mapping.model.ClassMapping; -import blue.lapis.nocturne.mapping.model.FieldMapping; -import blue.lapis.nocturne.mapping.model.MethodMapping; import java.io.Closeable; import java.io.IOException; @@ -59,30 +56,6 @@ protected MappingsWriter(PrintWriter outputWriter) { */ public abstract void write(MappingContext mappings); - /** - * Writes the given {@link ClassMapping} to the {@link MappingsWriter}'s - * {@link PrintWriter}. - * - * @param classMapping The {@link ClassMapping} to write - */ - protected abstract void writeClassMapping(ClassMapping classMapping); - - /** - * Writes the given {@link FieldMapping} to the {@link MappingsWriter}'s - * {@link PrintWriter}. - * - * @param fieldMapping The {@link FieldMapping} to write - */ - protected abstract void writeFieldMapping(FieldMapping fieldMapping); - - /** - * Writes the given {@link MethodMapping} to the {@link MappingsWriter}'s - * {@link PrintWriter}. - * - * @param mapping The {@link MethodMapping} to write - */ - protected abstract void writeMethodMapping(MethodMapping mapping); - @Override public void close() throws IOException { out.close(); diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java index 4892a21..4402b60 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java @@ -81,7 +81,12 @@ public void write(MappingContext mappingContext) { } } - @Override + /** + * Writes the given {@link ClassMapping} to the {@link SrgWriter}'s + * {@link PrintWriter}. + * + * @param classMapping The {@link ClassMapping} to write + */ protected void writeClassMapping(ClassMapping classMapping) { if (!classMapping.getObfuscatedName().equals(classMapping.getDeobfuscatedName())) { clWriter.format("CL: %s %s\n", @@ -93,14 +98,24 @@ protected void writeClassMapping(ClassMapping classMapping) { classMapping.getMethodMappings().values().stream().filter(NOT_USELESS).forEach(this::writeMethodMapping); } - @Override + /** + * Writes the given {@link FieldMapping} to the {@link SrgWriter}'s + * {@link PrintWriter}. + * + * @param fieldMapping The {@link FieldMapping} to write + */ protected void writeFieldMapping(FieldMapping fieldMapping) { fdWriter.format("FD: %s/%s %s/%s\n", fieldMapping.getParent().getFullObfuscatedName(), fieldMapping.getObfuscatedName(), fieldMapping.getParent().getFullDeobfuscatedName(), fieldMapping.getDeobfuscatedName()); } - @Override + /** + * Writes the given {@link MethodMapping} to the {@link SrgWriter}'s + * {@link PrintWriter}. + * + * @param mapping The {@link MethodMapping} to write + */ protected void writeMethodMapping(MethodMapping mapping) { mdWriter.format("MD: %s/%s %s %s/%s %s\n", mapping.getParent().getFullObfuscatedName(), mapping.getObfuscatedName(), From 4721f4b251459bc6ed5c745e52f01803ad964f39 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 01:10:01 +0100 Subject: [PATCH 10/58] Remove Enigma warning dialog --- .../gui/io/mappings/MappingsOpenDialogHelper.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index 0ed9f7d..b242958 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -31,9 +31,6 @@ import blue.lapis.nocturne.mapping.io.reader.MappingReaderType; import blue.lapis.nocturne.mapping.io.reader.MappingsReader; import blue.lapis.nocturne.util.helper.PropertiesHelper; - -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; import java.io.BufferedReader; @@ -77,17 +74,6 @@ public static void openMappings() throws IOException { if (Files.exists(selectedPath)) { //TODO: isn't this redundant? MappingReaderType type = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { - if (type == MappingReaderType.ENIGMA) { - Alert confirmEngima = new Alert(Alert.AlertType.CONFIRMATION, - Main.getResourceBundle().getString("enigma.support_notice"), - ButtonType.YES, ButtonType.NO); - confirmEngima.showAndWait(); - - if (confirmEngima.getResult() == ButtonType.NO) { - return; - } - } - MappingContext context = reader.read(); Main.getMappingContext().assimilate(context); MainController.INSTANCE.updateClassViews(); From c6e884d88beecee0fc562166e87d61f1a1159484 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 11:48:59 +0100 Subject: [PATCH 11/58] Add support for argument mappings (WIP) --- .../nocturne/gui/scene/control/CodeTab.java | 6 +- .../mapping/model/ArgumentMapping.java | 90 +++++++++++++++++++ .../nocturne/mapping/model/MethodMapping.java | 26 ++++++ .../blue/lapis/nocturne/util/MemberType.java | 3 +- src/main/resources/lang/de_DE.properties | 1 + src/main/resources/lang/en_US.properties | 1 + 6 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java b/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java index 7e6188d..4f290b7 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java @@ -161,7 +161,9 @@ public void setCode(String code) { public enum SelectableMemberType { FIELD("codetab.identifier.field", "codetab.identifier.type"), METHOD("codetab.identifier.method", "codetab.identifier.descriptor"), - CLASS("codetab.identifier.class"); + ARG("codetab.identifier.arg", "codetab.identifier.type"), + CLASS("codetab.identifier.class"), + ; private final String identifierLabel; private final String infoLabel; @@ -216,6 +218,8 @@ public static SelectableMemberType fromMemberType(MemberType type) { return SelectableMemberType.FIELD; case METHOD: return SelectableMemberType.METHOD; + case ARG: + return SelectableMemberType.ARG; default: throw new AssertionError(); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java new file mode 100644 index 0000000..b00d2e6 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java @@ -0,0 +1,90 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.model; + +import blue.lapis.nocturne.gui.scene.text.SelectableMember; +import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.util.MemberType; + +/** + * Represents a {@link Mapping} for arguments. + */ +public class ArgumentMapping extends Mapping { + + private final SelectableMember.MemberKey memberKey; + private final MethodMapping parent; + + /** + * Constructs a new {@link ArgumentMapping} with the given parameters. + * + * @param parent The parent method mapping + * @param obfName The obfuscated name of the mapped argument + * @param deobfName The deobfuscated name of the mapped argument + * @param propagate Whether to propagate this mapping to super- and + * sub-classes + */ + public ArgumentMapping(MethodMapping parent, String obfName, String deobfName, boolean propagate) { + super(obfName, deobfName); + this.memberKey = new SelectableMember.MemberKey(MemberType.ARG, "", ""); // TODO: Use actual values + this.parent = parent; + + this.parent.addArgumentMapping(this, propagate); + } + + public void initialize(boolean propagate) { + this.setDeobfuscatedName(getDeobfuscatedName(), propagate); + } + + /** + * Gets the parent method mapping of this argument mapping. + * + * @return The parent mapping + */ + public MethodMapping getParent() { + return this.parent; + } + + @Override + public MappingContext getContext() { + return this.getParent().getContext(); + } + + @Override + protected SelectableMember.MemberKey getMemberKey() { + return this.memberKey; + } + + @Override + public void setDeobfuscatedName(String name) { + setDeobfuscatedName(name, true); + } + + public void setDeobfuscatedName(String deobf, boolean propagate) { + super.setDeobfuscatedName(deobf); + + // TODO: propagate + } +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index c6c8616..b01b3ee 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -35,12 +35,17 @@ import blue.lapis.nocturne.util.MemberType; import blue.lapis.nocturne.util.helper.HierarchyHelper; import blue.lapis.nocturne.util.helper.MappingsHelper; +import com.google.common.collect.ImmutableMap; + +import java.util.HashMap; +import java.util.Map; /** * Represents a {@link Mapping} for a method. */ public class MethodMapping extends MemberMapping { + private final Map argumentMappings = new HashMap<>(); private final SelectableMember.MemberKey memberKey; private final MethodDescriptor descriptor; private final IndexedMethod.Signature sig; @@ -83,6 +88,27 @@ public void initialize(boolean propagate) { this.setDeobfuscatedName(getDeobfuscatedName(), propagate); } + /** + * Gets a clone of the {@link ArgumentMapping}s. + * + * @return A clone of the {@link ArgumentMapping}s + */ + public ImmutableMap getArgumentMappings() { + return ImmutableMap.copyOf(this.argumentMappings); + } + + /** + * Adds the given {@link ArgumentMapping} to this {@link ClassMapping}. + * + * @param mapping The {@link ArgumentMapping} to add + * @param propagate Whether to propagate this mapping to super- and + * sub-classes + */ + void addArgumentMapping(ArgumentMapping mapping, boolean propagate) { + mapping.initialize(propagate); + argumentMappings.put(mapping.getObfuscatedName(), mapping); + } + /** * Returns the {@link MethodDescriptor} of this method. * diff --git a/src/main/java/blue/lapis/nocturne/util/MemberType.java b/src/main/java/blue/lapis/nocturne/util/MemberType.java index 7146497..ea48233 100644 --- a/src/main/java/blue/lapis/nocturne/util/MemberType.java +++ b/src/main/java/blue/lapis/nocturne/util/MemberType.java @@ -36,7 +36,8 @@ public enum MemberType { CLASS, FIELD, - METHOD; + METHOD, + ARG; private static HashMap index; diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 2845f22..7e9aa39 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -24,6 +24,7 @@ codetab.identifier.type=Typ codetab.identifier.method=Methode codetab.identifier.descriptor=Deskriptor codetab.identifier.class=Klasse +codetab.identifier.arg=Argument member.contextmenu.rename=Umbenennen member.contextmenu.reset=Zur\u00fccksetzen diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 688822e..560cd6d 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -23,6 +23,7 @@ codetab.identifier.type=Type codetab.identifier.method=Method codetab.identifier.descriptor=Descriptor codetab.identifier.class=Class +codetab.identifier.arg=Argument member.contextmenu.rename=Rename member.contextmenu.reset=Reset From 5ceee313940b47787113695349958276cc5a84eb Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 16:31:42 +0100 Subject: [PATCH 12/58] Preliminary support for writing arguments for Enigma --- .../nocturne/mapping/io/writer/EnigmaWriter.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index 4b46496..0920600 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -26,6 +26,7 @@ package blue.lapis.nocturne.mapping.io.writer; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; @@ -88,7 +89,15 @@ protected void writeMethodMapping(MethodMapping methodMapping, int depth) { out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " + methodMapping.getDeobfuscatedName() + " " + methodMapping.getObfuscatedDescriptor().toString()); } - // TODO: Support argument mappings + + for (ArgumentMapping argumentMapping : methodMapping.getArgumentMappings().values()) { + writeArgumentMapping(argumentMapping, depth + 1); + } + } + + protected void writeArgumentMapping(ArgumentMapping argumentMapping, int depth) { + // TODO: get the actual index + out.println(getIndentForDepth(depth) + "ARG 0 " + argumentMapping.getDeobfuscatedName()); } private String getIndentForDepth(int depth) { From 072a13ad2d9d7b343930f3d9d806d813cbd284c7 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 16:39:24 +0100 Subject: [PATCH 13/58] Add index to ArgumentMapping --- .../nocturne/mapping/model/ArgumentMapping.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java index b00d2e6..cf2a2aa 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java @@ -36,20 +36,23 @@ public class ArgumentMapping extends Mapping { private final SelectableMember.MemberKey memberKey; private final MethodMapping parent; + private final int index; /** * Constructs a new {@link ArgumentMapping} with the given parameters. * * @param parent The parent method mapping + * @param index The index of the argument * @param obfName The obfuscated name of the mapped argument * @param deobfName The deobfuscated name of the mapped argument * @param propagate Whether to propagate this mapping to super- and * sub-classes */ - public ArgumentMapping(MethodMapping parent, String obfName, String deobfName, boolean propagate) { + public ArgumentMapping(MethodMapping parent, int index, String obfName, String deobfName, boolean propagate) { super(obfName, deobfName); this.memberKey = new SelectableMember.MemberKey(MemberType.ARG, "", ""); // TODO: Use actual values this.parent = parent; + this.index = index; this.parent.addArgumentMapping(this, propagate); } @@ -58,6 +61,15 @@ public void initialize(boolean propagate) { this.setDeobfuscatedName(getDeobfuscatedName(), propagate); } + /** + * Gets the index of the mapped argument. + * + * @return The index + */ + public int getIndex() { + return index; + } + /** * Gets the parent method mapping of this argument mapping. * From 59d7080f9fba6e2221304fa1744de156a107ad17 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Mon, 15 Aug 2016 17:01:44 +0100 Subject: [PATCH 14/58] Read Enigma arguement mappings --- .../mapping/io/reader/EnigmaReader.java | 22 ++++++++++++++- .../nocturne/util/helper/MappingsHelper.java | 28 +++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 6b01ec2..1d64cad 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -29,6 +29,7 @@ import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -53,6 +54,7 @@ public MappingContext read() { MappingContext mappings = new MappingContext(); ClassMapping currentClass = null; + MethodMapping currentMethod = null; int lineNum = 0; for (String line : reader.lines().collect(Collectors.toList())) { @@ -101,6 +103,7 @@ public MappingContext read() { } currentClass = MappingsHelper.genClassMapping(mappings, obf, deobf, false); + currentMethod = null; break; } case FIELD_MAPPING_KEY: { @@ -117,7 +120,9 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String type = arr[3]; + MappingsHelper.genFieldMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, Type.fromString(type)); + currentMethod = null; break; } case METHOD_MAPPING_KEY: { @@ -138,10 +143,25 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String sig = arr[3]; - MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, sig); + + currentMethod = MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, sig); break; } case ARG_MAPPING_KEY: { + if (arr.length != 3) { + throw new IllegalArgumentException("Cannot parse file: malformed argument mapping on line " + + lineNum); + } + + if (currentMethod == null) { + throw new IllegalArgumentException("Cannot parse file: found argument mapping before initial " + + "method mapping on line " + lineNum); + } + + int index = Integer.parseInt(arr[1]); + String deobf = arr[2]; + + MappingsHelper.genArgumentMapping(mappings, currentMethod, index, deobf); break; } default: { diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 8bf7043..1a36b8d 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -32,6 +32,7 @@ import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.InnerClassMapping; @@ -110,22 +111,39 @@ public static void genFieldMapping(MappingContext context, String owningClass, S } } - public static void genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, + public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, String descriptor) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for method in non-existent class \"" + owningClass + "\" - ignoring"); - return; + return null; } else if (!StringHelper.isJavaIdentifier(obf) || !StringHelper.isJavaIdentifier(deobf)) { Main.getLogger().warning("Discovered method mapping with illegal name - ignoring"); - return; + return null; } ClassMapping parent = getOrCreateClassMapping(context, owningClass); if (parent.getMethodMappings().containsKey(obf)) { - parent.getMethodMappings().get(obf).setDeobfuscatedName(deobf); + final MethodMapping methodMapping = parent.getMethodMappings().get(obf); + methodMapping.setDeobfuscatedName(deobf); + return methodMapping; + } else { + return new MethodMapping(parent, obf, deobf, MethodDescriptor.fromString(descriptor)); + } + } + + public static void genArgumentMapping(MappingContext context, MethodMapping methodMapping, int index, String deobf) { + if (!StringHelper.isJavaIdentifier(deobf)) { + Main.getLogger().warning("Discovered argument mapping with illegal name - ignoring"); + return; + } + + Optional mapping = methodMapping.getArgumentMappings().values().stream().filter( + argumentMapping -> argumentMapping.getIndex() == index).findFirst(); + if (mapping.isPresent()) { + mapping.get().setDeobfuscatedName(deobf); } else { - new MethodMapping(parent, obf, deobf, MethodDescriptor.fromString(descriptor)); + new ArgumentMapping(methodMapping, index, deobf, deobf, true); } } From 400da22211fa0579874ee1125782e5c9d1eb5fd4 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 15 Aug 2016 17:50:21 -0400 Subject: [PATCH 15/58] Work towards proper field signature handling --- .../gui/scene/text/SelectableMember.java | 9 +- .../nocturne/jar/model/JarClassEntry.java | 25 ++-- .../nocturne/mapping/model/FieldMapping.java | 7 +- .../nocturne/mapping/model/MethodMapping.java | 2 +- .../processor/index/ClassIndexer.java | 19 ++- .../processor/index/model/IndexedClass.java | 10 +- .../processor/index/model/IndexedField.java | 127 ++++++++++++++++++ .../nocturne/util/helper/MappingsHelper.java | 15 ++- 8 files changed, 184 insertions(+), 30 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 4463bd4..ea02086 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -35,10 +35,12 @@ import blue.lapis.nocturne.gui.scene.control.CodeTab; import blue.lapis.nocturne.jar.model.JarClassEntry; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.Mapping; import blue.lapis.nocturne.mapping.model.MemberMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; +import blue.lapis.nocturne.processor.index.model.IndexedField; import blue.lapis.nocturne.processor.index.model.IndexedMethod; import blue.lapis.nocturne.util.MemberType; import blue.lapis.nocturne.util.helper.HierarchyHelper; @@ -79,6 +81,7 @@ public class SelectableMember extends Text { private final StringProperty descriptorProperty = new SimpleStringProperty(this, "descriptor"); private final StringProperty parentClassProperty = new SimpleStringProperty(this, "parentClass"); + private final Type fieldType; private final MethodDescriptor desc; private final IndexedMethod.Signature sig; @@ -94,6 +97,7 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de this.type = type; this.nameProperty.set(name); this.descriptorProperty.set(descriptor); + this.fieldType = type == MemberType.FIELD ? Type.fromString(descriptor) : null; this.desc = type == MemberType.METHOD ? MethodDescriptor.fromString(descriptor) : null; this.sig = type == MemberType.METHOD ? new IndexedMethod.Signature(name, desc) : null; this.parentClassProperty.set(parentClass); @@ -273,7 +277,8 @@ private boolean checkMemberDupe(String newName) { } case FIELD: { JarClassEntry jce = Main.getLoadedJar().getClass(getParentClass()).get(); - if (jce.getCurrentFieldNames().containsValue(newName)) { + IndexedField.Signature newSig = new IndexedField.Signature(newName, this.fieldType); + if (jce.getCurrentFields().containsValue(newSig)) { showDupeAlert(false); return false; } else { @@ -286,7 +291,7 @@ private boolean checkMemberDupe(String newName) { .map(c -> Main.getLoadedJar().getClass(c).get()).collect(Collectors.toSet()); for (JarClassEntry jce : hierarchy) { IndexedMethod.Signature newSig = new IndexedMethod.Signature(newName, this.desc); - if (jce.getCurrentMethodNames().containsValue(newSig)) { + if (jce.getCurrentMethods().containsValue(newSig)) { showDupeAlert(!jce.getName().equals(getName())); return false; } diff --git a/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java b/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java index a7b13a5..ca2acfd 100644 --- a/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java +++ b/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java @@ -35,6 +35,7 @@ import blue.lapis.nocturne.decompile.SimpleBytecodeProvider; import blue.lapis.nocturne.decompile.SimpleFernflowerLogger; import blue.lapis.nocturne.processor.index.ClassIndexer; +import blue.lapis.nocturne.processor.index.model.IndexedField; import blue.lapis.nocturne.processor.index.model.IndexedMethod; import blue.lapis.nocturne.processor.transform.ClassTransformer; import blue.lapis.nocturne.util.MemberType; @@ -58,6 +59,14 @@ public class JarClassEntry { private static Dialog decompileDialog; + private final String name; + private byte[] content; + private boolean deobfuscated; + + private final Map classNames = new HashMap<>(); + private final Map fields = new HashMap<>(); + private final Map methods = new HashMap<>(); + static { if (!Main.getInstance().testingEnv) { decompileDialog = new Dialog<>(); @@ -70,14 +79,6 @@ public class JarClassEntry { } } - private final String name; - private byte[] content; - private boolean deobfuscated; - - private final Map classNames = new HashMap<>(); - private final Map fieldNames = new HashMap<>(); - private final Map methodNames = new HashMap<>(); - /** * Constructs a new {@link JarClassEntry} with the given name and byte * content. @@ -193,12 +194,12 @@ public Map getCurrentInnerClassNames() { return classNames; } - public Map getCurrentFieldNames() { - return fieldNames; + public Map getCurrentFields() { + return fields; } - public Map getCurrentMethodNames() { - return methodNames; + public Map getCurrentMethods() { + return methods; } @Override diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 6f37638..ba7e87b 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -30,6 +30,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.attribute.Type; +import blue.lapis.nocturne.processor.index.model.IndexedField; import blue.lapis.nocturne.util.MemberType; /** @@ -38,7 +39,8 @@ public class FieldMapping extends MemberMapping { private final ClassMapping parent; - private final Type type; //TODO: not necessary (or possible) for SRG mappings so we won't enforce it + private final Type type; + private final IndexedField.Signature sig; /** * Constructs a new {@link FieldMapping} with the given parameters. @@ -52,6 +54,7 @@ public FieldMapping(ClassMapping parent, String obfName, String deobfName, Type super(parent, obfName, deobfName); this.parent = parent; this.type = type; + this.sig = new IndexedField.Signature(obfName, type); parent.addFieldMapping(this); } @@ -79,7 +82,7 @@ public void setDeobfuscatedName(String deobf) { super.setDeobfuscatedName(deobf); Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentFieldNames().put(getObfuscatedName(), deobf); + .getCurrentFields().put(sig, new IndexedField.Signature(getDeobfuscatedName(), type)); } @Override diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index b01b3ee..4663a79 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -160,7 +160,7 @@ public void setDeobfuscatedName(String deobf, boolean propagate) { } Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentMethodNames().put(sig, new IndexedMethod.Signature(deobf, descriptor)); + .getCurrentMethods().put(sig, new IndexedMethod.Signature(deobf, descriptor)); } } diff --git a/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java b/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java index a7c61ed..8431cc5 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java @@ -33,6 +33,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.JarClassEntry; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.processor.ClassProcessor; import blue.lapis.nocturne.processor.constantpool.ConstantPoolReader; import blue.lapis.nocturne.processor.constantpool.model.ConstantPool; @@ -41,8 +42,11 @@ import blue.lapis.nocturne.processor.constantpool.model.structure.ConstantStructure; import blue.lapis.nocturne.processor.constantpool.model.structure.Utf8Structure; import blue.lapis.nocturne.processor.index.model.IndexedClass; +import blue.lapis.nocturne.processor.index.model.IndexedField; import blue.lapis.nocturne.processor.index.model.IndexedMethod; +import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -90,7 +94,7 @@ public IndexedClass index() { } } - List fields = indexFields(buffer, pool); + List fields = indexFields(buffer, pool); List methods = indexMethods(buffer, pool); @@ -103,16 +107,17 @@ public IndexedClass index() { * * @param buffer The buffer to read from */ - private List indexFields(ByteBuffer buffer, ConstantPool pool) { - List fields = new ArrayList<>(); + private List indexFields(ByteBuffer buffer, ConstantPool pool) { + List fields = new ArrayList<>(); int fieldCount = buffer.getShort(); // read the field count for (int i = 0; i < fieldCount; i++) { buffer.position(buffer.position() + 2); // skip the access String name = getString(pool, buffer.getShort()); // get the name - fields.add(name); - jce.getCurrentFieldNames().put(name, name); // index the field name for future reference - buffer.position(buffer.position() + 2); // skip the descriptor + Type desc = Type.fromString(getString(pool, buffer.getShort())); // get the descriptor + IndexedField.Signature sig = new IndexedField.Signature(name, desc); + fields.add(sig); + jce.getCurrentFields().put(sig, sig); // index the field name for future reference skipAttributes(buffer); } @@ -137,7 +142,7 @@ private List indexMethods(ByteBuffer buffer, ConstantPool pool) { MethodDescriptor desc = MethodDescriptor.fromString(getString(pool, buffer.getShort())); IndexedMethod.Signature sig = new IndexedMethod.Signature(name, desc); methods.add(new IndexedMethod(sig, vis)); - jce.getCurrentMethodNames().put(sig, sig); // index the method sig for future reference + jce.getCurrentMethods().put(sig, sig); // index the method sig for future reference skipAttributes(buffer); } diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java index fde0643..5fbeeb6 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java @@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import java.util.HashMap; import java.util.List; @@ -47,16 +46,17 @@ public class IndexedClass extends Hierarchical { private ImmutableConstantPool constantPool; private final String superClass; private final ImmutableList interfaces; - private final ImmutableSet fields; //TODO: use full signature instead of just name + private final ImmutableMap fields; private final ImmutableMap methods; public IndexedClass(String name, ImmutableConstantPool constantPool, String superClass, List interfaces, - List fields, List methods) { + List fields, List methods) { this.name = name; this.constantPool = constantPool; this.superClass = superClass; this.interfaces = ImmutableList.copyOf(interfaces); - this.fields = ImmutableSet.copyOf(fields); + this.fields = ImmutableMap.copyOf( + fields.stream().collect(Collectors.toMap(IndexedField::getSignature, f -> f))); this.methods = ImmutableMap.copyOf( methods.stream().collect(Collectors.toMap(IndexedMethod::getSignature, m -> m)) ); @@ -78,7 +78,7 @@ public ImmutableList getInterfaces() { return interfaces; } - public ImmutableSet getFields() { + public ImmutableMap getFields() { return fields; } diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java new file mode 100644 index 0000000..25e33a5 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java @@ -0,0 +1,127 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.processor.index.model; + +import blue.lapis.nocturne.jar.model.attribute.Type; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Represents a method serialized by Nocturne's class indexer. + */ +public class IndexedField extends Hierarchical { + + private final Signature signature; + private final Visibility visibility; + + public IndexedField(Signature signature, Visibility visibility) { + this.signature = signature; + this.visibility = visibility; + } + + public Signature getSignature() { + return signature; + } + + public Visibility getVisibility() { + return visibility; + } + + /** + * Represents the unique signature of a particular field. + */ + public static class Signature { + + private final String name; + private final Type type; + + public Signature(String name, Type type) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public Type getType() { + return type; + } + + @Override + public boolean equals(Object otherObj) { + if (!(otherObj instanceof Signature)) { + return false; + } + Signature sig = (Signature) otherObj; + return sig.getName().equals(getName()) && sig.getType().equals(getType()); + } + + @Override + public int hashCode() { + return Objects.hash(name, type); + } + + } + + /** + * Represents the visibility level of a particular method. + */ + public enum Visibility { + + PACKAGE ((byte) 0b000), + PUBLIC ((byte) 0b001), + PRIVATE ((byte) 0b010), + PROTECTED((byte) 0b100); + + private static Map visMap; + + private final byte tag; + + Visibility(byte tag) { + this.tag = tag; + register(); + } + + public byte getTag() { + return tag; + } + + private void register() { + if (visMap == null) { + visMap = new HashMap<>(); + } + visMap.put(getTag(), this); + } + + public static Visibility fromAccessFlags(short flags) { + return visMap.get((byte) (flags & 0b111)); // we're only interested in the last 3 bytes + } + + } +} diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 5529631..94e42da 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -36,8 +36,11 @@ import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; +import blue.lapis.nocturne.processor.index.model.IndexedClass; +import blue.lapis.nocturne.processor.index.model.IndexedField; import java.util.Optional; +import java.util.stream.Stream; /** * Static utility class for assisting with mapping retrieval and creation. @@ -81,6 +84,7 @@ public static void genClassMapping(MappingContext context, String obf, String de } } + //TODO: modify this to accept proper field signatures public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for field in non-existent class \"" + owningClass @@ -95,7 +99,16 @@ public static void genFieldMapping(MappingContext context, String owningClass, S if (parent.getFieldMappings().containsKey(obf)) { parent.getFieldMappings().get(obf).setDeobfuscatedName(deobf); } else { - new FieldMapping(parent, obf, deobf, null); + Stream stream = IndexedClass.INDEXED_CLASSES.get(owningClass).getFields().keySet() + .stream().filter(s -> s.getName().equals(obf)); + if (stream.count() > 1) { + Main.getLogger().warning("Discovered ambiguous field mapping! Ignoring..."); + return; + } else if (stream.count() == 0) { + Main.getLogger().warning("Discovered field mapping for non-existent field - ignoring..."); + return; + } + new FieldMapping(parent, obf, deobf, stream.findFirst().get().getType()); } } From f2ff53d1bd45d7fccb15f608934e62c20f3ae813 Mon Sep 17 00:00:00 2001 From: Minecrell Date: Tue, 16 Aug 2016 18:48:45 +0200 Subject: [PATCH 16/58] Add Lapislazuli so it can fix Travis --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index a9b8e47..7e8beb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,10 @@ script: ./gradlew build notifications: email: false +before_install: + - git config --global user.name "Lapislazuli" + - git config --global user.email "lapislazuli@lapis.blue" + before_script: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" From 5f0eb82ac420e34305e0517ca6fee9e0e2ee52a7 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 13:30:17 -0400 Subject: [PATCH 17/58] Add Jenkinsfile --- Jenkinsfile | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..5ace950 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,29 @@ +node { + def win = System.properties['os.name'].startsWith('Windows') + + stage 'Stage Checkout' + checkout scm + if (win) { + bat 'git submodule update --init' + } else { + sh 'git submodule update --init' + } + + stage 'Stage Build' + def ver = version() + echo "Building version ${ver} on branch ${env.BRANCH_NAME}" + if (win) { + bat "./gradlew -PBUILD_NUMBER=${env.BUILD_NUMBER}" + } else { + sh "./gradlew -PBUILD_NUMBER=${env.BUILD_NUMBER}" + } + + stage 'Stage Archive' + step([$class: 'ArtifactArchiver', artifacts: 'build/libs/*.jar', excludes: 'build/libs/*-base.jar', + fingerprint: true]) +} + +def version() { + def matcher = readFile('build.gradle') =~ 'version = \'(.+)\'' + matcher ? matcher[0][1] : null +} From ac908e91d9a3ba0377c7d6e318ae953a9eff96a6 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 18:34:21 -0400 Subject: [PATCH 18/58] Update Gradle wrapper to 3.0 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 53324 -> 53319 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d99d3fa..2e9c114 100644 --- a/build.gradle +++ b/build.gradle @@ -125,5 +125,5 @@ artifacts { } task wrapper(type: Wrapper) { - gradleVersion = '2.14' + gradleVersion = '3.0' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3baa851b28c65f87dd36a6748e1a85cf360c1301..d3b83982b9b1bccad955349d702be9b884c6e049 100644 GIT binary patch delta 2138 zcmZ9M4Nz276vywr-DMZuT^14c~ z6N;x&M;f)+^mdeHuqEwRj6nCY1qM8oLx@i4ZiG+~!%EWZP;li7R67pC#h3XClONGH5 zio@TL!T@2C%fi^8<%&22@5_Eg@TPn(f(D(^&kISo<}4%Lz87RjhWxiNvO#ZEAUR;p z@WY8DS|!JcHa1`^POP);j?vIm$!FcZ>+D{HG-{wyW(2iU(~vReAj=_5S1?EQf^?-2 z2FtTD)m9pn8ZsED5jxYb@aN3T+lq?ceP2$=EBWz{ zft`PK?x?7DdFH(scP8AJsL+J3TT?xwb)e;&pH8nX`sIZkVVi@iNgS80$qtFG^lN(e zT32G(2VZXeblTg8f}+DGwJ$0TUwLAC%2Zq9!z1RHlMiZq9v9P^B5}i8*uM3GsFlfmLRHZhg_AV+d*<2@!GEq*pvEO85sQMC{xb`>6aA`}8lsT8z4zs0q>J~Gfi}guNGvRPQ zBX^F>XPVSwfKhOzIZaBt3St~n#oYzPju^a{S_iM&O)q41p)De9wuBomWi2UO+9d}s zaln0t5tW7(Uh*6Grt2WJ1$zNrZ{azU1ionVhct;6s#;Vitf5%KjbLv`;6g#u%9c#6 zJhxVcOLJR!RIj9HsT|Rs)`=FOwF0j!KJSzha*u8$n(pn<(^#rhqA*Tr0b?7pw6^hF zkOuLR4h1aK_)UJ|9Lc#QuEFgxLK3_QiF{;6$HvloU~ij&IrpuPJet8#Nb{OSnsfeW zt`1OvrJd!BXy>_=dc=0UA1GZa^oYIKbbY^Ahk0j zQ_u)dsG#upuz~(-$-hZi*{s2Ag-de_mPh0i*H#R!Ycp zk*28(2Fl_gv6tnU+sktwm1CZYUe*&^_BHBk;|S@b%_#Pdg~49tpXKxX>1uj%E8U0q zRlaIRGq=YJGF=AT%uA=Ts#F%>Uf>oed#k~5qmA^$N)myQ%yOlJAT zF%6f|+5AGMOZxb=R>kBp2z)N>M_`+*41ro7xt9wfp{iQ~;ySTcib%iD5dq25gt#J7 zu3P7Y!C1ILhJh;5*ByhYOGe!=n7pc2FqEuy73A)wwQ_!orY0vTA1xg*+V?xkcS1FX zs3TdQZ~sNrtoL5rchVHLwISuH|N1*gNsncZ{*0XxaysPK{`!624=1PsHuae*D?QG> zpQ!%2?rvGvs-D96UNzktY$w_0Wn|9t6*;!3AoUNDhXG+x9opd&O@-G_g>HMY24G(rb`-A%jYg_)VrxjzL4Nj>X{ij%Xp!-z z?TU!yt1bcgwy+BQYL^vNsBvqkWLQA%m);eE*7A!|+}c~k3eI0t4+&elYc>i#w=Tp8 zoPhdk0y5OFM&QID~kd1Hr}kCaszS>)(|pHls6kmW16)zrDYOoKW*U{ z?Gn_UYYE0OZgouDRRSf{sb24-FCA_PLr#W1<4B!^kaa8}ks|*mG{zc-)`eD%Attn* zWl~YQRVd)Lm6NQePpsj3{=IU348R0(b^huK>XT_#@+7LYDfmlIvu&ItjUKWE;=gJe z$Iuiy?C_`eZ3cvttsE1WN++iU)0M4WXudjjLO=x!WE85I@3iJGnOhnV7t+R7!Mq)` zigeWK_qxy(>Av)wU4b40!OD?1s5Ak5!bBebYz2XqhGzIt|2BcV$ZyM7t1BS~;My+` zk&80X{Ys{m=8u!LnZ7mc;MxP(%@vW)=Q>jv%Jp=na{r_5seK^W1}7{M39j!zfnsMM z@2=w;8Bvl${)|bk2l2r7PWEA9|iPq zRS<1&Q{x$hF%emxfZiSS^F(J{qOaQCL0P<=V-6Rh+d+F6LX7||C;}*mzO<_`lVp#D z*Gr+a5GYOjo(+_scC{lAiE&+<2af{r1e7Kw-YFeV*@bG$6runBZt?xtWw^H{1z!0{ z?u0~(ay8Q-M?5CBpq*oORY8ewIVXCt>3r^YaNZdhl6azfs-5RGR{J`qI#p^^_(M<9 z`D#SxWY>T|OJ~?QJnX#=j_JC99`3c=8~IWaeT?tz3-E~&`S{S^JB(;Cy^~`G8qgx6 mGXSB304=(NP+O+~r{pnaF?oZ78Xld Date: Tue, 16 Aug 2016 19:16:42 -0400 Subject: [PATCH 19/58] Fix compile errors and such --- .../gui/scene/text/SelectableMember.java | 44 ++++++++----- .../nocturne/jar/model/JarClassEntry.java | 12 ++-- .../mapping/io/reader/EnigmaReader.java | 2 +- .../nocturne/mapping/io/reader/SrgReader.java | 3 +- .../nocturne/mapping/model/FieldMapping.java | 8 +-- .../nocturne/mapping/model/MethodMapping.java | 9 +-- .../processor/index/ClassIndexer.java | 18 +++--- .../processor/index/model/IndexedClass.java | 10 +-- .../processor/index/model/IndexedField.java | 46 ++------------ .../processor/index/model/IndexedMethod.java | 46 ++------------ .../index/model/signature/FieldSignature.java | 63 +++++++++++++++++++ .../model/signature/MemberSignature.java | 43 +++++++++++++ .../model/signature/MethodSignature.java | 63 +++++++++++++++++++ .../nocturne/util/helper/HierarchyHelper.java | 3 +- .../nocturne/util/helper/MappingsHelper.java | 33 ++++++---- 15 files changed, 263 insertions(+), 140 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java create mode 100644 src/main/java/blue/lapis/nocturne/processor/index/model/signature/MemberSignature.java create mode 100644 src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index ea02086..f7fffc9 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -40,8 +40,9 @@ import blue.lapis.nocturne.mapping.model.Mapping; import blue.lapis.nocturne.mapping.model.MemberMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; -import blue.lapis.nocturne.processor.index.model.IndexedField; -import blue.lapis.nocturne.processor.index.model.IndexedMethod; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MemberSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.MemberType; import blue.lapis.nocturne.util.helper.HierarchyHelper; import blue.lapis.nocturne.util.helper.MappingsHelper; @@ -81,9 +82,7 @@ public class SelectableMember extends Text { private final StringProperty descriptorProperty = new SimpleStringProperty(this, "descriptor"); private final StringProperty parentClassProperty = new SimpleStringProperty(this, "parentClass"); - private final Type fieldType; - private final MethodDescriptor desc; - private final IndexedMethod.Signature sig; + private final MemberSignature sig; private String fullName = null; // only used for classes @@ -97,9 +96,15 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de this.type = type; this.nameProperty.set(name); this.descriptorProperty.set(descriptor); - this.fieldType = type == MemberType.FIELD ? Type.fromString(descriptor) : null; - this.desc = type == MemberType.METHOD ? MethodDescriptor.fromString(descriptor) : null; - this.sig = type == MemberType.METHOD ? new IndexedMethod.Signature(name, desc) : null; + + if (type == MemberType.FIELD) { + this.sig = new FieldSignature(name, Type.fromString(descriptor)); + } else if (type == MemberType.METHOD) { + this.sig = new MethodSignature(name, MethodDescriptor.fromString(descriptor)); + } else { + this.sig = null; + } + this.parentClassProperty.set(parentClass); if (type == MemberType.CLASS) { @@ -212,17 +217,20 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de qualName = name; break; case FIELD: - if (!ic.getFields().contains(getName())) { + //noinspection SuspiciousMethodCalls: sig must be a FieldSignature object + if (!ic.getFields().containsKey(sig)) { throw new IllegalArgumentException(); } qualName = getParentClass() + CLASS_PATH_SEPARATOR_CHAR + name; break; case METHOD: String parent = null; + //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object if (ic.getMethods().containsKey(sig)) { parent = getParentClass(); } else { for (IndexedClass hc : ic.getHierarchy()) { + //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object if (hc.getMethods().containsKey(sig)) { parent = hc.getName(); break; @@ -238,7 +246,8 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de throw new AssertionError(); } //TODO: we're ignoring field descriptors for now since SRG doesn't support them - MemberKey key = new MemberKey(type, qualName, type == MemberType.METHOD ? descriptor : null); + MemberKey key = new MemberKey(type, qualName, + type == MemberType.FIELD || type == MemberType.METHOD ? descriptor : null); if (!MEMBERS.containsKey(key)) { MEMBERS.put(key, new ArrayList<>()); } @@ -277,7 +286,8 @@ private boolean checkMemberDupe(String newName) { } case FIELD: { JarClassEntry jce = Main.getLoadedJar().getClass(getParentClass()).get(); - IndexedField.Signature newSig = new IndexedField.Signature(newName, this.fieldType); + FieldSignature newSig = new FieldSignature(newName, + ((FieldSignature) sig).getType()); if (jce.getCurrentFields().containsValue(newSig)) { showDupeAlert(false); return false; @@ -286,11 +296,13 @@ private boolean checkMemberDupe(String newName) { } } case METHOD: { - Set hierarchy = HierarchyHelper.getClassesInHierarchy(getParentClass(), sig).stream() - .filter(c -> Main.getLoadedJar().getClass(c).isPresent()) + Set hierarchy = HierarchyHelper.getClassesInHierarchy(getParentClass(), + (MethodSignature) sig) + .stream().filter(c -> Main.getLoadedJar().getClass(c).isPresent()) .map(c -> Main.getLoadedJar().getClass(c).get()).collect(Collectors.toSet()); for (JarClassEntry jce : hierarchy) { - IndexedMethod.Signature newSig = new IndexedMethod.Signature(newName, this.desc); + MethodSignature newSig + = new MethodSignature(newName, ((MethodSignature) sig).getDescriptor()); if (jce.getCurrentMethods().containsValue(newSig)) { showDupeAlert(!jce.getName().equals(getName())); return false; @@ -333,7 +345,8 @@ public void setMapping(String mapping) { break; } case FIELD: { - MappingsHelper.genFieldMapping(Main.getMappingContext(), getParentClass(), getName(), mapping); + MappingsHelper.genFieldMapping(Main.getMappingContext(), getParentClass(), getName(), mapping, + getDescriptor()); break; } case METHOD: { @@ -342,6 +355,7 @@ public void setMapping(String mapping) { classes.add(clazz); for (IndexedClass ic : classes) { + //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object if (ic.getMethods().containsKey(sig)) { MappingsHelper.genMethodMapping(Main.getMappingContext(), ic.getName(), getName(), mapping, getDescriptor()); diff --git a/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java b/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java index ca2acfd..ad28f49 100644 --- a/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java +++ b/src/main/java/blue/lapis/nocturne/jar/model/JarClassEntry.java @@ -35,8 +35,8 @@ import blue.lapis.nocturne.decompile.SimpleBytecodeProvider; import blue.lapis.nocturne.decompile.SimpleFernflowerLogger; import blue.lapis.nocturne.processor.index.ClassIndexer; -import blue.lapis.nocturne.processor.index.model.IndexedField; -import blue.lapis.nocturne.processor.index.model.IndexedMethod; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.processor.transform.ClassTransformer; import blue.lapis.nocturne.util.MemberType; import blue.lapis.nocturne.util.helper.StringHelper; @@ -64,8 +64,8 @@ public class JarClassEntry { private boolean deobfuscated; private final Map classNames = new HashMap<>(); - private final Map fields = new HashMap<>(); - private final Map methods = new HashMap<>(); + private final Map fields = new HashMap<>(); + private final Map methods = new HashMap<>(); static { if (!Main.getInstance().testingEnv) { @@ -194,11 +194,11 @@ public Map getCurrentInnerClassNames() { return classNames; } - public Map getCurrentFields() { + public Map getCurrentFields() { return fields; } - public Map getCurrentMethods() { + public Map getCurrentMethods() { return methods; } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index d4f6619..33babcb 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -81,7 +81,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; String type = arr[3]; - MappingsHelper.genFieldMapping(Main.getMappingContext(), currentClass, obf, deobf); // TODO: type + MappingsHelper.genFieldMapping(Main.getMappingContext(), currentClass, obf, deobf, type); break; } case "METHOD": { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java index 30edd48..d8a6e35 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java @@ -99,7 +99,8 @@ private void genFieldMappings(MappingContext context, List fieldMappings String owningClass = arr[1].substring(0, lastIndex); String obf = arr[1].substring(lastIndex + 1); String deobf = arr[2].substring(arr[2].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1); - MappingsHelper.genFieldMapping(context, owningClass, obf, deobf); + // SRG doesn't support field types so we just pass a null type arg and let the helper method figure it out + MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, null); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index ba7e87b..bcd6bd8 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -30,7 +30,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.attribute.Type; -import blue.lapis.nocturne.processor.index.model.IndexedField; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; import blue.lapis.nocturne.util.MemberType; /** @@ -40,7 +40,7 @@ public class FieldMapping extends MemberMapping { private final ClassMapping parent; private final Type type; - private final IndexedField.Signature sig; + private final FieldSignature sig; /** * Constructs a new {@link FieldMapping} with the given parameters. @@ -54,7 +54,7 @@ public FieldMapping(ClassMapping parent, String obfName, String deobfName, Type super(parent, obfName, deobfName); this.parent = parent; this.type = type; - this.sig = new IndexedField.Signature(obfName, type); + this.sig = new FieldSignature(obfName, type); parent.addFieldMapping(this); } @@ -82,7 +82,7 @@ public void setDeobfuscatedName(String deobf) { super.setDeobfuscatedName(deobf); Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentFields().put(sig, new IndexedField.Signature(getDeobfuscatedName(), type)); + .getCurrentFields().put(sig, new FieldSignature(getDeobfuscatedName(), type)); } @Override diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index 4663a79..967f584 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -31,10 +31,11 @@ import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.processor.index.model.IndexedClass; -import blue.lapis.nocturne.processor.index.model.IndexedMethod; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.MemberType; import blue.lapis.nocturne.util.helper.HierarchyHelper; import blue.lapis.nocturne.util.helper.MappingsHelper; + import com.google.common.collect.ImmutableMap; import java.util.HashMap; @@ -48,7 +49,7 @@ public class MethodMapping extends MemberMapping { private final Map argumentMappings = new HashMap<>(); private final SelectableMember.MemberKey memberKey; private final MethodDescriptor descriptor; - private final IndexedMethod.Signature sig; + private final MethodSignature sig; /** * Constructs a new {@link MethodMapping} with the given parameters. @@ -65,7 +66,7 @@ public MethodMapping(ClassMapping parent, String obfName, String deobfName, Meth boolean propagate) { super(parent, obfName, deobfName); this.descriptor = descriptor; - this.sig = new IndexedMethod.Signature(getObfuscatedName(), descriptor); + this.sig = new MethodSignature(getObfuscatedName(), descriptor); memberKey = new SelectableMember.MemberKey(MemberType.METHOD, getQualifiedName(), getObfuscatedDescriptor().toString()); parent.addMethodMapping(this, propagate); @@ -160,7 +161,7 @@ public void setDeobfuscatedName(String deobf, boolean propagate) { } Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentMethods().put(sig, new IndexedMethod.Signature(deobf, descriptor)); + .getCurrentMethods().put(sig, new MethodSignature(deobf, descriptor)); } } diff --git a/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java b/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java index 8431cc5..c18edad 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/ClassIndexer.java @@ -44,8 +44,8 @@ import blue.lapis.nocturne.processor.index.model.IndexedClass; import blue.lapis.nocturne.processor.index.model.IndexedField; import blue.lapis.nocturne.processor.index.model.IndexedMethod; - -import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -94,7 +94,7 @@ public IndexedClass index() { } } - List fields = indexFields(buffer, pool); + List fields = indexFields(buffer, pool); List methods = indexMethods(buffer, pool); @@ -107,16 +107,16 @@ public IndexedClass index() { * * @param buffer The buffer to read from */ - private List indexFields(ByteBuffer buffer, ConstantPool pool) { - List fields = new ArrayList<>(); + private List indexFields(ByteBuffer buffer, ConstantPool pool) { + List fields = new ArrayList<>(); int fieldCount = buffer.getShort(); // read the field count for (int i = 0; i < fieldCount; i++) { - buffer.position(buffer.position() + 2); // skip the access + IndexedField.Visibility vis = IndexedField.Visibility.fromAccessFlags(buffer.getShort()); // get the access String name = getString(pool, buffer.getShort()); // get the name Type desc = Type.fromString(getString(pool, buffer.getShort())); // get the descriptor - IndexedField.Signature sig = new IndexedField.Signature(name, desc); - fields.add(sig); + FieldSignature sig = new FieldSignature(name, desc); + fields.add(new IndexedField(sig, vis)); jce.getCurrentFields().put(sig, sig); // index the field name for future reference skipAttributes(buffer); } @@ -140,7 +140,7 @@ private List indexMethods(ByteBuffer buffer, ConstantPool pool) { IndexedMethod.Visibility vis = IndexedMethod.Visibility.fromAccessFlags(buffer.getShort()); String name = getString(pool, buffer.getShort()); MethodDescriptor desc = MethodDescriptor.fromString(getString(pool, buffer.getShort())); - IndexedMethod.Signature sig = new IndexedMethod.Signature(name, desc); + MethodSignature sig = new MethodSignature(name, desc); methods.add(new IndexedMethod(sig, vis)); jce.getCurrentMethods().put(sig, sig); // index the method sig for future reference diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java index 5fbeeb6..b195d9b 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedClass.java @@ -26,6 +26,8 @@ package blue.lapis.nocturne.processor.index.model; import blue.lapis.nocturne.processor.constantpool.model.ImmutableConstantPool; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -46,8 +48,8 @@ public class IndexedClass extends Hierarchical { private ImmutableConstantPool constantPool; private final String superClass; private final ImmutableList interfaces; - private final ImmutableMap fields; - private final ImmutableMap methods; + private final ImmutableMap fields; + private final ImmutableMap methods; public IndexedClass(String name, ImmutableConstantPool constantPool, String superClass, List interfaces, List fields, List methods) { @@ -78,11 +80,11 @@ public ImmutableList getInterfaces() { return interfaces; } - public ImmutableMap getFields() { + public ImmutableMap getFields() { return fields; } - public ImmutableMap getMethods() { + public ImmutableMap getMethods() { return methods; } diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java index 25e33a5..c7ad5fc 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedField.java @@ -25,26 +25,25 @@ package blue.lapis.nocturne.processor.index.model; -import blue.lapis.nocturne.jar.model.attribute.Type; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** * Represents a method serialized by Nocturne's class indexer. */ public class IndexedField extends Hierarchical { - private final Signature signature; + private final FieldSignature signature; private final Visibility visibility; - public IndexedField(Signature signature, Visibility visibility) { + public IndexedField(FieldSignature signature, Visibility visibility) { this.signature = signature; this.visibility = visibility; } - public Signature getSignature() { + public FieldSignature getSignature() { return signature; } @@ -52,43 +51,6 @@ public Visibility getVisibility() { return visibility; } - /** - * Represents the unique signature of a particular field. - */ - public static class Signature { - - private final String name; - private final Type type; - - public Signature(String name, Type type) { - this.name = name; - this.type = type; - } - - public String getName() { - return name; - } - - public Type getType() { - return type; - } - - @Override - public boolean equals(Object otherObj) { - if (!(otherObj instanceof Signature)) { - return false; - } - Signature sig = (Signature) otherObj; - return sig.getName().equals(getName()) && sig.getType().equals(getType()); - } - - @Override - public int hashCode() { - return Objects.hash(name, type); - } - - } - /** * Represents the visibility level of a particular method. */ diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedMethod.java b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedMethod.java index 91ee88c..65453b6 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedMethod.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/IndexedMethod.java @@ -25,26 +25,25 @@ package blue.lapis.nocturne.processor.index.model; -import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** * Represents a method serialized by Nocturne's class indexer. */ public class IndexedMethod extends Hierarchical { - private final Signature signature; + private final MethodSignature signature; private final Visibility visibility; - public IndexedMethod(Signature signature, Visibility visibility) { + public IndexedMethod(MethodSignature signature, Visibility visibility) { this.signature = signature; this.visibility = visibility; } - public Signature getSignature() { + public MethodSignature getSignature() { return signature; } @@ -52,43 +51,6 @@ public Visibility getVisibility() { return visibility; } - /** - * Represents the unique signature of a particular method. - */ - public static class Signature { - - private final String name; - private final MethodDescriptor descriptor; - - public Signature(String name, MethodDescriptor descriptor) { - this.name = name; - this.descriptor = descriptor; - } - - public String getName() { - return name; - } - - public MethodDescriptor getDescriptor() { - return descriptor; - } - - @Override - public boolean equals(Object otherObj) { - if (!(otherObj instanceof Signature)) { - return false; - } - Signature sig = (Signature) otherObj; - return sig.getName().equals(getName()) && sig.getDescriptor().equals(getDescriptor()); - } - - @Override - public int hashCode() { - return Objects.hash(name, descriptor); - } - - } - /** * Represents the visibility level of a particular method. */ diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java new file mode 100644 index 0000000..4335917 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java @@ -0,0 +1,63 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.processor.index.model.signature; + +import blue.lapis.nocturne.jar.model.attribute.Type; +import blue.lapis.nocturne.processor.index.model.IndexedField; + +import java.util.Objects; + +/** + * Represents the unique signature of a particular field. + */ +public class FieldSignature extends MemberSignature { + + protected final Type type; + + public FieldSignature(String name, Type type) { + super(name); + this.type = type; + } + + public Type getType() { + return type; + } + + @Override + public boolean equals(Object otherObj) { + if (!(otherObj instanceof FieldSignature)) { + return false; + } + FieldSignature sig = (FieldSignature) otherObj; + return sig.getName().equals(getName()) && sig.getType().equals(getType()); + } + + @Override + public int hashCode() { + return Objects.hash(name, type); + } + +} diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MemberSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MemberSignature.java new file mode 100644 index 0000000..ea5fd52 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MemberSignature.java @@ -0,0 +1,43 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.processor.index.model.signature; + +/** + * Represents the unique signature of a particular class member. + */ +public abstract class MemberSignature { + + protected final String name; + + public MemberSignature(String name) { + this.name = name; + } + + public String getName() { + return name; + } + +} diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java new file mode 100644 index 0000000..a18df7f --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java @@ -0,0 +1,63 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.processor.index.model.signature; + +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.processor.index.model.IndexedMethod; + +import java.util.Objects; + +/** + * Represents the unique signature of a particular method. + */ +public class MethodSignature extends MemberSignature { + + protected final MethodDescriptor descriptor; + + public MethodSignature(String name, MethodDescriptor descriptor) { + super(name); + this.descriptor = descriptor; + } + + public MethodDescriptor getDescriptor() { + return descriptor; + } + + @Override + public boolean equals(Object otherObj) { + if (!(otherObj instanceof MethodSignature)) { + return false; + } + MethodSignature sig = (MethodSignature) otherObj; + return sig.getName().equals(getName()) && sig.getDescriptor().equals(getDescriptor()); + } + + @Override + public int hashCode() { + return Objects.hash(name, descriptor); + } + +} diff --git a/src/main/java/blue/lapis/nocturne/util/helper/HierarchyHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/HierarchyHelper.java index a1e76b6..e98e611 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/HierarchyHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/HierarchyHelper.java @@ -31,6 +31,7 @@ import blue.lapis.nocturne.processor.index.model.IndexedClass; import blue.lapis.nocturne.processor.index.model.IndexedMethod; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import java.util.Set; import java.util.stream.Collectors; @@ -40,7 +41,7 @@ */ public final class HierarchyHelper { - public static Set getClassesInHierarchy(String className, IndexedMethod.Signature sig) { + public static Set getClassesInHierarchy(String className, MethodSignature sig) { checkState(INDEXED_CLASSES.containsKey(className), "Class \"" + className + "\" is not indexed"); IndexedClass clazz = INDEXED_CLASSES.get(className); diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 94e42da..bf15f01 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -30,6 +30,7 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; @@ -37,9 +38,11 @@ import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; -import blue.lapis.nocturne.processor.index.model.IndexedField; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -85,7 +88,9 @@ public static void genClassMapping(MappingContext context, String obf, String de } //TODO: modify this to accept proper field signatures - public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf) { + // this is gonna be tricky + public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, + String descriptor) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for field in non-existent class \"" + owningClass + "\" - ignoring"); @@ -99,16 +104,22 @@ public static void genFieldMapping(MappingContext context, String owningClass, S if (parent.getFieldMappings().containsKey(obf)) { parent.getFieldMappings().get(obf).setDeobfuscatedName(deobf); } else { - Stream stream = IndexedClass.INDEXED_CLASSES.get(owningClass).getFields().keySet() - .stream().filter(s -> s.getName().equals(obf)); - if (stream.count() > 1) { - Main.getLogger().warning("Discovered ambiguous field mapping! Ignoring..."); - return; - } else if (stream.count() == 0) { - Main.getLogger().warning("Discovered field mapping for non-existent field - ignoring..."); - return; + Type type; + if (descriptor != null) { + type = Type.fromString(descriptor); + } else { + List sigList = IndexedClass.INDEXED_CLASSES.get(owningClass).getFields().keySet() + .stream().filter(s -> s.getName().equals(obf)).collect(Collectors.toList()); + if (sigList.size() > 1) { + Main.getLogger().warning("Discovered ambiguous field mapping! Ignoring..."); + return; + } else if (sigList.size() == 0) { + Main.getLogger().warning("Discovered field mapping for non-existent field - ignoring..."); + return; + } + type = sigList.get(0).getType(); } - new FieldMapping(parent, obf, deobf, stream.findFirst().get().getType()); + new FieldMapping(parent, obf, deobf, type); } } From 1cfa0c2665bb856d32bb872e768f9e1633e1e89c Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 19:30:57 -0400 Subject: [PATCH 20/58] Fix field members not being updated in GUI --- .../java/blue/lapis/nocturne/mapping/model/FieldMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index bcd6bd8..0108a79 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -87,7 +87,7 @@ public void setDeobfuscatedName(String deobf) { @Override protected SelectableMember.MemberKey getMemberKey() { - return new SelectableMember.MemberKey(MemberType.FIELD, getQualifiedName(), null); + return new SelectableMember.MemberKey(MemberType.FIELD, getQualifiedName(), type.toString()); } private String getQualifiedName() { From 51849cde877068b074b9581061ec66ff7ff2f45c Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 19:38:28 -0400 Subject: [PATCH 21/58] Remove useless comment --- .../java/blue/lapis/nocturne/util/helper/MappingsHelper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index bf15f01..d09eccf 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -87,8 +87,6 @@ public static void genClassMapping(MappingContext context, String obf, String de } } - //TODO: modify this to accept proper field signatures - // this is gonna be tricky public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, String descriptor) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { From 7368d4831bf56d329f5bb40f56db279bcf8f0893 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 21:19:00 -0400 Subject: [PATCH 22/58] Fix bugs relating to arg mappings --- .../gui/scene/text/SelectableMember.java | 2 +- .../mapping/io/reader/EnigmaReader.java | 27 ++++++++++--------- .../nocturne/mapping/io/reader/SrgReader.java | 2 +- .../mapping/io/writer/EnigmaWriter.java | 6 ++--- .../nocturne/util/helper/MappingsHelper.java | 5 ++-- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index f7fffc9..1a7cfaa 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -358,7 +358,7 @@ public void setMapping(String mapping) { //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object if (ic.getMethods().containsKey(sig)) { MappingsHelper.genMethodMapping(Main.getMappingContext(), ic.getName(), getName(), mapping, - getDescriptor()); + getDescriptor(), false); } } break; diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index f07d174..69a9ad5 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -127,25 +127,28 @@ public MappingContext read() { break; } case METHOD_MAPPING_KEY: { - if (arr.length == 3) { - continue; - } - - if (arr.length != 4) { - throw new IllegalArgumentException("Cannot parse file: malformed method mapping on line " - + lineNum); - } - if (currentClass == null) { throw new IllegalArgumentException("Cannot parse file: found method mapping before initial " + "class mapping on line " + lineNum); } String obf = arr[1]; - String deobf = arr[2]; - String sig = arr[3]; + String deobf; + String sig; + if (arr.length == 3) { + deobf = obf; + sig = arr[2]; + } else if (arr.length == 4) { + deobf = arr[2]; + sig = arr[3]; + } else { + throw new IllegalArgumentException("Cannot parse file: malformed method mapping on line " + + lineNum); + } + - currentMethod = MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, sig); + currentMethod = MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, + deobf, sig, true); break; } case ARG_MAPPING_KEY: { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java index d8a6e35..799f3e2 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java @@ -112,7 +112,7 @@ private void genMethodMappings(MappingContext context, List methodMappin String obf = arr[1].substring(lastIndex + 1); String descriptor = arr[2]; String deobf = arr[3].substring(arr[3].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1); - MappingsHelper.genMethodMapping(context, owningClass, obf, deobf, descriptor); + MappingsHelper.genMethodMapping(context, owningClass, obf, deobf, descriptor, false); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index 0920600..8a2f2ec 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -54,6 +54,7 @@ public void write(MappingContext mappings) { for (TopLevelClassMapping classMapping : mappings.getMappings().values()) { this.writeClassMapping(classMapping, 0); } + out.close(); } protected void writeClassMapping(ClassMapping classMapping, int depth) { @@ -95,9 +96,8 @@ protected void writeMethodMapping(MethodMapping methodMapping, int depth) { } } - protected void writeArgumentMapping(ArgumentMapping argumentMapping, int depth) { - // TODO: get the actual index - out.println(getIndentForDepth(depth) + "ARG 0 " + argumentMapping.getDeobfuscatedName()); + protected void writeArgumentMapping(ArgumentMapping argMapping, int depth) { + out.println(getIndentForDepth(depth) + "ARG " + argMapping.getIndex() + " " + argMapping.getDeobfuscatedName()); } private String getIndentForDepth(int depth) { diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 7228f54..d973e8b 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -130,12 +130,13 @@ public static void genFieldMapping(MappingContext context, String owningClass, S } public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, - String descriptor) { + String descriptor, boolean acceptInitializer) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for method in non-existent class \"" + owningClass + "\" - ignoring"); return null; - } else if (!StringHelper.isJavaIdentifier(obf) || !StringHelper.isJavaIdentifier(deobf)) { + } else if (!(obf.equals("") && acceptInitializer && obf.equals(deobf)) + && (!StringHelper.isJavaIdentifier(obf) || !StringHelper.isJavaIdentifier(deobf))) { Main.getLogger().warning("Discovered method mapping with illegal name - ignoring"); return null; } From e95f3e979cb36f062c1b694699394b5dbca2df3d Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 21:47:40 -0400 Subject: [PATCH 23/58] Fix handling of 'none/' prefixes in Enigma mappings --- .../mapping/io/reader/EnigmaReader.java | 45 ++++++++++++++++--- .../nocturne/mapping/io/reader/SrgReader.java | 3 +- .../mapping/io/writer/EnigmaWriter.java | 42 ++++++++++++++--- .../blue/lapis/nocturne/util/Constants.java | 2 + .../nocturne/util/helper/MappingsHelper.java | 24 ++++++---- 5 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 69a9ad5..f11632a 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -25,13 +25,17 @@ package blue.lapis.nocturne.mapping.io.reader; +import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_PATTERN; +import static blue.lapis.nocturne.util.Constants.ENIGMA_ROOT_PACKAGE_PREFIX; import static javax.swing.text.html.HTML.Tag.HEAD; import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -92,8 +96,8 @@ public MappingContext read() { + lineNum); } - String obf = arr[1].replace("none/", ""); - String deobf = arr.length == 3 ? arr[2] : obf; + String obf = removeNonePrefix(arr[1]); + String deobf = arr.length == 3 ? removeNonePrefix(arr[2]) : obf; if (indentLevel != 0) { if (currentClass == null) { @@ -121,7 +125,7 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; - String type = arr[3]; + Type type = removeNonePrefix(Type.fromString(arr[3])); MappingsHelper.genFieldMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, type); currentMethod = null; break; @@ -134,21 +138,22 @@ public MappingContext read() { String obf = arr[1]; String deobf; - String sig; + String descStr; if (arr.length == 3) { deobf = obf; - sig = arr[2]; + descStr = arr[2]; } else if (arr.length == 4) { deobf = arr[2]; - sig = arr[3]; + descStr = arr[3]; } else { throw new IllegalArgumentException("Cannot parse file: malformed method mapping on line " + lineNum); } + MethodDescriptor desc = removeNonePrefixes(MethodDescriptor.fromString(descStr)); currentMethod = MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, - deobf, sig, true); + deobf, desc, true); break; } case ARG_MAPPING_KEY: { @@ -176,4 +181,30 @@ public MappingContext read() { return mappings; } + + private String removeNonePrefix(String str) { + if (str.length() < 6) { + return str; + } + String substr = str.substring(5); + if (str.startsWith(ENIGMA_ROOT_PACKAGE_PREFIX) + && !CLASS_PATH_SEPARATOR_PATTERN.matcher(str.substring(5)).find()) { + return substr; + } + return str; + } + + private Type removeNonePrefix(Type type) { + return type.isPrimitive() ? type : Type.fromString("L" + removeNonePrefix(type.getClassName()) + ";"); + } + + private MethodDescriptor removeNonePrefixes(MethodDescriptor desc) { + Type[] params = new Type[desc.getParamTypes().length]; + for (int i = 0; i < params.length; i++) { + params[i] = removeNonePrefix(desc.getParamTypes()[i]); + } + Type returnType = removeNonePrefix(desc.getReturnType()); + return new MethodDescriptor(returnType, params); + } + } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java index 799f3e2..bbb9d42 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java @@ -27,6 +27,7 @@ import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_CHAR; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.util.helper.MappingsHelper; @@ -100,7 +101,7 @@ private void genFieldMappings(MappingContext context, List fieldMappings String obf = arr[1].substring(lastIndex + 1); String deobf = arr[2].substring(arr[2].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1); // SRG doesn't support field types so we just pass a null type arg and let the helper method figure it out - MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, null); + MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, (Type) null); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index 8a2f2ec..9552078 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -25,6 +25,11 @@ package blue.lapis.nocturne.mapping.io.writer; +import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_PATTERN; +import static blue.lapis.nocturne.util.Constants.ENIGMA_ROOT_PACKAGE_PREFIX; + +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; @@ -59,9 +64,10 @@ public void write(MappingContext mappings) { protected void writeClassMapping(ClassMapping classMapping, int depth) { if (classMapping.getDeobfuscatedName().equals(classMapping.getObfuscatedName())) { - out.println(getIndentForDepth(depth) + "CLASS " + classMapping.getObfuscatedName()); + out.println(getIndentForDepth(depth) + "CLASS " + addNonePrefix(classMapping.getObfuscatedName())); } else { - out.println(getIndentForDepth(depth) + "CLASS " + classMapping.getObfuscatedName() + " " + classMapping.getDeobfuscatedName()); + out.println(getIndentForDepth(depth) + "CLASS " + addNonePrefix(classMapping.getObfuscatedName()) + " " + + addNonePrefix(classMapping.getDeobfuscatedName())); } for (ClassMapping innerClass : classMapping.getInnerClassMappings().values()) { @@ -78,17 +84,18 @@ protected void writeClassMapping(ClassMapping classMapping, int depth) { } protected void writeFieldMapping(FieldMapping fieldMapping, int depth) { - out.println(getIndentForDepth(depth) + "FIELD " + fieldMapping.getObfuscatedName() + " " + fieldMapping.getDeobfuscatedName() + " " - + fieldMapping.getType().toString()); + out.println(getIndentForDepth(depth) + "FIELD " + fieldMapping.getObfuscatedName() + " " + + fieldMapping.getDeobfuscatedName() + " " + addNonePrefix(fieldMapping.getType()).toString()); } protected void writeMethodMapping(MethodMapping methodMapping, int depth) { if (methodMapping.getDeobfuscatedName().equals(methodMapping.getObfuscatedName())) { out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " - + methodMapping.getObfuscatedDescriptor().toString()); + + addNonePrefixes(methodMapping.getObfuscatedDescriptor()).toString()); } else { - out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " + methodMapping.getDeobfuscatedName() + " " - + methodMapping.getObfuscatedDescriptor().toString()); + out.println(getIndentForDepth(depth) + "METHOD " + methodMapping.getObfuscatedName() + " " + + methodMapping.getDeobfuscatedName() + " " + + addNonePrefixes(methodMapping.getObfuscatedDescriptor()).toString()); } for (ArgumentMapping argumentMapping : methodMapping.getArgumentMappings().values()) { @@ -107,4 +114,25 @@ private String getIndentForDepth(int depth) { } return builder.toString(); } + + private String addNonePrefix(String str) { + if (!CLASS_PATH_SEPARATOR_PATTERN.matcher(str).find()) { + return ENIGMA_ROOT_PACKAGE_PREFIX + str; + } + return str; + } + + private Type addNonePrefix(Type type) { + return type.isPrimitive() ? type : Type.fromString("L" + addNonePrefix(type.getClassName()) + ";"); + } + + private MethodDescriptor addNonePrefixes(MethodDescriptor desc) { + Type[] params = new Type[desc.getParamTypes().length]; + for (int i = 0; i < params.length; i++) { + params[i] = addNonePrefix(desc.getParamTypes()[i]); + } + Type returnType = addNonePrefix(desc.getReturnType()); + return new MethodDescriptor(returnType, params); + } + } diff --git a/src/main/java/blue/lapis/nocturne/util/Constants.java b/src/main/java/blue/lapis/nocturne/util/Constants.java index 9199c9e..0bed63c 100644 --- a/src/main/java/blue/lapis/nocturne/util/Constants.java +++ b/src/main/java/blue/lapis/nocturne/util/Constants.java @@ -66,6 +66,8 @@ public final class Constants { .put("ind", " ") // set indentation string .build(); + public static final String ENIGMA_ROOT_PACKAGE_PREFIX = "none/"; + static { VERSION = MoreObjects.firstNonNull(Main.class.getPackage().getImplementationVersion(), "UNKNOWN"); } diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index d973e8b..aff9de8 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -97,6 +97,11 @@ public static ClassMapping genClassMapping(MappingContext context, String obf, S public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, String descriptor) { + genFieldMapping(context, owningClass, obf, deobf, descriptor); + } + + public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, + Type descriptor) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for field in non-existent class \"" + owningClass + "\" - ignoring"); @@ -110,10 +115,7 @@ public static void genFieldMapping(MappingContext context, String owningClass, S if (parent.getFieldMappings().containsKey(obf)) { parent.getFieldMappings().get(obf).setDeobfuscatedName(deobf); } else { - Type type; - if (descriptor != null) { - type = Type.fromString(descriptor); - } else { + if (descriptor == null) { List sigList = IndexedClass.INDEXED_CLASSES.get(owningClass).getFields().keySet() .stream().filter(s -> s.getName().equals(obf)).collect(Collectors.toList()); if (sigList.size() > 1) { @@ -123,14 +125,20 @@ public static void genFieldMapping(MappingContext context, String owningClass, S Main.getLogger().warning("Discovered field mapping for non-existent field - ignoring..."); return; } - type = sigList.get(0).getType(); + descriptor = sigList.get(0).getType(); } - new FieldMapping(parent, obf, deobf, type); + new FieldMapping(parent, obf, deobf, descriptor); } } public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, - String descriptor, boolean acceptInitializer) { + String descriptor, boolean acceptInitializer) { + return genMethodMapping(context, owningClass, obf, deobf, MethodDescriptor.fromString(descriptor), + acceptInitializer); + } + + public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, + MethodDescriptor descriptor, boolean acceptInitializer) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for method in non-existent class \"" + owningClass + "\" - ignoring"); @@ -147,7 +155,7 @@ public static MethodMapping genMethodMapping(MappingContext context, String owni methodMapping.setDeobfuscatedName(deobf); return methodMapping; } else { - return new MethodMapping(parent, obf, deobf, MethodDescriptor.fromString(descriptor)); + return new MethodMapping(parent, obf, deobf, descriptor); } } From 308156b50715619be608fc055f70345f90ce98df Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 22:55:08 -0400 Subject: [PATCH 24/58] Represent mapping types as enum values --- .../nocturne/mapping/io/MappingFormatType.java | 16 ++++++++++++++++ .../mapping/io/reader/MappingReaderType.java | 15 +++++++++------ .../mapping/io/writer/MappingWriterType.java | 14 ++++++++------ .../nocturne/util/helper/PropertiesHelper.java | 1 + 4 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java new file mode 100644 index 0000000..5a52a0c --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java @@ -0,0 +1,16 @@ +package blue.lapis.nocturne.mapping.io; + +public enum MappingFormatType { + SRG("srg"), + ENIGMA("*"); + + private final String extension; + + MappingFormatType(String extension) { + this.extension = extension; + } + + public String getFileExtension() { + return this.extension; + } +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java index 04c59b9..31824e2 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java @@ -26,6 +26,9 @@ package blue.lapis.nocturne.mapping.io.reader; import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.mapping.io.MappingFormatType; +import blue.lapis.nocturne.mapping.io.writer.EnigmaWriter; +import blue.lapis.nocturne.mapping.io.writer.SrgWriter; import com.google.common.collect.Maps; import javafx.stage.FileChooser; @@ -38,10 +41,8 @@ public enum MappingReaderType { - SRG(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_srg"), "*.srg"), - SrgReader.class), - ENIGMA(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_enigma"), "*.*"), - EnigmaReader.class); + SRG(MappingFormatType.SRG, SrgReader.class), + ENIGMA(MappingFormatType.ENIGMA, EnigmaReader.class); private static final Map filterToType = Maps.newHashMap(); @@ -52,8 +53,10 @@ public enum MappingReaderType { private final FileChooser.ExtensionFilter extensionFilter; private final Constructor readerCtor; - MappingReaderType(FileChooser.ExtensionFilter extensionFilter, Class readerClass) { - this.extensionFilter = extensionFilter; + MappingReaderType(MappingFormatType mappingType, Class readerClass) { + this.extensionFilter = new FileChooser.ExtensionFilter(Main.getResourceBundle() + .getString("filechooser.type_" + mappingType.name().toLowerCase()), + "*." + mappingType.getFileExtension()); try { this.readerCtor = readerClass.getConstructor(BufferedReader.class); } catch (NoSuchMethodException ex) { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java index eb8e747..511df31 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java @@ -26,6 +26,8 @@ package blue.lapis.nocturne.mapping.io.writer; import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.mapping.io.MappingFormatType; + import com.google.common.collect.Maps; import javafx.stage.FileChooser; @@ -37,10 +39,8 @@ public enum MappingWriterType { - SRG(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_srg"), "*.srg"), - SrgWriter.class), - ENIGMA(new FileChooser.ExtensionFilter(Main.getResourceBundle().getString("filechooser.type_enigma"), "*.*"), - EnigmaWriter.class); + SRG(MappingFormatType.SRG, SrgWriter.class), + ENIGMA(MappingFormatType.ENIGMA, EnigmaWriter.class); private static final Map filterToType = Maps.newHashMap(); @@ -51,8 +51,10 @@ public enum MappingWriterType { private final FileChooser.ExtensionFilter extensionFilter; private final Constructor writerCtor; - MappingWriterType(FileChooser.ExtensionFilter extensionFilter, Class readerClass) { - this.extensionFilter = extensionFilter; + MappingWriterType(MappingFormatType mappingType, Class readerClass) { + this.extensionFilter = new FileChooser.ExtensionFilter(Main.getResourceBundle() + .getString("filechooser.type_" + mappingType.name().toLowerCase()), + "*." + mappingType.getFileExtension()); try { this.writerCtor = readerClass.getConstructor(PrintWriter.class); } catch (NoSuchMethodException ex) { diff --git a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java index f5b35ff..e6470fd 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java @@ -104,6 +104,7 @@ public static class Key { public static final Key LOCALE = new Key("locale", "en_US"); public static final Key LAST_JAR_DIRECTORY = new Key("lastJarDir", ""); public static final Key LAST_MAPPINGS_DIRECTORY = new Key("lastMappingsDir", ""); + public static final Key LAST_MAPPING_FORMAT = new Key("lastMappingFormat", ""); private final String key; private final String defaultValue; From ae8839cc6d2912a732389f09ca407eefebb45ab2 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 16 Aug 2016 23:16:23 -0400 Subject: [PATCH 25/58] Teach Nocturne to remember last selected extension filter --- .../io/mappings/MappingsOpenDialogHelper.java | 13 +++++++++---- .../io/mappings/MappingsSaveDialogHelper.java | 19 +++++++++++++++---- .../mapping/io/reader/MappingReaderType.java | 9 ++++++++- .../mapping/io/writer/MappingWriterType.java | 7 +++++++ .../util/helper/PropertiesHelper.java | 3 ++- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index b242958..130ca9c 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -52,8 +52,13 @@ private MappingsOpenDialogHelper() { public static void openMappings() throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(Main.getResourceBundle().getString("filechooser.open_mapping")); - Arrays.asList(MappingReaderType.values()) - .forEach(t -> fileChooser.getExtensionFilters().add(t.getExtensionFilter())); + Arrays.asList(MappingReaderType.values()).forEach(t -> { + fileChooser.getExtensionFilters().add(t.getExtensionFilter()); + if (Main.getPropertiesHelper().getProperty(PropertiesHelper.Key.LAST_MAPPING_LOAD_FORMAT) + .equals(t.name())) { + fileChooser.setSelectedExtensionFilter(t.getExtensionFilter()); + } + }); String lastDir = Main.getPropertiesHelper().getProperty(PropertiesHelper.Key.LAST_MAPPINGS_DIRECTORY); if (!lastDir.isEmpty()) { @@ -71,8 +76,9 @@ public static void openMappings() throws IOException { Path selectedPath = selectedFile.toPath(); - if (Files.exists(selectedPath)) { //TODO: isn't this redundant? MappingReaderType type = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); + Main.getPropertiesHelper() + .setProperty(PropertiesHelper.Key.LAST_MAPPING_LOAD_FORMAT, type.getFormatType().name()); try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { MappingContext context = reader.read(); Main.getMappingContext().assimilate(context); @@ -81,7 +87,6 @@ public static void openMappings() throws IOException { } Main.setCurrentMappingsPath(selectedPath); - } } } diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java index ddc9f83..7416e04 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java @@ -26,6 +26,8 @@ package blue.lapis.nocturne.gui.io.mappings; import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.mapping.io.MappingFormatType; +import blue.lapis.nocturne.mapping.io.reader.MappingReaderType; import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; import blue.lapis.nocturne.mapping.io.writer.MappingsWriter; import blue.lapis.nocturne.util.helper.PropertiesHelper; @@ -60,8 +62,13 @@ public static void saveMappings() throws IOException { public static boolean saveMappingsAs() throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(Main.getResourceBundle().getString("filechooser.save_mapping")); - Arrays.asList(MappingWriterType.values()) - .forEach(t -> fileChooser.getExtensionFilters().add(t.getExtensionFilter())); + Arrays.asList(MappingWriterType.values()).forEach(t -> { + fileChooser.getExtensionFilters().add(t.getExtensionFilter()); + if (Main.getPropertiesHelper().getProperty(PropertiesHelper.Key.LAST_MAPPING_SAVE_FORMAT) + .equals(t.name())) { + fileChooser.setSelectedExtensionFilter(t.getExtensionFilter()); + } + }); String lastDir = Main.getPropertiesHelper().getProperty(PropertiesHelper.Key.LAST_MAPPINGS_DIRECTORY); if (!lastDir.isEmpty()) { @@ -87,17 +94,21 @@ public static boolean saveMappingsAs() throws IOException { Main.getMappingContext().setDirty(true); } - final MappingWriterType writerType = MappingWriterType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); + final MappingWriterType writerType + = MappingWriterType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); Main.setCurrentMappingsPath(selectedFile.toPath()); Main.setCurrentWriterType(writerType); saveMappings0(writerType); + Main.getPropertiesHelper() + .setProperty(PropertiesHelper.Key.LAST_MAPPING_SAVE_FORMAT, writerType.getFormatType().name()); return true; } private static void saveMappings0(MappingWriterType writerType) throws IOException { if (Main.getMappingContext().isDirty()) { - try (MappingsWriter writer = writerType.constructWriter(new PrintWriter(Main.getCurrentMappingsPath().toFile()))) { + try (MappingsWriter writer + = writerType.constructWriter(new PrintWriter(Main.getCurrentMappingsPath().toFile()))) { writer.write(Main.getMappingContext()); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java index 31824e2..fd07d29 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java @@ -44,7 +44,9 @@ public enum MappingReaderType { SRG(MappingFormatType.SRG, SrgReader.class), ENIGMA(MappingFormatType.ENIGMA, EnigmaReader.class); - private static final Map filterToType = Maps.newHashMap(); + private final MappingFormatType type; + + public static final Map filterToType = Maps.newHashMap(); static { Arrays.asList(values()).forEach(t -> filterToType.put(t.getExtensionFilter(), t)); @@ -54,6 +56,7 @@ public enum MappingReaderType { private final Constructor readerCtor; MappingReaderType(MappingFormatType mappingType, Class readerClass) { + this.type = mappingType; this.extensionFilter = new FileChooser.ExtensionFilter(Main.getResourceBundle() .getString("filechooser.type_" + mappingType.name().toLowerCase()), "*." + mappingType.getFileExtension()); @@ -64,6 +67,10 @@ public enum MappingReaderType { } } + public MappingFormatType getFormatType() { + return this.type; + } + public FileChooser.ExtensionFilter getExtensionFilter() { return this.extensionFilter; } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java index 511df31..c0b80bb 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java @@ -42,6 +42,8 @@ public enum MappingWriterType { SRG(MappingFormatType.SRG, SrgWriter.class), ENIGMA(MappingFormatType.ENIGMA, EnigmaWriter.class); + private final MappingFormatType type; + private static final Map filterToType = Maps.newHashMap(); static { @@ -52,6 +54,7 @@ public enum MappingWriterType { private final Constructor writerCtor; MappingWriterType(MappingFormatType mappingType, Class readerClass) { + this.type = mappingType; this.extensionFilter = new FileChooser.ExtensionFilter(Main.getResourceBundle() .getString("filechooser.type_" + mappingType.name().toLowerCase()), "*." + mappingType.getFileExtension()); @@ -62,6 +65,10 @@ public enum MappingWriterType { } } + public MappingFormatType getFormatType() { + return this.type; + } + public FileChooser.ExtensionFilter getExtensionFilter() { return this.extensionFilter; } diff --git a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java index e6470fd..09e9ed8 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/PropertiesHelper.java @@ -104,7 +104,8 @@ public static class Key { public static final Key LOCALE = new Key("locale", "en_US"); public static final Key LAST_JAR_DIRECTORY = new Key("lastJarDir", ""); public static final Key LAST_MAPPINGS_DIRECTORY = new Key("lastMappingsDir", ""); - public static final Key LAST_MAPPING_FORMAT = new Key("lastMappingFormat", ""); + public static final Key LAST_MAPPING_LOAD_FORMAT = new Key("lastMappingLoadFormat", ""); + public static final Key LAST_MAPPING_SAVE_FORMAT = new Key("lastMappingSaveFormat", ""); private final String key; private final String defaultValue; From 671f245fc253fdc8159e76fadefd30a04b9dfae5 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 00:26:05 -0400 Subject: [PATCH 26/58] Add test cases for Enigma reader --- .../io/mappings/MappingsOpenDialogHelper.java | 20 +-- .../mapping/io/MappingFormatType.java | 25 +++ .../mapping/io/reader/EnigmaReader.java | 4 +- .../nocturne/util/helper/MappingsHelper.java | 8 +- .../mapping/io/reader/EnigmaReaderTest.java | 90 +++++++++++ .../mapping/io/reader/ReaderTestHelper.java | 152 ++++++++++++++++++ .../test/mapping/io/reader/SrgReaderTest.java | 110 ++----------- src/test/resources/example.eng | 7 + 8 files changed, 305 insertions(+), 111 deletions(-) create mode 100644 src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java create mode 100644 src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java create mode 100644 src/test/resources/example.eng diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index 130ca9c..0abf501 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -76,17 +76,17 @@ public static void openMappings() throws IOException { Path selectedPath = selectedFile.toPath(); - MappingReaderType type = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); - Main.getPropertiesHelper() - .setProperty(PropertiesHelper.Key.LAST_MAPPING_LOAD_FORMAT, type.getFormatType().name()); - try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { - MappingContext context = reader.read(); - Main.getMappingContext().assimilate(context); - MainController.INSTANCE.updateClassViews(); - Main.getMappingContext().setDirty(false); - } + MappingReaderType type = MappingReaderType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); + Main.getPropertiesHelper() + .setProperty(PropertiesHelper.Key.LAST_MAPPING_LOAD_FORMAT, type.getFormatType().name()); + try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { + MappingContext context = reader.read(); + Main.getMappingContext().assimilate(context); + MainController.INSTANCE.updateClassViews(); + Main.getMappingContext().setDirty(false); + } - Main.setCurrentMappingsPath(selectedPath); + Main.setCurrentMappingsPath(selectedPath); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java index 5a52a0c..54e3288 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java @@ -1,3 +1,28 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.io; public enum MappingFormatType { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index f11632a..5c14e2c 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -104,8 +104,8 @@ public MappingContext read() { throw new IllegalArgumentException("Cannot parse file: found field mapping before initial " + "class mapping on line " + lineNum); } - obf = currentClass.getFullObfuscatedName() + "/" + obf; - deobf = currentClass.getFullDeobfuscatedName() + "/" + deobf; + obf = currentClass.getFullObfuscatedName() + "$" + obf; + deobf = currentClass.getFullDeobfuscatedName() + "$" + deobf; } currentClass = MappingsHelper.genClassMapping(mappings, obf, deobf, false); diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index aff9de8..4a376b1 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -52,7 +52,8 @@ */ public final class MappingsHelper { - public static ClassMapping genClassMapping(MappingContext context, String obf, String deobf, boolean updateClassViews) { + public static ClassMapping genClassMapping(MappingContext context, String obf, String deobf, + boolean updateClassViews) { if (!Main.getLoadedJar().getClass(obf).isPresent()) { Main.getLogger().warning("Discovered mapping for non-existent class \"" + obf + "\" - ignoring"); return null; @@ -97,7 +98,7 @@ public static ClassMapping genClassMapping(MappingContext context, String obf, S public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, String descriptor) { - genFieldMapping(context, owningClass, obf, deobf, descriptor); + genFieldMapping(context, owningClass, obf, deobf, Type.fromString(descriptor)); } public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, @@ -159,7 +160,8 @@ public static MethodMapping genMethodMapping(MappingContext context, String owni } } - public static void genArgumentMapping(MappingContext context, MethodMapping methodMapping, int index, String deobf) { + public static void genArgumentMapping(MappingContext context, MethodMapping methodMapping, int index, + String deobf) { if (!StringHelper.isJavaIdentifier(deobf)) { Main.getLogger().warning("Discovered argument mapping with illegal name - ignoring"); return; diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java new file mode 100644 index 0000000..418c625 --- /dev/null +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java @@ -0,0 +1,90 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.test.mapping.io.reader; + +import static blue.lapis.nocturne.test.mapping.io.reader.ReaderTestHelper.loadMain; + +import blue.lapis.nocturne.mapping.io.reader.EnigmaReader; +import blue.lapis.nocturne.mapping.io.reader.SrgReader; + +import jdk.nashorn.api.scripting.URLReader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.IOException; + +/** + * Unit tests related to the {@link SrgReader}. + */ +public class EnigmaReaderTest { + + private static ReaderTestHelper helper; + + @BeforeClass + public static void initialize() throws IOException { + loadMain(); + EnigmaReader reader + = new EnigmaReader(new BufferedReader(new URLReader(ClassLoader.getSystemResource("example.eng")))); + helper = new ReaderTestHelper(reader.read()); + } + + @Test + public void classTest() { + helper.classTest(); + } + + @Test + public void innerClassTest() { + helper.innerClassTest(); + } + + @Test + public void innerClassWithoutParentMappingTest() { + helper.innerClassWithoutParentMappingTest(); + } + + @Test + public void fieldTest() { + helper.fieldTest(); + } + + @Test + public void fieldInnerClassTest() { + helper.fieldInnerClassTest(); + } + + @Test + public void methodTest() { + helper.methodTest(); + } + + @Test + public void partialDeobfuscationTest() { + helper.partialDeobfuscationTest(); + } + +} diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java new file mode 100644 index 0000000..9110cf0 --- /dev/null +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java @@ -0,0 +1,152 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.test.mapping.io.reader; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.jar.io.JarLoader; +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Primitive; +import blue.lapis.nocturne.jar.model.attribute.Type; +import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.io.reader.SrgReader; +import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.FieldMapping; +import blue.lapis.nocturne.mapping.model.InnerClassMapping; +import blue.lapis.nocturne.mapping.model.MethodMapping; + +import java.io.IOException; + +/** + * Unit tests related to the {@link SrgReader}. + */ +class ReaderTestHelper { + + private static final String EXAMPLE_PACKAGE = "com/example/project"; + + private MappingContext mappings; + + ReaderTestHelper(MappingContext mappings) { + this.mappings = mappings; + } + + static void loadMain() throws IOException { + new Main(true); + Main.setLoadedJar(JarLoader.loadJar("test.jar", ReaderTestHelper.class.getResourceAsStream("/test.jar"))); + } + + void classTest() { + assertTrue(mappings.getMappings().containsKey("a")); + ClassMapping mapping = mappings.getMappings().get("a"); + assertEquals("a", mapping.getObfuscatedName()); + assertEquals(EXAMPLE_PACKAGE + "/Example", mapping.getDeobfuscatedName()); + } + + void innerClassTest() { + assertTrue(mappings.getMappings().containsKey("a")); + ClassMapping mapping = mappings.getMappings().get("a"); + + assertTrue(mapping.getInnerClassMappings().containsKey("b")); + InnerClassMapping inner = mapping.getInnerClassMappings().get("b"); + + assertEquals("b", inner.getObfuscatedName()); + assertEquals("Inner", inner.getDeobfuscatedName()); + assertEquals(EXAMPLE_PACKAGE + "/Example$Inner", inner.getFullDeobfuscatedName()); + } + + void innerClassWithoutParentMappingTest() { + assertTrue(mappings.getMappings().containsKey("b")); + ClassMapping mapping = mappings.getMappings().get("b"); + + assertTrue(mapping.getInnerClassMappings().containsKey("a")); + InnerClassMapping inner = mapping.getInnerClassMappings().get("a"); + + assertEquals("a", inner.getObfuscatedName()); + assertEquals("Inner", inner.getDeobfuscatedName()); + assertEquals("b$a", inner.getFullObfuscatedName()); + assertEquals("b$Inner", inner.getFullDeobfuscatedName()); + } + + void fieldTest() { + assertTrue(mappings.getMappings().containsKey("a")); + ClassMapping mapping = mappings.getMappings().get("a"); + + assertTrue(mapping.getFieldMappings().containsKey("a")); + FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); + assertEquals("a", fieldMapping.getObfuscatedName()); + assertEquals("someField", fieldMapping.getDeobfuscatedName()); + } + + void fieldInnerClassTest() { + assertTrue(mappings.getMappings().containsKey("a")); + assertTrue(mappings.getMappings().get("a").getInnerClassMappings().containsKey("b")); + + ClassMapping mapping = mappings.getMappings().get("a").getInnerClassMappings().get("b"); + assertTrue(mapping.getFieldMappings().containsKey("a")); + + FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); + assertEquals("a", fieldMapping.getObfuscatedName()); + assertEquals("someInnerField", fieldMapping.getDeobfuscatedName()); + } + + void methodTest() { + assertTrue(mappings.getMappings().containsKey("a")); + ClassMapping mapping = mappings.getMappings().get("a"); + + assertTrue(mapping.getMethodMappings().containsKey("a(ILa;I)La;")); + + MethodMapping methodMapping = mapping.getMethodMappings().get("a(ILa;I)La;"); + assertEquals("a", methodMapping.getObfuscatedName()); + assertEquals("someMethod", methodMapping.getDeobfuscatedName()); + assertArrayEquals( + new Type[]{ + new Type(Primitive.INT, 0), + new Type("a", 0), + new Type(Primitive.INT, 0) + }, + methodMapping.getObfuscatedDescriptor().getParamTypes()); + assertEquals(new Type("a", 0), methodMapping.getObfuscatedDescriptor().getReturnType()); + + MethodDescriptor deobfSig = methodMapping.getDeobfuscatedDescriptor(); + assertArrayEquals( + new Type[]{ + new Type(Primitive.INT, 0), + new Type(EXAMPLE_PACKAGE + "/Example", 0), + new Type(Primitive.INT, 0) + }, + deobfSig.getParamTypes() + ); + assertEquals(new Type(EXAMPLE_PACKAGE + "/Example", 0), deobfSig.getReturnType()); + } + + void partialDeobfuscationTest() { + assertEquals("com/example/project/Example$c", ClassMapping.deobfuscate(mappings, "a$c")); + } + +} diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java index 4a4501c..3872b62 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java @@ -25,24 +25,11 @@ package blue.lapis.nocturne.test.mapping.io.reader; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import blue.lapis.nocturne.Main; -import blue.lapis.nocturne.jar.io.JarLoader; -import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; -import blue.lapis.nocturne.jar.model.attribute.Primitive; -import blue.lapis.nocturne.jar.model.attribute.Type; -import blue.lapis.nocturne.mapping.MappingContext; +import static blue.lapis.nocturne.test.mapping.io.reader.ReaderTestHelper.loadMain; + +import blue.lapis.nocturne.mapping.io.reader.EnigmaReader; import blue.lapis.nocturne.mapping.io.reader.SrgReader; -import blue.lapis.nocturne.mapping.model.ClassMapping; -import blue.lapis.nocturne.mapping.model.FieldMapping; -import blue.lapis.nocturne.mapping.model.InnerClassMapping; -import blue.lapis.nocturne.mapping.model.MethodMapping; -import javafx.application.Application; -import javafx.stage.Stage; import jdk.nashorn.api.scripting.URLReader; import org.junit.BeforeClass; import org.junit.Test; @@ -55,118 +42,49 @@ */ public class SrgReaderTest { - private static final String EXAMPLE_PACKAGE = "com/example/project"; - - private static MappingContext mappings; - - public static class NonApp extends Application { - @Override - public void start(Stage primaryStage) throws Exception { - } - } + private static ReaderTestHelper helper; @BeforeClass - public static void initialize() throws InterruptedException, IOException { - new Main(true); - Main.setLoadedJar(JarLoader.loadJar("test.jar", SrgReaderTest.class.getResourceAsStream("/test.jar"))); + public static void initialize() throws IOException { + loadMain(); SrgReader reader = new SrgReader(new BufferedReader(new URLReader(ClassLoader.getSystemResource("example.srg")))); - mappings = reader.read(); + helper = new ReaderTestHelper(reader.read()); } @Test public void classTest() { - assertTrue(mappings.getMappings().containsKey("a")); - ClassMapping mapping = mappings.getMappings().get("a"); - assertEquals("a", mapping.getObfuscatedName()); - assertEquals(EXAMPLE_PACKAGE + "/Example", mapping.getDeobfuscatedName()); + helper.classTest(); } @Test public void innerClassTest() { - assertTrue(mappings.getMappings().containsKey("a")); - ClassMapping mapping = mappings.getMappings().get("a"); - - assertTrue(mapping.getInnerClassMappings().containsKey("b")); - InnerClassMapping inner = mapping.getInnerClassMappings().get("b"); - - assertEquals("b", inner.getObfuscatedName()); - assertEquals("Inner", inner.getDeobfuscatedName()); - assertEquals(EXAMPLE_PACKAGE + "/Example$Inner", inner.getFullDeobfuscatedName()); + helper.innerClassTest(); } @Test public void innerClassWithoutParentMappingTest() { - assertTrue(mappings.getMappings().containsKey("b")); - ClassMapping mapping = mappings.getMappings().get("b"); - - assertTrue(mapping.getInnerClassMappings().containsKey("a")); - InnerClassMapping inner = mapping.getInnerClassMappings().get("a"); - - assertEquals("a", inner.getObfuscatedName()); - assertEquals("Inner", inner.getDeobfuscatedName()); - assertEquals("b$a", inner.getFullObfuscatedName()); - assertEquals("b$Inner", inner.getFullDeobfuscatedName()); + helper.innerClassWithoutParentMappingTest(); } @Test public void fieldTest() { - assertTrue(mappings.getMappings().containsKey("a")); - ClassMapping mapping = mappings.getMappings().get("a"); - - assertTrue(mapping.getFieldMappings().containsKey("a")); - FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); - assertEquals("a", fieldMapping.getObfuscatedName()); - assertEquals("someField", fieldMapping.getDeobfuscatedName()); + helper.fieldTest(); } @Test public void fieldInnerClassTest() { - assertTrue(mappings.getMappings().containsKey("a")); - assertTrue(mappings.getMappings().get("a").getInnerClassMappings().containsKey("b")); - - ClassMapping mapping = mappings.getMappings().get("a").getInnerClassMappings().get("b"); - assertTrue(mapping.getFieldMappings().containsKey("a")); - - FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); - assertEquals("a", fieldMapping.getObfuscatedName()); - assertEquals("someInnerField", fieldMapping.getDeobfuscatedName()); + helper.fieldInnerClassTest(); } @Test public void methodTest() { - assertTrue(mappings.getMappings().containsKey("a")); - ClassMapping mapping = mappings.getMappings().get("a"); - - assertTrue(mapping.getMethodMappings().containsKey("a(ILa;I)La;")); - - MethodMapping methodMapping = mapping.getMethodMappings().get("a(ILa;I)La;"); - assertEquals("a", methodMapping.getObfuscatedName()); - assertEquals("someMethod", methodMapping.getDeobfuscatedName()); - assertArrayEquals( - new Type[]{ - new Type(Primitive.INT, 0), - new Type("a", 0), - new Type(Primitive.INT, 0) - }, - methodMapping.getObfuscatedDescriptor().getParamTypes()); - assertEquals(new Type("a", 0), methodMapping.getObfuscatedDescriptor().getReturnType()); - - MethodDescriptor deobfSig = methodMapping.getDeobfuscatedDescriptor(); - assertArrayEquals( - new Type[]{ - new Type(Primitive.INT, 0), - new Type(EXAMPLE_PACKAGE + "/Example", 0), - new Type(Primitive.INT, 0) - }, - deobfSig.getParamTypes() - ); - assertEquals(new Type(EXAMPLE_PACKAGE + "/Example", 0), deobfSig.getReturnType()); + helper.methodTest(); } @Test public void partialDeobfuscationTest() { - assertEquals("com/example/project/Example$c", ClassMapping.deobfuscate(mappings, "a$c")); + helper.partialDeobfuscationTest(); } } diff --git a/src/test/resources/example.eng b/src/test/resources/example.eng new file mode 100644 index 0000000..b067943 --- /dev/null +++ b/src/test/resources/example.eng @@ -0,0 +1,7 @@ +CLASS none/a com/example/project/Example + CLASS b Inner + FIELD a someInnerField I + FIELD a someField I + METHOD a someMethod (ILnone/a;I)Lnone/a; +CLASS none/b + CLASS a Inner From 93d65b3b354527776b5a758c95ef36c651f78f1f Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 00:28:54 -0400 Subject: [PATCH 27/58] Fix 'none/' prefixes being inappropriately applied to inner classes --- .../lapis/nocturne/mapping/io/writer/EnigmaWriter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index 9552078..b595330 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -34,6 +34,7 @@ import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; +import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; @@ -63,11 +64,14 @@ public void write(MappingContext mappings) { } protected void writeClassMapping(ClassMapping classMapping, int depth) { + boolean inner = classMapping instanceof InnerClassMapping; if (classMapping.getDeobfuscatedName().equals(classMapping.getObfuscatedName())) { - out.println(getIndentForDepth(depth) + "CLASS " + addNonePrefix(classMapping.getObfuscatedName())); + out.println(getIndentForDepth(depth) + "CLASS " + + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName()))); } else { - out.println(getIndentForDepth(depth) + "CLASS " + addNonePrefix(classMapping.getObfuscatedName()) + " " - + addNonePrefix(classMapping.getDeobfuscatedName())); + out.println(getIndentForDepth(depth) + "CLASS " + + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + " " + + (inner ? classMapping.getDeobfuscatedName() : addNonePrefix(classMapping.getDeobfuscatedName()))); } for (ClassMapping innerClass : classMapping.getInnerClassMappings().values()) { From 9453c8078f624fa1c6106079ddf9299424facf13 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 00:32:28 -0400 Subject: [PATCH 28/58] Clean up imports --- src/main/java/blue/lapis/nocturne/gui/MainController.java | 1 - .../nocturne/gui/io/mappings/MappingsOpenDialogHelper.java | 2 +- .../nocturne/gui/io/mappings/MappingsSaveDialogHelper.java | 3 +-- .../blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java | 2 -- .../lapis/nocturne/mapping/io/reader/MappingReaderType.java | 2 -- .../processor/index/model/signature/FieldSignature.java | 1 - .../processor/index/model/signature/MethodSignature.java | 1 - .../java/blue/lapis/nocturne/util/helper/MappingsHelper.java | 4 +--- .../lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java | 1 - 9 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index 8b4be0a..3cb5a0d 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -47,7 +47,6 @@ import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.Alert; -import javafx.scene.control.Dialog; import javafx.scene.control.MenuItem; import javafx.scene.control.RadioMenuItem; import javafx.scene.control.TabPane; diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index 0abf501..4d76c03 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -31,13 +31,13 @@ import blue.lapis.nocturne.mapping.io.reader.MappingReaderType; import blue.lapis.nocturne.mapping.io.reader.MappingsReader; import blue.lapis.nocturne.util.helper.PropertiesHelper; + import javafx.stage.FileChooser; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java index 7416e04..937b635 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java @@ -26,11 +26,10 @@ package blue.lapis.nocturne.gui.io.mappings; import blue.lapis.nocturne.Main; -import blue.lapis.nocturne.mapping.io.MappingFormatType; -import blue.lapis.nocturne.mapping.io.reader.MappingReaderType; import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; import blue.lapis.nocturne.mapping.io.writer.MappingsWriter; import blue.lapis.nocturne.util.helper.PropertiesHelper; + import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 5c14e2c..5c60de9 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -27,7 +27,6 @@ import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_PATTERN; import static blue.lapis.nocturne.util.Constants.ENIGMA_ROOT_PACKAGE_PREFIX; -import static javax.swing.text.html.HTML.Tag.HEAD; import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; @@ -35,7 +34,6 @@ import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; -import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java index fd07d29..4b454ce 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java @@ -27,8 +27,6 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.mapping.io.MappingFormatType; -import blue.lapis.nocturne.mapping.io.writer.EnigmaWriter; -import blue.lapis.nocturne.mapping.io.writer.SrgWriter; import com.google.common.collect.Maps; import javafx.stage.FileChooser; diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java index 4335917..fb615a1 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java @@ -26,7 +26,6 @@ package blue.lapis.nocturne.processor.index.model.signature; import blue.lapis.nocturne.jar.model.attribute.Type; -import blue.lapis.nocturne.processor.index.model.IndexedField; import java.util.Objects; diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java index a18df7f..20461ff 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/MethodSignature.java @@ -26,7 +26,6 @@ package blue.lapis.nocturne.processor.index.model.signature; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; -import blue.lapis.nocturne.processor.index.model.IndexedMethod; import java.util.Objects; diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 4a376b1..7cc2927 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -27,7 +27,6 @@ import static blue.lapis.nocturne.util.Constants.INNER_CLASS_SEPARATOR_CHAR; import static blue.lapis.nocturne.util.Constants.INNER_CLASS_SEPARATOR_PATTERN; -import static javax.swing.text.html.HTML.Tag.HEAD; import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; @@ -45,7 +44,6 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Static utility class for assisting with mapping retrieval and creation. @@ -177,7 +175,7 @@ public static void genArgumentMapping(MappingContext context, MethodMapping meth } private static Optional getClassMapping(MappingContext context, String qualifiedName, - boolean create) { + boolean create) { String[] arr = INNER_CLASS_SEPARATOR_PATTERN.split(qualifiedName); ClassMapping mapping = context.getMappings().get(arr[0]); diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java index 3872b62..9c99747 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java @@ -27,7 +27,6 @@ import static blue.lapis.nocturne.test.mapping.io.reader.ReaderTestHelper.loadMain; -import blue.lapis.nocturne.mapping.io.reader.EnigmaReader; import blue.lapis.nocturne.mapping.io.reader.SrgReader; import jdk.nashorn.api.scripting.URLReader; From 6f910ddd73aaf731d5669757f1b93ff1e0f2bbdb Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 21:27:50 -0400 Subject: [PATCH 29/58] Fix EnigmaReader --- .../mapping/io/reader/EnigmaReader.java | 35 +++++++++++-------- .../nocturne/util/helper/MappingsHelper.java | 2 +- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 5c60de9..29fa70b 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -27,16 +27,19 @@ import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_PATTERN; import static blue.lapis.nocturne.util.Constants.ENIGMA_ROOT_PACKAGE_PREFIX; +import static blue.lapis.nocturne.util.Constants.INNER_CLASS_SEPARATOR_CHAR; import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; +import java.util.Stack; import java.util.stream.Collectors; /** @@ -57,9 +60,10 @@ public EnigmaReader(BufferedReader reader) { public MappingContext read() { MappingContext mappings = new MappingContext(); - ClassMapping currentClass = null; + Stack classStack = new Stack<>(); MethodMapping currentMethod = null; int lineNum = 0; + int lastIndentLevel = -1; for (String line : reader.lines().collect(Collectors.toList())) { lineNum++; @@ -87,6 +91,10 @@ public MappingContext read() { indentLevel++; } + if (lastIndentLevel != -1 && indentLevel < lastIndentLevel) { + classStack.pop(); + } + switch (arr[0]) { case CLASS_MAPPING_KEY: { if (arr.length < 2 || arr.length > 3) { @@ -97,16 +105,11 @@ public MappingContext read() { String obf = removeNonePrefix(arr[1]); String deobf = arr.length == 3 ? removeNonePrefix(arr[2]) : obf; - if (indentLevel != 0) { - if (currentClass == null) { - throw new IllegalArgumentException("Cannot parse file: found field mapping before initial " - + "class mapping on line " + lineNum); - } - obf = currentClass.getFullObfuscatedName() + "$" + obf; - deobf = currentClass.getFullDeobfuscatedName() + "$" + deobf; + if (lastIndentLevel != -1 && indentLevel > lastIndentLevel) { + obf = classStack.peek().getFullObfuscatedName() + INNER_CLASS_SEPARATOR_CHAR + obf; + deobf = classStack.peek().getFullDeobfuscatedName() + INNER_CLASS_SEPARATOR_CHAR + deobf; } - - currentClass = MappingsHelper.genClassMapping(mappings, obf, deobf, false); + classStack.push(MappingsHelper.genClassMapping(mappings, obf, deobf, false)); currentMethod = null; break; } @@ -116,7 +119,7 @@ public MappingContext read() { + lineNum); } - if (currentClass == null) { + if (classStack.isEmpty()) { throw new IllegalArgumentException("Cannot parse file: found field mapping before initial " + "class mapping on line " + lineNum); } @@ -124,12 +127,13 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; Type type = removeNonePrefix(Type.fromString(arr[3])); - MappingsHelper.genFieldMapping(mappings, currentClass.getFullObfuscatedName(), obf, deobf, type); + MappingsHelper.genFieldMapping(mappings, classStack.peek().getFullObfuscatedName(), obf, deobf, + type); currentMethod = null; break; } case METHOD_MAPPING_KEY: { - if (currentClass == null) { + if (classStack.isEmpty()) { throw new IllegalArgumentException("Cannot parse file: found method mapping before initial " + "class mapping on line " + lineNum); } @@ -150,8 +154,8 @@ public MappingContext read() { MethodDescriptor desc = removeNonePrefixes(MethodDescriptor.fromString(descStr)); - currentMethod = MappingsHelper.genMethodMapping(mappings, currentClass.getFullObfuscatedName(), obf, - deobf, desc, true); + currentMethod = MappingsHelper.genMethodMapping(mappings, classStack.peek().getFullObfuscatedName(), + obf, deobf, desc, true); break; } case ARG_MAPPING_KEY: { @@ -175,6 +179,7 @@ public MappingContext read() { Main.getLogger().warning("Unrecognized mapping on line " + lineNum); } } + lastIndentLevel = indentLevel; } return mappings; diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 7cc2927..0121dd7 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -64,7 +64,7 @@ public static ClassMapping genClassMapping(MappingContext context, String obf, S String[] obfSplit = INNER_CLASS_SEPARATOR_PATTERN.split(obf); String[] deobfSplit = INNER_CLASS_SEPARATOR_PATTERN.split(deobf); if (obfSplit.length != deobfSplit.length) { // non-inner mapped to inner or vice versa - Main.getLogger().warning("Unsupported mapping: " + obf + " <-> " + deobf); + Main.getLogger().warning("Unsupported mapping: " + obf + " -> " + deobf); return null; // ignore it } From 6c75a570ccb922982a696e2ec5b3ccc15f9f4fff Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 21:55:20 -0400 Subject: [PATCH 30/58] Fix inner class mapping inference validation --- .../nocturne/util/helper/MappingsHelper.java | 29 +++++++++++++++++-- .../mapping/io/reader/ReaderTestHelper.java | 2 +- src/test/resources/example.eng | 2 +- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 0121dd7..cfdb282 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -72,6 +72,31 @@ public static ClassMapping genClassMapping(MappingContext context, String obf, S ClassMapping parent = getOrCreateClassMapping(context, obf.substring(0, obf.lastIndexOf(INNER_CLASS_SEPARATOR_CHAR))); + // atomic validation pass + ClassMapping next = parent; + for (int i = deobfSplit.length - 2; i >= 0; i--) { + if (!next.getObfuscatedName().equals(next.getDeobfuscatedName()) + && !next.getDeobfuscatedName().equals(deobfSplit[i])) { + Main.getLogger().warning("Nonsense mapping " + obf + " -> " + deobf + + " - conflicts with outer class mapping. Ignoring..."); + return null; + } + if (next instanceof InnerClassMapping) { + next = ((InnerClassMapping) next).getParent(); + } + } + + // application pass + next = parent; + for (int i = deobfSplit.length - 2; i >= 0; i--) { + if (next.getObfuscatedName().equals(next.getDeobfuscatedName())) { + next.setDeobfuscatedName(deobfSplit[i]); + } + if (next instanceof InnerClassMapping) { + next = ((InnerClassMapping) next).getParent(); + } + } + String baseObfName = obfSplit[obfSplit.length - 1]; String baseDeobfname = deobfSplit[deobfSplit.length - 1]; if (parent.getInnerClassMappings().containsKey(baseObfName)) { @@ -165,8 +190,8 @@ public static void genArgumentMapping(MappingContext context, MethodMapping meth return; } - Optional mapping = methodMapping.getArgumentMappings().values().stream().filter( - argumentMapping -> argumentMapping.getIndex() == index).findFirst(); + Optional mapping = methodMapping.getArgumentMappings().values().stream() + .filter(argumentMapping -> argumentMapping.getIndex() == index).findFirst(); if (mapping.isPresent()) { mapping.get().setDeobfuscatedName(deobf); } else { diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java index 9110cf0..4f044c0 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java @@ -90,7 +90,7 @@ void innerClassWithoutParentMappingTest() { assertEquals("a", inner.getObfuscatedName()); assertEquals("Inner", inner.getDeobfuscatedName()); assertEquals("b$a", inner.getFullObfuscatedName()); - assertEquals("b$Inner", inner.getFullDeobfuscatedName()); + assertEquals("com/example/project/Another$Inner", inner.getFullDeobfuscatedName()); } void fieldTest() { diff --git a/src/test/resources/example.eng b/src/test/resources/example.eng index b067943..21609e0 100644 --- a/src/test/resources/example.eng +++ b/src/test/resources/example.eng @@ -3,5 +3,5 @@ CLASS none/a com/example/project/Example FIELD a someInnerField I FIELD a someField I METHOD a someMethod (ILnone/a;I)Lnone/a; -CLASS none/b +CLASS none/b com/example/project/Another CLASS a Inner From 92657c664e27a59df414f6d816c88f62295acf77 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 22:28:21 -0400 Subject: [PATCH 31/58] Make reader tests more robust --- .../mapping/io/reader/EnigmaReaderTest.java | 10 +++++++ .../mapping/io/reader/ReaderTestHelper.java | 28 ++++++++++++++++++ .../test/mapping/io/reader/SrgReaderTest.java | 10 +++++++ src/test/resources/example.eng | 3 ++ src/test/resources/example.srg | 5 ++-- src/test/resources/test.jar | Bin 1615 -> 2869 bytes 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java index 418c625..fc45fb6 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java @@ -67,6 +67,11 @@ public void innerClassWithoutParentMappingTest() { helper.innerClassWithoutParentMappingTest(); } + @Test + public void nestedInnerClassWithoutParentMappingTest() { + helper.nestedInnerClassWithoutParentMappingTest(); + } + @Test public void fieldTest() { helper.fieldTest(); @@ -77,6 +82,11 @@ public void fieldInnerClassTest() { helper.fieldInnerClassTest(); } + @Test + public void fieldNestedInnerClassTest() { + helper.fieldNestedInnerClassTest(); + } + @Test public void methodTest() { helper.methodTest(); diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java index 4f044c0..7ced1b1 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java @@ -93,6 +93,21 @@ void innerClassWithoutParentMappingTest() { assertEquals("com/example/project/Another$Inner", inner.getFullDeobfuscatedName()); } + void nestedInnerClassWithoutParentMappingTest() { + assertTrue(mappings.getMappings().containsKey("b")); + ClassMapping mapping = mappings.getMappings().get("b"); + + assertTrue(mapping.getInnerClassMappings().containsKey("a")); + InnerClassMapping inner = mapping.getInnerClassMappings().get("a"); + assertTrue(inner.getInnerClassMappings().containsKey("c")); + InnerClassMapping deeper = inner.getInnerClassMappings().get("c"); + + assertEquals("c", deeper.getObfuscatedName()); + assertEquals("Deeper", deeper.getDeobfuscatedName()); + assertEquals("b$a$c", deeper.getFullObfuscatedName()); + assertEquals("com/example/project/Another$Inner$Deeper", deeper.getFullDeobfuscatedName()); + } + void fieldTest() { assertTrue(mappings.getMappings().containsKey("a")); ClassMapping mapping = mappings.getMappings().get("a"); @@ -115,6 +130,19 @@ void fieldInnerClassTest() { assertEquals("someInnerField", fieldMapping.getDeobfuscatedName()); } + void fieldNestedInnerClassTest() { + assertTrue(mappings.getMappings().containsKey("a")); + assertTrue(mappings.getMappings().get("a").getInnerClassMappings().containsKey("b")); + ClassMapping inner = mappings.getMappings().get("a").getInnerClassMappings().get("b"); + assertTrue(inner.getInnerClassMappings().containsKey("c")); + ClassMapping deeper = inner.getInnerClassMappings().get("c"); + assertTrue(deeper.getFieldMappings().containsKey("a")); + + FieldMapping fieldMapping = deeper.getFieldMappings().get("a"); + assertEquals("a", fieldMapping.getObfuscatedName()); + assertEquals("someDeeperField", fieldMapping.getDeobfuscatedName()); + } + void methodTest() { assertTrue(mappings.getMappings().containsKey("a")); ClassMapping mapping = mappings.getMappings().get("a"); diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java index 9c99747..7aaaae8 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java @@ -66,6 +66,11 @@ public void innerClassWithoutParentMappingTest() { helper.innerClassWithoutParentMappingTest(); } + @Test + public void nestedInnerClassWithoutParentMappingTest() { + helper.nestedInnerClassWithoutParentMappingTest(); + } + @Test public void fieldTest() { helper.fieldTest(); @@ -76,6 +81,11 @@ public void fieldInnerClassTest() { helper.fieldInnerClassTest(); } + @Test + public void fieldNestedInnerClassTest() { + helper.fieldNestedInnerClassTest(); + } + @Test public void methodTest() { helper.methodTest(); diff --git a/src/test/resources/example.eng b/src/test/resources/example.eng index 21609e0..a4eb5f1 100644 --- a/src/test/resources/example.eng +++ b/src/test/resources/example.eng @@ -1,7 +1,10 @@ CLASS none/a com/example/project/Example CLASS b Inner + CLASS c Deeper + FIELD a someDeeperField I FIELD a someInnerField I FIELD a someField I METHOD a someMethod (ILnone/a;I)Lnone/a; CLASS none/b com/example/project/Another CLASS a Inner + CLASS c Deeper diff --git a/src/test/resources/example.srg b/src/test/resources/example.srg index ae539c1..e23269c 100644 --- a/src/test/resources/example.srg +++ b/src/test/resources/example.srg @@ -1,7 +1,8 @@ -# This is a comment, to check the reader doesn't read them. CL: a com/example/project/Example CL: a$b com/example/project/Example$Inner -CL: b$a com/example/project/Another$Inner +CL: a$b$c com/example/project/Example$Inner$Deeper +CL: b$a$c com/example/project/Another$Inner$Deeper FD: a/a com/example/project/Example/someField FD: a$b/a com/example/project/Example$Inner/someInnerField +FD: a$b$c/a com/example/project/Example$Inner$Deeper/someDeeperField MD: a/a (ILa;I)La; com/example/project/Example/someMethod (ILcom/example/project/Example;I)Lcom/example/project/Example; diff --git a/src/test/resources/test.jar b/src/test/resources/test.jar index 1350c4e7e9b3f94aa88052f8e60d3921613fec92..27fb635e134461fbb8aa8c6f1e9ac56aff52f60c 100644 GIT binary patch literal 2869 zcmZ{l3p~^7AIE>o#tfNz&RkYD)L{(AWh%MWVk5U>osN5?P!vVU{?oFQ^w$N)+*Oh~ zxfEr1rHFDc-H661t+_QsItu4ERKL~hJbOK_?`zxddGGst_Iy5%o3jL582|tzkaUz8igNNG6|2t>)8j4M&mY#d8DX}TqU-Z1h$v(B zYlh#r_LwUQ8eMa`JXwZ$CYQ96Uc60`8Jm~%Jbd@$_RdRZ`0E89bZY{`^K8aH z+Bs}WH#6@uUQ_qsgl5GEpRr-M|FiAv!uZi@3u&Uip1VyqNi$lKTQnp6!c*n4W{ae_ zEJW*+$337NnxHIFB3YJ1`JGx$U16)texO+$pUZfW<&)_{XPU+Sgi$=}%u@a7Q*{k- zb36XFM1#yaMbt)m+L|`s68+c^9w+YX%XiN(fNKp^pIEk$m8$;Y$_iyiw%SG7lwlv~W-6TZ zKdzG2F3-h8YoLOo&Yh&ib3G3Vu;(m%F%?qZcAo+IF>p#Q?tXVbYydO0 z4n;SXJ$CT!!IqMN!mF-lFRWy`ZB5)!ER5`}V(1@&r)$hanWMTCaRoE%;6eb#}_N=NJ2Ao`h!q{9@3P)lNU*AV=kBMHK4frBaU6`SkSIY?rP5W2puo_Py*ZE z&f13x3iE9LrWd&AZ+-W=HOcZyRbtNi%-e>&%E=7Y%2)bj3Q0j5t@-k}4tp1W1EySH z^EWyKQFJZgY8qohv8PUjW(!JO6WDm^DFLX-nq|*| znk;*k3Wk{*njO(~{}LEx37*jR(fBReY}2Pzo-q-_tCHEOjFNwD#2m#VLuQXp zJ|p$^{r^-+hacka0}~-C-~TItFO8cmjb zO3wQzeh&Fc-={%x2Zf8gV>Zc<(OIxFqpDj4$G4g!Hkx{Cul;2HRGnmiRrmY6skuRL zq}tkgR6*gI%`T$7gGM@{+dd=G?)8 zm#R;qZ(a0|+EsG6O z)SiZUr)iEKOCr+pZNBY{F7lxq^{ENCqhG-(@?juBzgj%$?_FpO=XC-&2PGbM}IjvBU=kwq9Tzqf^dw~Ae^koz4}YVkuDunGW#Si4umfqFeqA9CT9`({5)H%evcNvSDjOcrMOvJE$b0f0QlZ=*^B2mk1-XzkhQdk4xr-{izq8czm-;*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48Bt5`TA zUPvC9JzFE=hq$WR^Cemq&&5Tbh^tOxn40~m=wlHh*b#qyBmJC#R=5B$Zbz^KWfS$1 za}tY-WBoSzF*%CNVL!fh&T@q^H4!zD1jgREN7{}&5mIVB_D?tO#KdCHcMb0^ojTIQ z|6noCW^wKAxiii4@1^wbw`XVgzQgZ=%k={iF_K?cl2|jJ?bS|i4V$_;Lo;5jWBJbW z+xwfI6?{?aNSj@*{^CsW`+4Q^*QTz|;{q*KLUj543G1z92tB^Vqut!S z{{^ol7we~=`r;eEY+Cp3f@7@Q9BJDF-U;RmEY^Ve(6QsLT=Aj-#;ldvD-Jud(GiJJ^QX? z-I;y&_rI5C5S~*ixM;eP)4T@;2Rj|67>ge{yL#>K>rDjQ^T>g!_?(oTH=VoSw zWyQ{pnowO4v#MIsUL<>S)(O5g?>WWiJG9wtWREz^`|YN-CNbCR?$X^EoC>nBbxv;a z9ClG^i;wNu%XTAs_P4?}p34;Z3Rr%!g966!d{*Qmptr^G1`H^bz=Oq>>yU#$>wOiq zixR#z4Xp_a#g=Upncbk!A=dRbFGfW%Pr?4)X|D|*805U>q;yH{`+kq-^WVMp3}F&G z4GaqmN*-8qaHw$H^UDr(nW^C&D)gpw(c~;=gY?hb3x%JCyMFlI8P@(wFSJn1DEX-E z(^A3JxtAJrr?0Hw;OE;_6DriycG%}dbj6gFUD|dU%bA2F{x}EE$$oUF+UM~!#_W$w zw$Znr=51H{7&L!5W54Kz!~KSl3+zE&T|SjHd>hascYqjoh5)63Bo%0ukoEJ;270zO z`O=zY8;`BO7i|;K`f8!Mw|ee)YzP1)dzA=AN{2ZZZ#6o;Ls3tUukJ)4$#}KPWG6HY;GZ%Jbb5M1$nugysgehwv$EiAY81edBbS}b0<)k;>~=yZu&$K1*Z z9=m0AuEeb`{#JI^G^paCd~MzIM>leddz=@X*?Q=es4Abro3Hu{?ujlfe#p6#tw-Zo zKdW1Yg?hQ|l>qj?%%A}2DtiC)7SOxg;J9aG5@A3s}L$SD~Vi3o5W=s$S2M%RX%Dp2iu0rWpK h(W7fZ4mni2E;Az~p8#)GHjp#efG`y3h$rB11OVke7{LGl From 4acd2370e1800567f0881d7019fef6cc3fa368f0 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 17 Aug 2016 22:49:11 -0400 Subject: [PATCH 32/58] Attempt to fix semi-rare NPE on mappings load --- .../blue/lapis/nocturne/mapping/model/InnerClassMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/InnerClassMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/InnerClassMapping.java index 1decc54..9690273 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/InnerClassMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/InnerClassMapping.java @@ -107,7 +107,7 @@ public void setDeobfuscatedName(String deobf) { return; } - super.setDeobfuscatedName(deobf); + super.setDeobfuscatedName(deobf, false); } @Override From 1d6a623f200b45443dae6aad079496fbdb050e3f Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Thu, 18 Aug 2016 00:43:23 -0400 Subject: [PATCH 33/58] Implement support for JAM 2.0 --- .../mapping/io/MappingFormatType.java | 1 + .../mapping/io/reader/EnigmaReader.java | 13 +- .../nocturne/mapping/io/reader/JamReader.java | 173 ++++++++++++++++++ .../mapping/io/reader/MappingReaderType.java | 1 + .../nocturne/mapping/io/reader/SrgReader.java | 27 ++- .../mapping/io/writer/EnigmaWriter.java | 11 +- .../nocturne/mapping/io/writer/JamWriter.java | 144 +++++++++++++++ .../mapping/io/writer/MappingWriterType.java | 1 + .../nocturne/mapping/model/FieldMapping.java | 4 +- .../nocturne/mapping/model/MethodMapping.java | 14 +- ...pping.java => MethodParameterMapping.java} | 11 +- .../blue/lapis/nocturne/util/Constants.java | 2 + .../nocturne/util/helper/MappingsHelper.java | 6 +- src/main/resources/lang/de_DE.properties | 1 + src/main/resources/lang/en_US.properties | 1 + .../mapping/io/reader/EnigmaReaderTest.java | 3 +- .../test/mapping/io/reader/JamReaderTest.java | 101 ++++++++++ .../test/mapping/io/reader/SrgReaderTest.java | 3 +- src/test/resources/{ => mappings}/example.eng | 0 src/test/resources/mappings/example.jam | 8 + src/test/resources/{ => mappings}/example.srg | 0 21 files changed, 495 insertions(+), 30 deletions(-) create mode 100644 src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java create mode 100644 src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java rename src/main/java/blue/lapis/nocturne/mapping/model/{ArgumentMapping.java => MethodParameterMapping.java} (89%) create mode 100644 src/test/java/blue/lapis/nocturne/test/mapping/io/reader/JamReaderTest.java rename src/test/resources/{ => mappings}/example.eng (100%) create mode 100644 src/test/resources/mappings/example.jam rename src/test/resources/{ => mappings}/example.srg (100%) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java index 54e3288..77f15b6 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/MappingFormatType.java @@ -27,6 +27,7 @@ public enum MappingFormatType { SRG("srg"), + JAM("jam"), ENIGMA("*"); private final String extension; diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 29fa70b..9090cbb 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -34,7 +34,6 @@ import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; -import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.util.helper.MappingsHelper; @@ -114,6 +113,10 @@ public MappingContext read() { break; } case FIELD_MAPPING_KEY: { + if (classStack.peek() == null) { + continue; + } + if (arr.length != 4) { throw new IllegalArgumentException("Cannot parse file: malformed field mapping on line " + lineNum); @@ -133,6 +136,10 @@ public MappingContext read() { break; } case METHOD_MAPPING_KEY: { + if (classStack.peek() == null) { + continue; + } + if (classStack.isEmpty()) { throw new IllegalArgumentException("Cannot parse file: found method mapping before initial " + "class mapping on line " + lineNum); @@ -159,6 +166,10 @@ public MappingContext read() { break; } case ARG_MAPPING_KEY: { + if (classStack.peek() == null) { + continue; + } + if (arr.length != 3) { throw new IllegalArgumentException("Cannot parse file: malformed argument mapping on line " + lineNum); diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java new file mode 100644 index 0000000..4bed4d8 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java @@ -0,0 +1,173 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.io.reader; + +import static blue.lapis.nocturne.util.Constants.SPACE_PATTERN; + +import blue.lapis.nocturne.Main; +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.util.helper.MappingsHelper; + +import java.io.BufferedReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * The mappings reader, for the SRG format. + */ +public class JamReader extends MappingsReader { + + private static final String CLASS_MAPPING_KEY = "CL"; + private static final String FIELD_MAPPING_KEY = "FD"; + private static final String METHOD_MAPPING_KEY = "MD"; + private static final String PARAM_MAPPING_KEY = "MP"; + + private static final int CLASS_MAPPING_ELEMENT_COUNT = 3; + private static final int FIELD_MAPPING_ELEMENT_COUNT = 5; + private static final int METHOD_MAPPING_ELEMENT_COUNT = 5; + private static final int PARAM_MAPPING_ELEMENT_COUNT = 7; + + public JamReader(BufferedReader reader) { + super(reader); + } + + @Override + public MappingContext read() { + MappingContext mappings = new MappingContext(); + + Pattern spacePattern = Pattern.compile(" ", Pattern.LITERAL); + List rawClassMappings = new ArrayList<>(); + List rawFieldMappings = new ArrayList<>(); + List rawMethodMappings = new ArrayList<>(); + List rawParamMappings = new ArrayList<>(); + + for (String line : reader.lines().collect(Collectors.toList())) { + String trim = line.trim(); + if (trim.charAt(0) == '#' || trim.isEmpty()) { + continue; + } + + if (line.length() < 4) { + Main.getLogger().warning("Found bogus line in mappings file - ignoring"); + continue; + } + + int len = spacePattern.split(line).length; + + String key = line.substring(0, 2); + if (key.equals(CLASS_MAPPING_KEY) && len == CLASS_MAPPING_ELEMENT_COUNT) { + rawClassMappings.add(line); + } else if (key.equals(FIELD_MAPPING_KEY) && len == FIELD_MAPPING_ELEMENT_COUNT) { + rawFieldMappings.add(line); + } else if (key.equals(METHOD_MAPPING_KEY) && len == METHOD_MAPPING_ELEMENT_COUNT) { + rawMethodMappings.add(line); + } else if (key.equals(PARAM_MAPPING_KEY) && len == PARAM_MAPPING_ELEMENT_COUNT) { + rawParamMappings.add(line); + } else { + Main.getLogger().warning("Discovered unrecognized key \"" + key + "\" in mappings file - ignoring"); + } + } + + // we need to sort the class mappings in order of ascending nesting level + rawClassMappings.sort((s1, s2) -> getClassNestingLevel(s1) - getClassNestingLevel(s2)); + + genClassMappings(mappings, rawClassMappings); + genFieldMappings(mappings, rawFieldMappings); + genMethodMappings(mappings, rawMethodMappings); + genMethodParamMappings(mappings, rawParamMappings); + + return mappings; + } + + private void genClassMappings(MappingContext context, List classMappings) { + for (String mapping : classMappings) { + String[] arr = SPACE_PATTERN.split(mapping); + String obf = arr[1]; + String deobf = arr[2]; + MappingsHelper.genClassMapping(context, obf, deobf, false); + } + } + + private void genFieldMappings(MappingContext context, List fieldMappings) { + for (String mapping : fieldMappings) { + String[] arr = SPACE_PATTERN.split(mapping); + String owningClass = arr[1]; + String obf = arr[2]; + String desc = arr[3]; + String deobf = arr[4]; + MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, desc); + } + } + + private void genMethodMappings(MappingContext context, List methodMappings) { + for (String mapping : methodMappings) { + String[] arr = SPACE_PATTERN.split(mapping); + String owningClass = arr[1]; + String obf = arr[2]; + String desc = arr[3]; + String deobf = arr[4]; + MappingsHelper.genMethodMapping(context, owningClass, obf, deobf, desc, false); + } + } + + private void genMethodParamMappings(MappingContext context, List paramMappings) { + for (String mapping : paramMappings) { + String[] arr = SPACE_PATTERN.split(mapping); + String owningClass = arr[1]; + String owningMethod = arr[2]; + String owningMethodDesc = arr[3]; //TODO: *stretching collar* oooooh... + Optional classMapping = MappingsHelper.getClassMapping(context, owningClass); + if (!classMapping.isPresent()) { + Main.getLogger().warning("Discovered orphaned method parameter mapping (class) - ignoring"); + continue; + } + MethodMapping methodMapping = classMapping.get().getMethodMappings() + .get(owningMethod); + if (methodMapping == null) { + methodMapping = new MethodMapping(classMapping.get(), owningMethod, owningMethod, + MethodDescriptor.fromString(owningMethodDesc), false); + } + int index; + try { + index = Integer.parseInt(arr[4]); + } catch (NumberFormatException ex) { + Main.getLogger().warning("Discovered invalid method parameter mapping (index) - ignoring"); + continue; + } + + String deobf = arr[5]; + + MappingsHelper.genArgumentMapping(context, methodMapping, index, deobf); + } + } + +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java index 4b454ce..cf70b97 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/MappingReaderType.java @@ -40,6 +40,7 @@ public enum MappingReaderType { SRG(MappingFormatType.SRG, SrgReader.class), + JAM(MappingFormatType.JAM, JamReader.class), ENIGMA(MappingFormatType.ENIGMA, EnigmaReader.class); private final MappingFormatType type; diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java index bbb9d42..931b41b 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java @@ -27,6 +27,7 @@ import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_CHAR; +import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.util.helper.MappingsHelper; @@ -42,9 +43,9 @@ */ public class SrgReader extends MappingsReader { - private static final String CLASS_MAPPING_KEY = "CL: "; - private static final String FIELD_MAPPING_KEY = "FD: "; - private static final String METHOD_MAPPING_KEY = "MD: "; + private static final String CLASS_MAPPING_KEY = "CL:"; + private static final String FIELD_MAPPING_KEY = "FD:"; + private static final String METHOD_MAPPING_KEY = "MD:"; private static final int CLASS_MAPPING_ELEMENT_COUNT = 3; private static final int FIELD_MAPPING_ELEMENT_COUNT = 3; @@ -64,13 +65,27 @@ public MappingContext read() { List rawMethodMappings = new ArrayList<>(); for (String line : reader.lines().collect(Collectors.toList())) { + String trim = line.trim(); + if (trim.charAt(0) == '#' || trim.isEmpty()) { + continue; + } + + if (line.length() < 4) { + Main.getLogger().warning("Found bogus line in mappings file - ignoring"); + continue; + } + int len = spacePattern.split(line).length; - if (line.startsWith(CLASS_MAPPING_KEY) && len == CLASS_MAPPING_ELEMENT_COUNT) { + + String key = line.substring(0, 3); + if (key.equals(CLASS_MAPPING_KEY) && len == CLASS_MAPPING_ELEMENT_COUNT) { rawClassMappings.add(line); - } else if (line.startsWith(FIELD_MAPPING_KEY) && len == FIELD_MAPPING_ELEMENT_COUNT) { + } else if (key.equals(FIELD_MAPPING_KEY) && len == FIELD_MAPPING_ELEMENT_COUNT) { rawFieldMappings.add(line); - } else if (line.startsWith(METHOD_MAPPING_KEY) && len == METHOD_MAPPING_ELEMENT_COUNT) { + } else if (key.equals(METHOD_MAPPING_KEY) && len == METHOD_MAPPING_ELEMENT_COUNT) { rawMethodMappings.add(line); + } else { + Main.getLogger().warning("Discovered unrecognized key \"" + key + "\" in mappings file - ignoring"); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index b595330..f7e37fd 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -31,11 +31,11 @@ import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; -import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.mapping.model.MethodParameterMapping; import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; import java.io.PrintWriter; @@ -89,7 +89,8 @@ protected void writeClassMapping(ClassMapping classMapping, int depth) { protected void writeFieldMapping(FieldMapping fieldMapping, int depth) { out.println(getIndentForDepth(depth) + "FIELD " + fieldMapping.getObfuscatedName() + " " - + fieldMapping.getDeobfuscatedName() + " " + addNonePrefix(fieldMapping.getType()).toString()); + + fieldMapping.getDeobfuscatedName() + " " + + addNonePrefix(fieldMapping.getObfuscatedType()).toString()); } protected void writeMethodMapping(MethodMapping methodMapping, int depth) { @@ -102,12 +103,12 @@ protected void writeMethodMapping(MethodMapping methodMapping, int depth) { + addNonePrefixes(methodMapping.getObfuscatedDescriptor()).toString()); } - for (ArgumentMapping argumentMapping : methodMapping.getArgumentMappings().values()) { - writeArgumentMapping(argumentMapping, depth + 1); + for (MethodParameterMapping methodParameterMapping : methodMapping.getParamMappings().values()) { + writeArgumentMapping(methodParameterMapping, depth + 1); } } - protected void writeArgumentMapping(ArgumentMapping argMapping, int depth) { + protected void writeArgumentMapping(MethodParameterMapping argMapping, int depth) { out.println(getIndentForDepth(depth) + "ARG " + argMapping.getIndex() + " " + argMapping.getDeobfuscatedName()); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java new file mode 100644 index 0000000..6164de4 --- /dev/null +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java @@ -0,0 +1,144 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.mapping.io.writer; + +import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.FieldMapping; +import blue.lapis.nocturne.mapping.model.Mapping; +import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.mapping.model.MethodParameterMapping; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.function.Predicate; + +/** + * The mappings writer, for the SRG format. + */ +public class JamWriter extends MappingsWriter { + + private static final Predicate NOT_USELESS + = mapping -> !mapping.getObfuscatedName().equals(mapping.getDeobfuscatedName()); + + private final ByteArrayOutputStream clOut = new ByteArrayOutputStream(); + private final ByteArrayOutputStream fdOut = new ByteArrayOutputStream(); + private final ByteArrayOutputStream mdOut = new ByteArrayOutputStream(); + private final ByteArrayOutputStream mpOut = new ByteArrayOutputStream(); + + private final PrintWriter clWriter = new PrintWriter(clOut); + private final PrintWriter fdWriter = new PrintWriter(fdOut); + private final PrintWriter mdWriter = new PrintWriter(mdOut); + private final PrintWriter mpWriter = new PrintWriter(mpOut); + + /** + * Constructs a new {@link JamWriter} which outputs to the given + * {@link PrintWriter}. + * + * @param out The {@link PrintWriter} to output to + */ + public JamWriter(PrintWriter out) { + super(out); + } + + @Override + public void write(MappingContext mappingContext) { + mappingContext.getMappings().values().forEach(this::writeClassMapping); + clWriter.close(); + fdWriter.close(); + mdWriter.close(); + mpWriter.close(); + out.write(clOut.toString()); + out.write(fdOut.toString()); + out.write(mdOut.toString()); + out.write(mpOut.toString()); + out.close(); + try { + clOut.close(); + fdOut.close(); + mdOut.close(); + mpOut.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Writes the given {@link ClassMapping} to the {@link JamWriter}'s + * {@link PrintWriter}. + * + * @param classMapping The {@link ClassMapping} to write + */ + protected void writeClassMapping(ClassMapping classMapping) { + if (!classMapping.getObfuscatedName().equals(classMapping.getDeobfuscatedName())) { + clWriter.format("CL %s %s\n", + classMapping.getFullObfuscatedName(), classMapping.getFullDeobfuscatedName()); + } + + classMapping.getInnerClassMappings().values().stream().filter(NOT_USELESS).forEach(this::writeClassMapping); + classMapping.getFieldMappings().values().stream().filter(NOT_USELESS).forEach(this::writeFieldMapping); + classMapping.getMethodMappings().values().forEach(this::writeMethodMapping); + } + + /** + * Writes the given {@link FieldMapping} to the {@link JamWriter}'s + * {@link PrintWriter}. + * + * @param fieldMapping The {@link FieldMapping} to write + */ + protected void writeFieldMapping(FieldMapping fieldMapping) { + fdWriter.format("FD %s %s %s %s\n", + fieldMapping.getParent().getFullObfuscatedName(), + fieldMapping.getObfuscatedName(), + fieldMapping.getObfuscatedType().toString(), + fieldMapping.getDeobfuscatedName()); + } + + /** + * Writes the given {@link MethodMapping} to the {@link JamWriter}'s + * {@link PrintWriter}. + * + * @param mapping The {@link MethodMapping} to write + */ + protected void writeMethodMapping(MethodMapping mapping) { + if (!mapping.getObfuscatedName().equals(mapping.getDeobfuscatedName())) { + mdWriter.format("MD %s %s %s %s\n", + mapping.getParent().getFullObfuscatedName(), + mapping.getObfuscatedName(), + mapping.getObfuscatedDescriptor(), + mapping.getDeobfuscatedName()); + } + for (MethodParameterMapping pm : mapping.getParamMappings().values()) { + mpWriter.format("MP %s %s %s %s %s\n", + pm.getParent().getParent().getFullDeobfuscatedName(), + pm.getParent().getObfuscatedName(), + pm.getParent().getObfuscatedDescriptor(), + pm.getIndex(), + pm.getDeobfuscatedName()); + } + } +} diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java index c0b80bb..d5a4d52 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingWriterType.java @@ -40,6 +40,7 @@ public enum MappingWriterType { SRG(MappingFormatType.SRG, SrgWriter.class), + JAM(MappingFormatType.JAM, JamWriter.class), ENIGMA(MappingFormatType.ENIGMA, EnigmaWriter.class); private final MappingFormatType type; diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 7c35e8b..8c4ecca 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -64,7 +64,7 @@ public FieldMapping(ClassMapping parent, String obfName, String deobfName, Type * * @return The {@link Type} of this field */ - public Type getType() { + public Type getObfuscatedType() { return type; } @@ -74,7 +74,7 @@ public Type getType() { * @return The deobfuscated {@link Type} of this field */ public Type getDeobfuscatedType() { - return getType().deobfuscate(getParent().getContext()); + return getObfuscatedType().deobfuscate(getParent().getContext()); } @Override diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index 967f584..b31fb5b 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -46,7 +46,7 @@ */ public class MethodMapping extends MemberMapping { - private final Map argumentMappings = new HashMap<>(); + private final Map argumentMappings = new HashMap<>(); private final SelectableMember.MemberKey memberKey; private final MethodDescriptor descriptor; private final MethodSignature sig; @@ -90,22 +90,22 @@ public void initialize(boolean propagate) { } /** - * Gets a clone of the {@link ArgumentMapping}s. + * Gets a clone of the {@link MethodParameterMapping}s. * - * @return A clone of the {@link ArgumentMapping}s + * @return A clone of the {@link MethodParameterMapping}s */ - public ImmutableMap getArgumentMappings() { + public ImmutableMap getParamMappings() { return ImmutableMap.copyOf(this.argumentMappings); } /** - * Adds the given {@link ArgumentMapping} to this {@link ClassMapping}. + * Adds the given {@link MethodParameterMapping} to this {@link ClassMapping}. * - * @param mapping The {@link ArgumentMapping} to add + * @param mapping The {@link MethodParameterMapping} to add * @param propagate Whether to propagate this mapping to super- and * sub-classes */ - void addArgumentMapping(ArgumentMapping mapping, boolean propagate) { + void addArgumentMapping(MethodParameterMapping mapping, boolean propagate) { mapping.initialize(propagate); argumentMappings.put(mapping.getObfuscatedName(), mapping); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java similarity index 89% rename from src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java rename to src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java index cf2a2aa..8a779d4 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/ArgumentMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java @@ -26,20 +26,23 @@ package blue.lapis.nocturne.mapping.model; import blue.lapis.nocturne.gui.scene.text.SelectableMember; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.util.MemberType; +import java.util.Optional; + /** * Represents a {@link Mapping} for arguments. */ -public class ArgumentMapping extends Mapping { +public class MethodParameterMapping extends Mapping { private final SelectableMember.MemberKey memberKey; private final MethodMapping parent; private final int index; /** - * Constructs a new {@link ArgumentMapping} with the given parameters. + * Constructs a new {@link MethodParameterMapping} with the given parameters. * * @param parent The parent method mapping * @param index The index of the argument @@ -48,8 +51,8 @@ public class ArgumentMapping extends Mapping { * @param propagate Whether to propagate this mapping to super- and * sub-classes */ - public ArgumentMapping(MethodMapping parent, int index, String obfName, String deobfName, boolean propagate) { - super(obfName, deobfName); + public MethodParameterMapping(MethodMapping parent, int index, String deobfName, boolean propagate) { + super(deobfName, deobfName); this.memberKey = new SelectableMember.MemberKey(MemberType.ARG, "", ""); // TODO: Use actual values this.parent = parent; this.index = index; diff --git a/src/main/java/blue/lapis/nocturne/util/Constants.java b/src/main/java/blue/lapis/nocturne/util/Constants.java index 0bed63c..970a2a9 100644 --- a/src/main/java/blue/lapis/nocturne/util/Constants.java +++ b/src/main/java/blue/lapis/nocturne/util/Constants.java @@ -49,6 +49,8 @@ public final class Constants { public static final Pattern DOT_PATTERN = Pattern.compile(".", Pattern.LITERAL); + public static final Pattern SPACE_PATTERN = Pattern.compile(" ", Pattern.LITERAL); + public static final String CLASS_FILE_NAME_TAIL = ".class"; public static final int CLASS_FORMAT_CONSTANT_POOL_OFFSET = 8; // byte offset of the CP per the class file format diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index cfdb282..979acf9 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -32,11 +32,11 @@ import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; -import blue.lapis.nocturne.mapping.model.ArgumentMapping; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.mapping.model.MethodParameterMapping; import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; @@ -190,12 +190,12 @@ public static void genArgumentMapping(MappingContext context, MethodMapping meth return; } - Optional mapping = methodMapping.getArgumentMappings().values().stream() + Optional mapping = methodMapping.getParamMappings().values().stream() .filter(argumentMapping -> argumentMapping.getIndex() == index).findFirst(); if (mapping.isPresent()) { mapping.get().setDeobfuscatedName(deobf); } else { - new ArgumentMapping(methodMapping, index, deobf, deobf, true); + new MethodParameterMapping(methodMapping, index, deobf, true); } } diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 7e9aa39..1757eaa 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -38,6 +38,7 @@ about.github=Der Quellcode ist auf GitHub verf\u00fcgbar. filechooser.type_jar=JAR Dateien filechooser.type_srg=SRG Dateien +filechooser.type_jam=JAM Dateien filechooser.type_enigma=Enigma Dateien filechooser.type_all=Alle Dateien filechooser.open_jar=JAR Datei ausw\u00e4hlen diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 560cd6d..5366b7e 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -37,6 +37,7 @@ about.github=The source code is available on GitHub. filechooser.type_jar=JAR Files filechooser.type_srg=SRG Files +filechooser.type_jam=JAM Files filechooser.type_enigma=Enigma Files filechooser.type_all=All Files filechooser.open_jar=Select JAR File diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java index fc45fb6..202ace2 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/EnigmaReaderTest.java @@ -48,7 +48,8 @@ public class EnigmaReaderTest { public static void initialize() throws IOException { loadMain(); EnigmaReader reader - = new EnigmaReader(new BufferedReader(new URLReader(ClassLoader.getSystemResource("example.eng")))); + = new EnigmaReader(new BufferedReader(new URLReader( + ClassLoader.getSystemResource("mappings/example.eng")))); helper = new ReaderTestHelper(reader.read()); } diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/JamReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/JamReaderTest.java new file mode 100644 index 0000000..ad61262 --- /dev/null +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/JamReaderTest.java @@ -0,0 +1,101 @@ +/* + * Nocturne + * Copyright (c) 2015-2016, Lapis + * + * The MIT License + * + * 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 blue.lapis.nocturne.test.mapping.io.reader; + +import static blue.lapis.nocturne.test.mapping.io.reader.ReaderTestHelper.loadMain; + +import blue.lapis.nocturne.mapping.io.reader.JamReader; +import blue.lapis.nocturne.mapping.io.reader.SrgReader; + +import jdk.nashorn.api.scripting.URLReader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.IOException; + +/** + * Unit tests related to the {@link SrgReader}. + */ +public class JamReaderTest { + + private static ReaderTestHelper helper; + + @BeforeClass + public static void initialize() throws IOException { + loadMain(); + JamReader reader + = new JamReader(new BufferedReader(new URLReader( + ClassLoader.getSystemResource("mappings/example.jam")))); + helper = new ReaderTestHelper(reader.read()); + } + + @Test + public void classTest() { + helper.classTest(); + } + + @Test + public void innerClassTest() { + helper.innerClassTest(); + } + + @Test + public void innerClassWithoutParentMappingTest() { + helper.innerClassWithoutParentMappingTest(); + } + + @Test + public void nestedInnerClassWithoutParentMappingTest() { + helper.nestedInnerClassWithoutParentMappingTest(); + } + + @Test + public void fieldTest() { + helper.fieldTest(); + } + + @Test + public void fieldInnerClassTest() { + helper.fieldInnerClassTest(); + } + + @Test + public void fieldNestedInnerClassTest() { + helper.fieldNestedInnerClassTest(); + } + + @Test + public void methodTest() { + helper.methodTest(); + } + + @Test + public void partialDeobfuscationTest() { + helper.partialDeobfuscationTest(); + } + +} diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java index 7aaaae8..c6c7cca 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/SrgReaderTest.java @@ -47,7 +47,8 @@ public class SrgReaderTest { public static void initialize() throws IOException { loadMain(); SrgReader reader - = new SrgReader(new BufferedReader(new URLReader(ClassLoader.getSystemResource("example.srg")))); + = new SrgReader(new BufferedReader(new URLReader( + ClassLoader.getSystemResource("mappings/example.srg")))); helper = new ReaderTestHelper(reader.read()); } diff --git a/src/test/resources/example.eng b/src/test/resources/mappings/example.eng similarity index 100% rename from src/test/resources/example.eng rename to src/test/resources/mappings/example.eng diff --git a/src/test/resources/mappings/example.jam b/src/test/resources/mappings/example.jam new file mode 100644 index 0000000..7f61e02 --- /dev/null +++ b/src/test/resources/mappings/example.jam @@ -0,0 +1,8 @@ +CL a com/example/project/Example +CL a$b com/example/project/Example$Inner +CL a$b$c com/example/project/Example$Inner$Deeper +CL b$a$c com/example/project/Another$Inner$Deeper +FD a a I someField +FD a$b a I someInnerField +FD a$b$c a I someDeeperField +MD a a (ILa;I)La; someMethod diff --git a/src/test/resources/example.srg b/src/test/resources/mappings/example.srg similarity index 100% rename from src/test/resources/example.srg rename to src/test/resources/mappings/example.srg From b5b5d40f64e80e0a95d01d3a5e55dcf402f8607f Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Thu, 18 Aug 2016 15:07:05 -0400 Subject: [PATCH 34/58] Update gitpatcher to 0.8.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2e9c114..f1e7670 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'idea' id 'checkstyle' - id 'net.minecrell.gitpatcher' version '0.8' + id 'net.minecrell.gitpatcher' version '0.8.1' id 'net.minecrell.licenser' version '0.2.1' id 'com.github.johnrengelman.shadow' version '1.2.3' From db07d7131c994bb46a7be7a41ececb8129a09738 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 13:14:58 -0400 Subject: [PATCH 35/58] Prevent redundant mappings from being written by EnigmaReader --- .../mapping/io/writer/EnigmaWriter.java | 20 +++++++++---------- .../nocturne/mapping/io/writer/JamWriter.java | 5 +---- .../mapping/io/writer/MappingsWriter.java | 5 +++++ .../nocturne/mapping/io/writer/SrgWriter.java | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index f7e37fd..26db472 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -66,25 +66,23 @@ public void write(MappingContext mappings) { protected void writeClassMapping(ClassMapping classMapping, int depth) { boolean inner = classMapping instanceof InnerClassMapping; if (classMapping.getDeobfuscatedName().equals(classMapping.getObfuscatedName())) { - out.println(getIndentForDepth(depth) + "CLASS " - + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName()))); + if (!classMapping.getInnerClassMappings().isEmpty()) { + out.println(getIndentForDepth(depth) + "CLASS " + + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName()))); + } } else { out.println(getIndentForDepth(depth) + "CLASS " + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + " " + (inner ? classMapping.getDeobfuscatedName() : addNonePrefix(classMapping.getDeobfuscatedName()))); } - for (ClassMapping innerClass : classMapping.getInnerClassMappings().values()) { - this.writeClassMapping(innerClass, depth + 1); - } + classMapping.getInnerClassMappings().values().forEach(m -> this.writeClassMapping(m, depth + 1)); - for (FieldMapping fieldMapping : classMapping.getFieldMappings().values()) { - this.writeFieldMapping(fieldMapping, depth + 1); - } + classMapping.getFieldMappings().values().stream().filter(NOT_USELESS) + .forEach(m -> this.writeFieldMapping(m, depth + 1)); - for (MethodMapping methodMapping : classMapping.getMethodMappings().values()) { - this.writeMethodMapping(methodMapping, depth + 1); - } + classMapping.getMethodMappings().values().stream().filter(NOT_USELESS) + .forEach(m -> this.writeMethodMapping(m, depth + 1)); } protected void writeFieldMapping(FieldMapping fieldMapping, int depth) { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java index 6164de4..be114be 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java @@ -42,9 +42,6 @@ */ public class JamWriter extends MappingsWriter { - private static final Predicate NOT_USELESS - = mapping -> !mapping.getObfuscatedName().equals(mapping.getDeobfuscatedName()); - private final ByteArrayOutputStream clOut = new ByteArrayOutputStream(); private final ByteArrayOutputStream fdOut = new ByteArrayOutputStream(); private final ByteArrayOutputStream mdOut = new ByteArrayOutputStream(); @@ -94,7 +91,7 @@ public void write(MappingContext mappingContext) { * @param classMapping The {@link ClassMapping} to write */ protected void writeClassMapping(ClassMapping classMapping) { - if (!classMapping.getObfuscatedName().equals(classMapping.getDeobfuscatedName())) { + if (NOT_USELESS.test(classMapping)) { clWriter.format("CL %s %s\n", classMapping.getFullObfuscatedName(), classMapping.getFullDeobfuscatedName()); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java index 6971421..a659578 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/MappingsWriter.java @@ -26,16 +26,21 @@ package blue.lapis.nocturne.mapping.io.writer; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.mapping.model.Mapping; import java.io.Closeable; import java.io.IOException; import java.io.PrintWriter; +import java.util.function.Predicate; /** * Superclass for all writer classes. */ public abstract class MappingsWriter implements Closeable { + protected static final Predicate NOT_USELESS + = mapping -> !mapping.getObfuscatedName().equals(mapping.getDeobfuscatedName()); + protected final PrintWriter out; /** diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java index 4402b60..3ff5ecf 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/SrgWriter.java @@ -88,7 +88,7 @@ public void write(MappingContext mappingContext) { * @param classMapping The {@link ClassMapping} to write */ protected void writeClassMapping(ClassMapping classMapping) { - if (!classMapping.getObfuscatedName().equals(classMapping.getDeobfuscatedName())) { + if (NOT_USELESS.test(classMapping)) { clWriter.format("CL: %s %s\n", classMapping.getFullObfuscatedName(), classMapping.getFullDeobfuscatedName()); } From 64d6225404c41241e117c857993b112d98c8bb4d Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 14:37:40 -0400 Subject: [PATCH 36/58] Store mappings with signature instead of just name --- .../gui/scene/text/SelectableMember.java | 6 ++-- .../nocturne/mapping/model/ClassMapping.java | 32 ++++++++++--------- .../nocturne/mapping/model/FieldMapping.java | 5 +++ .../nocturne/mapping/model/MemberMapping.java | 8 +++++ .../nocturne/mapping/model/MethodMapping.java | 5 +++ .../index/model/signature/FieldSignature.java | 5 +++ 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 1a7cfaa..ed75d78 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -422,10 +422,12 @@ private void updateText() { Optional classMapping = MappingsHelper.getClassMapping(Main.getMappingContext(), getParentClass()); if (classMapping.isPresent()) { - Map mappings = getType() == MemberType.FIELD + Map mappings = getType() == MemberType.FIELD ? classMapping.get().getFieldMappings() : classMapping.get().getMethodMappings(); - Mapping mapping = mappings.get(getName() + (getType() == MemberType.METHOD ? getDescriptor() : "")); + Mapping mapping = mappings.get(getType() == MemberType.METHOD + ? new MethodSignature(getName(), MethodDescriptor.fromString(getDescriptor())) + : new FieldSignature(getName(), Type.fromString(getDescriptor()))); if (mapping != null) { deobf = mapping.getDeobfuscatedName(); } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java index cd8aeed..29f1aec 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java @@ -32,6 +32,8 @@ import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.JarClassEntry; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.StringHelper; import com.google.common.collect.ImmutableMap; @@ -46,8 +48,8 @@ */ public abstract class ClassMapping extends Mapping { - private final Map fieldMappings = new HashMap<>(); - private final Map methodMappings = new HashMap<>(); + private final Map fieldMappings = new HashMap<>(); + private final Map methodMappings = new HashMap<>(); private final Map innerClassMappings = new HashMap<>(); /** @@ -69,7 +71,7 @@ protected ClassMapping(String obfName, String deobfName) { * * @return A clone of the {@link FieldMapping}s */ - public ImmutableMap getFieldMappings() { + public ImmutableMap getFieldMappings() { return ImmutableMap.copyOf(this.fieldMappings); } @@ -78,7 +80,7 @@ public ImmutableMap getFieldMappings() { * * @return A clone of the {@link MethodMapping}s */ - public ImmutableMap getMethodMappings() { + public ImmutableMap getMethodMappings() { return ImmutableMap.copyOf(this.methodMappings); } @@ -98,17 +100,17 @@ public ImmutableMap getInnerClassMappings() { */ void addFieldMapping(FieldMapping mapping) { mapping.initialize(); - fieldMappings.put(mapping.getObfuscatedName(), mapping); + fieldMappings.put(mapping.getSignature(), mapping); } /** - * Removes the {@link FieldMapping} by the given name from this + * Removes the {@link FieldMapping} with the given signature from this * {@link ClassMapping}. * - * @param fieldName The name of the field to remove the mapping of + * @param fieldSig The signature of the field to remove the mapping of */ - public void removeFieldMapping(String fieldName) { - fieldMappings.remove(fieldName); + public void removeFieldMapping(FieldSignature fieldSig) { + fieldMappings.remove(fieldSig); } /** @@ -120,17 +122,17 @@ public void removeFieldMapping(String fieldName) { */ void addMethodMapping(MethodMapping mapping, boolean propagate) { mapping.initialize(propagate); - methodMappings.put(mapping.getObfuscatedName() + mapping.getObfuscatedDescriptor(), mapping); + methodMappings.put(mapping.getSignature(), mapping); } /** - * Removes the {@link MethodMapping} by the given name from this + * Removes the {@link MethodMapping} with the given signature from this * {@link ClassMapping}. * - * @param methodName The name of the method to remove the mapping of + * @param methodSig The signature of the method to remove the mapping of */ - public void removeMethodMapping(String methodName) { - methodMappings.remove(methodName); + public void removeMethodMapping(MethodSignature methodSig) { + methodMappings.remove(methodSig); } /** @@ -201,7 +203,7 @@ public void setDeobfuscatedName(String name, boolean updateClassViews) { } } - public void updateEntryDeobfuscation() { + private void updateEntryDeobfuscation() { if (Main.getInstance() != null && Main.getLoadedJar() != null) { // first check is to fix stupid unit tests Optional classEntry = Main.getLoadedJar().getClass(getFullObfuscatedName()); if (classEntry.isPresent()) { diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 8c4ecca..bc9fb25 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -85,6 +85,11 @@ public void setDeobfuscatedName(String deobf) { .getCurrentFields().put(sig, new FieldSignature(getDeobfuscatedName(), type)); } + @Override + public FieldSignature getSignature() { + return sig; + } + @Override protected SelectableMember.MemberKey getMemberKey() { return new SelectableMember.MemberKey(MemberType.FIELD, getQualifiedName(), type.toString()); diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MemberMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MemberMapping.java index dbb9bee..e1da3b5 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MemberMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MemberMapping.java @@ -27,6 +27,7 @@ import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.processor.index.model.signature.MemberSignature; import java.util.List; @@ -67,6 +68,13 @@ public void setDeobfuscatedName(String name) { }); } + /** + * Gets the signature of this {@link MemberMapping}. + * + * @return The signature of this {@link MemberMapping} + */ + public abstract MemberSignature getSignature(); + @Override public MappingContext getContext() { return getParent().getContext(); diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index b31fb5b..ec5748a 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -128,6 +128,11 @@ public MethodDescriptor getDeobfuscatedDescriptor() { return getObfuscatedDescriptor().deobfuscate(getParent().getContext()); } + @Override + public MethodSignature getSignature() { + return sig; + } + @Override protected SelectableMember.MemberKey getMemberKey() { return memberKey; diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java index fb615a1..0c3b3fa 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/signature/FieldSignature.java @@ -45,6 +45,11 @@ public Type getType() { return type; } + @Override + public String toString() { + return this.getName() + ":" + this.getType().toString(); + } + @Override public boolean equals(Object otherObj) { if (!(otherObj instanceof FieldSignature)) { From da83818356e88ac353ba32f2acff8984b80e96d5 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 15:10:24 -0400 Subject: [PATCH 37/58] Implement manual deobfuscation toggling (still broken) and fix bugs from last commit --- .../lapis/nocturne/gui/MainController.java | 1 + .../gui/scene/text/SelectableMember.java | 94 +++++++++++++++---- .../blue/lapis/nocturne/jar/io/JarLoader.java | 4 +- .../mapping/io/reader/EnigmaReader.java | 8 +- .../nocturne/mapping/io/reader/JamReader.java | 15 ++- .../nocturne/mapping/io/reader/SrgReader.java | 9 +- .../nocturne/mapping/io/writer/JamWriter.java | 2 - .../nocturne/mapping/model/FieldMapping.java | 17 ++-- .../lapis/nocturne/mapping/model/Mapping.java | 24 +++++ .../nocturne/mapping/model/MethodMapping.java | 31 +++--- .../mapping/model/MethodParameterMapping.java | 4 - .../processor/index/model/Hierarchical.java | 1 + .../nocturne/util/JavaSyntaxHighlighter.java | 65 +++++++------ .../nocturne/util/helper/MappingsHelper.java | 57 +++++------ src/main/resources/lang/de_DE.properties | 1 + src/main/resources/lang/en_US.properties | 1 + 16 files changed, 204 insertions(+), 130 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index fd64b60..b10f4f8 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -41,6 +41,7 @@ import blue.lapis.nocturne.util.Constants; import blue.lapis.nocturne.util.helper.PropertiesHelper; import blue.lapis.nocturne.util.helper.SceneHelper; + import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index ed75d78..9193c97 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -29,6 +29,8 @@ import static blue.lapis.nocturne.util.Constants.DOT_PATTERN; import static blue.lapis.nocturne.util.Constants.INNER_CLASS_SEPARATOR_CHAR; import static blue.lapis.nocturne.util.Constants.Processing.CLASS_PREFIX; +import static blue.lapis.nocturne.util.helper.MappingsHelper.genMethodMapping; +import static blue.lapis.nocturne.util.helper.MappingsHelper.getOrCreateClassMapping; import blue.lapis.nocturne.Main; import blue.lapis.nocturne.gui.MainController; @@ -84,6 +86,8 @@ public class SelectableMember extends Text { private final MemberSignature sig; + private boolean deobfuscated; + private String fullName = null; // only used for classes public SelectableMember(CodeTab codeTab, MemberType type, String name) { @@ -171,9 +175,9 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de Optional parent = MappingsHelper.getClassMapping(Main.getMappingContext(), getParentClass()); if (parent.isPresent()) { - MemberMapping mapping = getType() == MemberType.FIELD - ? parent.get().getFieldMappings().get(getName()) - : parent.get().getMethodMappings().get(getName() + getDescriptor()); + MemberMapping mapping = (getType() == MemberType.FIELD + ? parent.get().getFieldMappings() : parent.get().getMethodMappings()) + .get(sig); if (mapping != null) { if (!checkMemberDupe(mapping.getObfuscatedName())) { return; @@ -191,13 +195,15 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de this.updateCodeTab(); }); + MenuItem toggleDeobf = new MenuItem(Main.getResourceBundle().getString("member.contextmenu.toggleDeobf")); + toggleDeobf.setOnAction(event -> { + this.setDeobfuscated(!this.deobfuscated); + genMapping().setAdHoc(this.deobfuscated); // set as ad hoc if we've marked it as deobfuscated + }); + MenuItem jumpToDefItem = new MenuItem(Main.getResourceBundle().getString("member.contextmenu.jumpToDef")); jumpToDefItem.setOnAction(event -> { - String className = getType() == MemberType.CLASS ? getName() : getParentClass(); - if (className.contains(INNER_CLASS_SEPARATOR_CHAR + "")) { - className = className.substring(0, className.indexOf(INNER_CLASS_SEPARATOR_CHAR)); - } - + String className = getClassName(); Optional cm = MappingsHelper.getClassMapping(Main.getMappingContext(), className); MainController.INSTANCE.openTab(className, cm.isPresent() ? cm.get().getDeobfuscatedName() : className); }); @@ -205,10 +211,17 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de ContextMenu contextMenu = new ContextMenu(); contextMenu.getItems().add(renameItem); contextMenu.getItems().add(resetItem); + contextMenu.getItems().add(toggleDeobf); contextMenu.getItems().add(jumpToDefItem); - this.setOnContextMenuRequested(event -> - contextMenu.show(SelectableMember.this, event.getScreenX(), event.getScreenY())); + this.setOnContextMenuRequested(event -> { + Optional mapping = MappingsHelper.getClassMapping(Main.getMappingContext(), getClassName()); + toggleDeobf.setDisable(mapping.isPresent() + && !mapping.get().getObfuscatedName().equals(mapping.get().getDeobfuscatedName())); + + contextMenu.show(SelectableMember.this, event.getScreenX(), event.getScreenY()); + + }); String qualName; IndexedClass ic = IndexedClass.INDEXED_CLASSES.get(getParentClass()); @@ -245,7 +258,6 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de default: throw new AssertionError(); } - //TODO: we're ignoring field descriptors for now since SRG doesn't support them MemberKey key = new MemberKey(type, qualName, type == MemberType.FIELD || type == MemberType.METHOD ? descriptor : null); if (!MEMBERS.containsKey(key)) { @@ -255,7 +267,16 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de updateText(); - setDeobfuscated(!getName().equals(getText())); + Optional mapping = getMapping(); + setDeobfuscated(!getName().equals(getText()) || (mapping.isPresent() && mapping.get().isAdHoc())); + } + + private String getClassName() { + String className = getType() == MemberType.CLASS ? getName() : getParentClass(); + if (className.contains(INNER_CLASS_SEPARATOR_CHAR + "")) { + className = className.substring(0, className.indexOf(INNER_CLASS_SEPARATOR_CHAR)); + } + return className; } private boolean checkClassDupe(String newName) { @@ -345,8 +366,8 @@ public void setMapping(String mapping) { break; } case FIELD: { - MappingsHelper.genFieldMapping(Main.getMappingContext(), getParentClass(), getName(), mapping, - getDescriptor()); + MappingsHelper.genFieldMapping(Main.getMappingContext(), getParentClass(), (FieldSignature) sig, + mapping); break; } case METHOD: { @@ -357,8 +378,7 @@ public void setMapping(String mapping) { for (IndexedClass ic : classes) { //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object if (ic.getMethods().containsKey(sig)) { - MappingsHelper.genMethodMapping(Main.getMappingContext(), ic.getName(), getName(), mapping, - getDescriptor(), false); + genMethodMapping(Main.getMappingContext(), ic.getName(), (MethodSignature) sig, mapping, false); } } break; @@ -500,6 +520,7 @@ public boolean isInnerClass() { } public void setDeobfuscated(boolean deobfuscated) { + this.deobfuscated = deobfuscated; getStyleClass().clear(); if (deobfuscated) { getStyleClass().add("deobfuscated"); @@ -508,4 +529,45 @@ public void setDeobfuscated(boolean deobfuscated) { } } + private Mapping genMapping() { + switch (getType()) { + case CLASS: { + return getOrCreateClassMapping(Main.getMappingContext(), getClassName()); + } + case FIELD: { + return MappingsHelper.genFieldMapping(Main.getMappingContext(), getClassName(), (FieldSignature) sig, + getName()); + } + case METHOD: { + return MappingsHelper.genMethodMapping(Main.getMappingContext(), getClassName(), (MethodSignature) sig, + getName(), false); + } + default: { + throw new AssertionError(); + } + } + } + + @SuppressWarnings("SuspiciousMethodCalls") + private Optional getMapping() { + Optional classMapping = MappingsHelper.getClassMapping(Main.getMappingContext(), getClassName()); + if (!classMapping.isPresent()) { + return classMapping; + } + switch (getType()) { + case CLASS: { + return classMapping; + } + case FIELD: { + return Optional.ofNullable(classMapping.get().getFieldMappings().get(sig)); + } + case METHOD: { + return Optional.ofNullable(classMapping.get().getMethodMappings().get(sig)); + } + default: { + throw new AssertionError(); + } + } + } + } diff --git a/src/main/java/blue/lapis/nocturne/jar/io/JarLoader.java b/src/main/java/blue/lapis/nocturne/jar/io/JarLoader.java index 7d0396d..651910d 100644 --- a/src/main/java/blue/lapis/nocturne/jar/io/JarLoader.java +++ b/src/main/java/blue/lapis/nocturne/jar/io/JarLoader.java @@ -120,9 +120,9 @@ public static ClassSet loadJar(String name, InputStream jarFile) throws IOExcept jar.close(); // release the resource ClassSet cs = new ClassSet(name, classes); Main.setLoadedJar(cs); - cs.getClasses().stream().forEach(JarClassEntry::index); + cs.getClasses().forEach(JarClassEntry::index); new ClassHierarchyBuilder(Sets.newHashSet(INDEXED_CLASSES.values())).buildHierarchies(); - cs.getClasses().stream().forEach(JarClassEntry::process); + cs.getClasses().forEach(JarClassEntry::process); INDEXED_CLASSES.values().forEach(IndexedClass::clearPool); return cs; } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 9090cbb..27762ec 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -35,6 +35,8 @@ import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -130,8 +132,8 @@ public MappingContext read() { String obf = arr[1]; String deobf = arr[2]; Type type = removeNonePrefix(Type.fromString(arr[3])); - MappingsHelper.genFieldMapping(mappings, classStack.peek().getFullObfuscatedName(), obf, deobf, - type); + MappingsHelper.genFieldMapping(mappings, classStack.peek().getFullObfuscatedName(), + new FieldSignature(obf, type), deobf); currentMethod = null; break; } @@ -162,7 +164,7 @@ public MappingContext read() { MethodDescriptor desc = removeNonePrefixes(MethodDescriptor.fromString(descStr)); currentMethod = MappingsHelper.genMethodMapping(mappings, classStack.peek().getFullObfuscatedName(), - obf, deobf, desc, true); + new MethodSignature(obf, desc), deobf, true); break; } case ARG_MAPPING_KEY: { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java index 4bed4d8..30f459e 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/JamReader.java @@ -29,9 +29,12 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; +import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -124,7 +127,7 @@ private void genFieldMappings(MappingContext context, List fieldMappings String obf = arr[2]; String desc = arr[3]; String deobf = arr[4]; - MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, desc); + MappingsHelper.genFieldMapping(context, owningClass, new FieldSignature(obf, Type.fromString(desc)), deobf); } } @@ -135,7 +138,8 @@ private void genMethodMappings(MappingContext context, List methodMappin String obf = arr[2]; String desc = arr[3]; String deobf = arr[4]; - MappingsHelper.genMethodMapping(context, owningClass, obf, deobf, desc, false); + MappingsHelper.genMethodMapping(context, owningClass, + new MethodSignature(obf, MethodDescriptor.fromString(desc)), deobf, false); } } @@ -151,10 +155,11 @@ private void genMethodParamMappings(MappingContext context, List paramMa continue; } MethodMapping methodMapping = classMapping.get().getMethodMappings() - .get(owningMethod); + .get(new MethodSignature(owningMethod, MethodDescriptor.fromString(owningMethodDesc))); if (methodMapping == null) { - methodMapping = new MethodMapping(classMapping.get(), owningMethod, owningMethod, - MethodDescriptor.fromString(owningMethodDesc), false); + methodMapping = new MethodMapping(classMapping.get(), + new MethodSignature(owningMethod, MethodDescriptor.fromString(owningMethodDesc)), owningMethod, + false); } int index; try { diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java index 931b41b..a0a0743 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/SrgReader.java @@ -28,8 +28,10 @@ import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_CHAR; import blue.lapis.nocturne.Main; -import blue.lapis.nocturne.jar.model.attribute.Type; +import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.mapping.MappingContext; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.helper.MappingsHelper; import java.io.BufferedReader; @@ -116,7 +118,7 @@ private void genFieldMappings(MappingContext context, List fieldMappings String obf = arr[1].substring(lastIndex + 1); String deobf = arr[2].substring(arr[2].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1); // SRG doesn't support field types so we just pass a null type arg and let the helper method figure it out - MappingsHelper.genFieldMapping(context, owningClass, obf, deobf, (Type) null); + MappingsHelper.genFieldMapping(context, owningClass, new FieldSignature(obf, null), deobf); } } @@ -128,7 +130,8 @@ private void genMethodMappings(MappingContext context, List methodMappin String obf = arr[1].substring(lastIndex + 1); String descriptor = arr[2]; String deobf = arr[3].substring(arr[3].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1); - MappingsHelper.genMethodMapping(context, owningClass, obf, deobf, descriptor, false); + MappingsHelper.genMethodMapping(context, owningClass, + new MethodSignature(obf, MethodDescriptor.fromString(descriptor)), deobf, false); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java index be114be..404962c 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/JamWriter.java @@ -28,14 +28,12 @@ import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; -import blue.lapis.nocturne.mapping.model.Mapping; import blue.lapis.nocturne.mapping.model.MethodMapping; import blue.lapis.nocturne.mapping.model.MethodParameterMapping; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.util.function.Predicate; /** * The mappings writer, for the SRG format. diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index bc9fb25..64a14e0 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -39,22 +39,19 @@ public class FieldMapping extends MemberMapping { private final ClassMapping parent; - private final Type type; private final FieldSignature sig; /** * Constructs a new {@link FieldMapping} with the given parameters. * * @param parent The parent {@link ClassMapping} - * @param obfName The obfuscated name of the field + * @param sig The obfuscated signature of the field * @param deobfName The deobfuscated name of the field - * @param type The (obfuscated) {@link Type} of the field */ - public FieldMapping(ClassMapping parent, String obfName, String deobfName, Type type) { - super(parent, obfName, deobfName); + public FieldMapping(ClassMapping parent, FieldSignature sig, String deobfName) { + super(parent, sig.getName(), deobfName); this.parent = parent; - this.type = type; - this.sig = new FieldSignature(obfName, type); + this.sig = sig; parent.addFieldMapping(this); } @@ -65,7 +62,7 @@ public FieldMapping(ClassMapping parent, String obfName, String deobfName, Type * @return The {@link Type} of this field */ public Type getObfuscatedType() { - return type; + return sig.getType(); } /** @@ -82,7 +79,7 @@ public void setDeobfuscatedName(String deobf) { super.setDeobfuscatedName(deobf); Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentFields().put(sig, new FieldSignature(getDeobfuscatedName(), type)); + .getCurrentFields().put(sig, new FieldSignature(getDeobfuscatedName(), sig.getType())); } @Override @@ -92,7 +89,7 @@ public FieldSignature getSignature() { @Override protected SelectableMember.MemberKey getMemberKey() { - return new SelectableMember.MemberKey(MemberType.FIELD, getQualifiedName(), type.toString()); + return new SelectableMember.MemberKey(MemberType.FIELD, getQualifiedName(), sig.getType().toString()); } private String getQualifiedName() { diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/Mapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/Mapping.java index d2ef8e9..063bd6b 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/Mapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/Mapping.java @@ -35,6 +35,7 @@ public abstract class Mapping { private final String obf; private String deobf; + private boolean adHoc; /** * Constructs a new mapping with the given parameters. @@ -75,10 +76,33 @@ public String getDeobfuscatedName() { * @param name The new deobfuscated name of this {@link Mapping} */ public void setDeobfuscatedName(String name) { + if (this.deobf.equals(name)) { + this.setAdHoc(false); + } this.deobf = name; getContext().setDirty(true); } + /** + * Gets whether this mapping is ad hoc, for the purpose of on-demand + * deobfuscation toggling. + * + * @return Whether this mapping is ad hoc + */ + public boolean isAdHoc() { + return adHoc; + } + + /** + * Sets whether this mapping is ad hoc, for the purpose of on-demand + * deobfuscation toggling. + * + * @param adHoc Whether this mapping is ad hoc + */ + public void setAdHoc(boolean adHoc) { + this.adHoc = adHoc; + } + /** * Gets the {@link MappingContext} which owns this {@link Mapping}. * diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index ec5748a..077c800 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -48,25 +48,20 @@ public class MethodMapping extends MemberMapping { private final Map argumentMappings = new HashMap<>(); private final SelectableMember.MemberKey memberKey; - private final MethodDescriptor descriptor; private final MethodSignature sig; /** * Constructs a new {@link MethodMapping} with the given parameters. * * @param parent The parent {@link ClassMapping} - * @param obfName The obfuscated name of the method + * @param sig The obfuscated signature of the method * @param deobfName The deobfuscated name of the method - * @param descriptor The (obfuscated) {@link MethodDescriptor descriptor} of - * the method * @param propagate Whether to propagate this mapping to super- and * sub-classes */ - public MethodMapping(ClassMapping parent, String obfName, String deobfName, MethodDescriptor descriptor, - boolean propagate) { - super(parent, obfName, deobfName); - this.descriptor = descriptor; - this.sig = new MethodSignature(getObfuscatedName(), descriptor); + public MethodMapping(ClassMapping parent, MethodSignature sig, String deobfName, boolean propagate) { + super(parent, sig.getName(), deobfName); + this.sig = sig; memberKey = new SelectableMember.MemberKey(MemberType.METHOD, getQualifiedName(), getObfuscatedDescriptor().toString()); parent.addMethodMapping(this, propagate); @@ -76,13 +71,11 @@ public MethodMapping(ClassMapping parent, String obfName, String deobfName, Meth * Constructs a new {@link MethodMapping} with the given parameters. * * @param parent The parent {@link ClassMapping} - * @param obfName The obfuscated name of the method + * @param sig The obfuscated signature of the method * @param deobfName The deobfuscated name of the method - * @param descriptor The (obfuscated) {@link MethodDescriptor descriptor} of - * the method */ - public MethodMapping(ClassMapping parent, String obfName, String deobfName, MethodDescriptor descriptor) { - this(parent, obfName, deobfName, descriptor, true); + public MethodMapping(ClassMapping parent, MethodSignature sig, String deobfName) { + this(parent, sig, deobfName, true); } public void initialize(boolean propagate) { @@ -116,7 +109,7 @@ void addArgumentMapping(MethodParameterMapping mapping, boolean propagate) { * @return The {@link MethodDescriptor} of this method */ public MethodDescriptor getObfuscatedDescriptor() { - return descriptor; + return sig.getDescriptor(); } /** @@ -157,16 +150,16 @@ public void setDeobfuscatedName(String deobf, boolean propagate) { } ClassMapping cm = MappingsHelper.getOrCreateClassMapping(getContext(), clazz); - if (cm.getMethodMappings().containsKey(getObfuscatedName())) { - cm.getMethodMappings().get(getObfuscatedName()).setDeobfuscatedName(deobf, false); + if (cm.getMethodMappings().containsKey(getSignature())) { + cm.getMethodMappings().get(getSignature()).setDeobfuscatedName(deobf, false); } else { - new MethodMapping(cm, getObfuscatedName(), deobf, getObfuscatedDescriptor(), false); + new MethodMapping(cm, getSignature(), deobf, false); } } } Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentMethods().put(sig, new MethodSignature(deobf, descriptor)); + .getCurrentMethods().put(sig, new MethodSignature(deobf, sig.getDescriptor())); } } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java index 8a779d4..9ee312f 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java @@ -26,12 +26,9 @@ package blue.lapis.nocturne.mapping.model; import blue.lapis.nocturne.gui.scene.text.SelectableMember; -import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.util.MemberType; -import java.util.Optional; - /** * Represents a {@link Mapping} for arguments. */ @@ -46,7 +43,6 @@ public class MethodParameterMapping extends Mapping { * * @param parent The parent method mapping * @param index The index of the argument - * @param obfName The obfuscated name of the mapped argument * @param deobfName The deobfuscated name of the mapped argument * @param propagate Whether to propagate this mapping to super- and * sub-classes diff --git a/src/main/java/blue/lapis/nocturne/processor/index/model/Hierarchical.java b/src/main/java/blue/lapis/nocturne/processor/index/model/Hierarchical.java index 24e6a38..46b24da 100644 --- a/src/main/java/blue/lapis/nocturne/processor/index/model/Hierarchical.java +++ b/src/main/java/blue/lapis/nocturne/processor/index/model/Hierarchical.java @@ -46,6 +46,7 @@ public Set getHierarchy() { public void finalizeHierarchy() { checkState(!isHierarchyFinalized, "Cannot finalize hierarchy more than once"); + //noinspection SuspiciousMethodCalls getHierarchy().remove(this); hierarchy = ImmutableSet.copyOf(hierarchy); diff --git a/src/main/java/blue/lapis/nocturne/util/JavaSyntaxHighlighter.java b/src/main/java/blue/lapis/nocturne/util/JavaSyntaxHighlighter.java index 12562b7..3361229 100644 --- a/src/main/java/blue/lapis/nocturne/util/JavaSyntaxHighlighter.java +++ b/src/main/java/blue/lapis/nocturne/util/JavaSyntaxHighlighter.java @@ -81,41 +81,40 @@ private JavaSyntaxHighlighter() { */ public static void highlight(List nodes) { List newNodes = new ArrayList<>(); - nodes.stream() - .forEach(node -> { - if (node.getClass() == SelectableMember.class) { - newNodes.add(node); - return; - } - String text = ((Text) node).getText(); - Matcher matcher = PATTERN.matcher(text); - int lastIndex = 0; - - while (matcher.find()) { - String group = null; - for (String pattern : PATTERN_NAMES) { - if (matcher.group(pattern) != null) { - group = pattern; - break; - } - } - assert group != null; + nodes.forEach(node -> { + if (node.getClass() == SelectableMember.class) { + newNodes.add(node); + return; + } + String text = ((Text) node).getText(); + Matcher matcher = PATTERN.matcher(text); + int lastIndex = 0; - int start = matcher.start(group); - int end = matcher.end(group); - if (group.equals("NUMBER") && !Character.isDigit(matcher.group(group).charAt(0))) { - //TODO: I am a horrible person - start += 1; - } - newNodes.add(new Text(text.substring(lastIndex, start))); - Text syntaxItem = new Text(text.substring(start, end)); - syntaxItem.getStyleClass().add("syntax"); - syntaxItem.getStyleClass().add(group.toLowerCase()); - newNodes.add(syntaxItem); - lastIndex = matcher.end(); + while (matcher.find()) { + String group = null; + for (String pattern : PATTERN_NAMES) { + if (matcher.group(pattern) != null) { + group = pattern; + break; } - newNodes.add(new Text(text.substring(lastIndex))); - }); + } + assert group != null; + + int start = matcher.start(group); + int end = matcher.end(group); + if (group.equals("NUMBER") && !Character.isDigit(matcher.group(group).charAt(0))) { + //TODO: I am a horrible person + start += 1; + } + newNodes.add(new Text(text.substring(lastIndex, start))); + Text syntaxItem = new Text(text.substring(start, end)); + syntaxItem.getStyleClass().add("syntax"); + syntaxItem.getStyleClass().add(group.toLowerCase()); + newNodes.add(syntaxItem); + lastIndex = matcher.end(); + } + newNodes.add(new Text(text.substring(lastIndex))); + }); nodes.clear(); nodes.addAll(newNodes); } diff --git a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java index 979acf9..ce804e6 100644 --- a/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java +++ b/src/main/java/blue/lapis/nocturne/util/helper/MappingsHelper.java @@ -29,8 +29,6 @@ import static blue.lapis.nocturne.util.Constants.INNER_CLASS_SEPARATOR_PATTERN; import blue.lapis.nocturne.Main; -import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; -import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.MappingContext; import blue.lapis.nocturne.mapping.model.ClassMapping; import blue.lapis.nocturne.mapping.model.FieldMapping; @@ -40,6 +38,7 @@ import blue.lapis.nocturne.mapping.model.TopLevelClassMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import java.util.List; import java.util.Optional; @@ -119,67 +118,59 @@ public static ClassMapping genClassMapping(MappingContext context, String obf, S } } - public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, - String descriptor) { - genFieldMapping(context, owningClass, obf, deobf, Type.fromString(descriptor)); - } - - public static void genFieldMapping(MappingContext context, String owningClass, String obf, String deobf, - Type descriptor) { + public static FieldMapping genFieldMapping(MappingContext context, String owningClass, final FieldSignature sig, + String deobf) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for field in non-existent class \"" + owningClass + "\" - ignoring"); - return; - } else if (!StringHelper.isJavaIdentifier(obf) || !StringHelper.isJavaIdentifier(deobf)) { + return null; + } else if (!StringHelper.isJavaIdentifier(sig.getName()) || !StringHelper.isJavaIdentifier(deobf)) { Main.getLogger().warning("Discovered field mapping with illegal name - ignoring"); - return; + return null; } ClassMapping parent = getOrCreateClassMapping(context, owningClass); - if (parent.getFieldMappings().containsKey(obf)) { - parent.getFieldMappings().get(obf).setDeobfuscatedName(deobf); + if (parent.getFieldMappings().containsKey(sig)) { + final FieldMapping fieldMapping = parent.getFieldMappings().get(sig); + fieldMapping.setDeobfuscatedName(deobf); + return fieldMapping; } else { - if (descriptor == null) { + FieldSignature finalSig = sig; + if (sig.getType() == null) { List sigList = IndexedClass.INDEXED_CLASSES.get(owningClass).getFields().keySet() - .stream().filter(s -> s.getName().equals(obf)).collect(Collectors.toList()); + .stream().filter(s -> s.getName().equals(sig.getName())).collect(Collectors.toList()); if (sigList.size() > 1) { Main.getLogger().warning("Discovered ambiguous field mapping! Ignoring..."); - return; + return null; } else if (sigList.size() == 0) { Main.getLogger().warning("Discovered field mapping for non-existent field - ignoring..."); - return; + return null; } - descriptor = sigList.get(0).getType(); + finalSig = sigList.get(0); } - new FieldMapping(parent, obf, deobf, descriptor); + return new FieldMapping(parent, finalSig, deobf); } } - public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, - String descriptor, boolean acceptInitializer) { - return genMethodMapping(context, owningClass, obf, deobf, MethodDescriptor.fromString(descriptor), - acceptInitializer); - } - - public static MethodMapping genMethodMapping(MappingContext context, String owningClass, String obf, String deobf, - MethodDescriptor descriptor, boolean acceptInitializer) { + public static MethodMapping genMethodMapping(MappingContext context, String owningClass, MethodSignature sig, + String deobf, boolean acceptInitializer) { if (!Main.getLoadedJar().getClass(owningClass).isPresent()) { Main.getLogger().warning("Discovered mapping for method in non-existent class \"" + owningClass + "\" - ignoring"); return null; - } else if (!(obf.equals("") && acceptInitializer && obf.equals(deobf)) - && (!StringHelper.isJavaIdentifier(obf) || !StringHelper.isJavaIdentifier(deobf))) { + } else if (!(sig.getName().equals("") && acceptInitializer && sig.getName().equals(deobf)) + && (!StringHelper.isJavaIdentifier(sig.getName()) || !StringHelper.isJavaIdentifier(deobf))) { Main.getLogger().warning("Discovered method mapping with illegal name - ignoring"); return null; } ClassMapping parent = getOrCreateClassMapping(context, owningClass); - if (parent.getMethodMappings().containsKey(obf)) { - final MethodMapping methodMapping = parent.getMethodMappings().get(obf); + if (parent.getMethodMappings().containsKey(sig)) { + final MethodMapping methodMapping = parent.getMethodMappings().get(sig); methodMapping.setDeobfuscatedName(deobf); return methodMapping; } else { - return new MethodMapping(parent, obf, deobf, descriptor); + return new MethodMapping(parent, sig, deobf); } } diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 1757eaa..221c449 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -28,6 +28,7 @@ codetab.identifier.arg=Argument member.contextmenu.rename=Umbenennen member.contextmenu.reset=Zur\u00fccksetzen +member.contextmenu.toggleDeobf=Toggle Deobfuscated member.contextmenu.jumpToDef=Springen zu definieren-Klasse about.title=\u00dcber Nocturne diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 5366b7e..e6d277d 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -27,6 +27,7 @@ codetab.identifier.arg=Argument member.contextmenu.rename=Rename member.contextmenu.reset=Reset +member.contextmenu.toggleDeobf=Toggle Deobfuscated member.contextmenu.jumpToDef=Jump to Defining Class about.title=About Nocturne From bd2da862b2308647e701ee34a891d3b1e8e8331f Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:04:29 -0400 Subject: [PATCH 38/58] Fix bugs with manual deobfuscation toggling --- .../gui/scene/text/SelectableMember.java | 134 +++++++++++------- .../nocturne/mapping/model/MethodMapping.java | 7 +- .../mapping/model/MethodParameterMapping.java | 2 +- 3 files changed, 92 insertions(+), 51 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 9193c97..2708b4c 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -39,8 +39,10 @@ import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.mapping.model.ClassMapping; +import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.Mapping; import blue.lapis.nocturne.mapping.model.MemberMapping; +import blue.lapis.nocturne.mapping.model.MethodParameterMapping; import blue.lapis.nocturne.processor.index.model.IndexedClass; import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; import blue.lapis.nocturne.processor.index.model.signature.MemberSignature; @@ -80,6 +82,8 @@ public class SelectableMember extends Text { private final CodeTab codeTab; private final MemberType type; + private final MemberKey key; + private final StringProperty nameProperty = new SimpleStringProperty(this, "name"); private final StringProperty descriptorProperty = new SimpleStringProperty(this, "descriptor"); private final StringProperty parentClassProperty = new SimpleStringProperty(this, "parentClass"); @@ -115,6 +119,9 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de fullName = getName(); } + this.key = new MemberKey(type, getQualifiedName(), + type == MemberType.FIELD || type == MemberType.METHOD ? descriptor : null); + this.setOnMouseClicked(event1 -> { if (event1.getButton() == MouseButton.PRIMARY) { this.updateCodeTab(); @@ -153,12 +160,28 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de MenuItem resetItem = new MenuItem(Main.getResourceBundle().getString("member.contextmenu.reset")); resetItem.setOnAction(event -> { if (getText().equals(getName())) { - return; + Optional mapping = getMapping(); + if (mapping.isPresent()) { + mapping.get().setAdHoc(false); + if (mapping.get() instanceof MemberMapping) { + ClassMapping parent = ((MemberMapping) mapping.get()).getParent(); + if (mapping.get() instanceof FieldMapping) { + //noinspection ConstantConditions + parent.removeFieldMapping((FieldSignature) sig); + } else { + //noinspection ConstantConditions + parent.removeMethodMapping((MethodSignature) sig); + } + } else if (mapping.get() instanceof MethodParameterMapping) { + ((MethodParameterMapping) mapping.get()).getParent() + .removeParamMapping(mapping.get().getObfuscatedName()); + } + } + MEMBERS.get(key).forEach(sm -> sm.setDeobfuscated(false)); } switch (getType()) { case CLASS: { - Optional mapping - = MappingsHelper.getClassMapping(Main.getMappingContext(), getName()); + Optional mapping = getMapping(); if (mapping.isPresent() && !mapping.get().getObfuscatedName().equals(mapping.get().getDeobfuscatedName())) { if ((!isInnerClass() && !checkClassDupe(mapping.get().getObfuscatedName())) @@ -166,6 +189,8 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de break; } mapping.get().setDeobfuscatedName(mapping.get().getObfuscatedName()); + mapping.get().setAdHoc(false); + setDeobfuscated(false); } fullName = getName(); break; @@ -175,14 +200,20 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de Optional parent = MappingsHelper.getClassMapping(Main.getMappingContext(), getParentClass()); if (parent.isPresent()) { - MemberMapping mapping = (getType() == MemberType.FIELD - ? parent.get().getFieldMappings() : parent.get().getMethodMappings()) - .get(sig); - if (mapping != null) { - if (!checkMemberDupe(mapping.getObfuscatedName())) { + Optional mapping = getMapping(); + if (mapping.isPresent()) { + if (!checkMemberDupe(mapping.get().getObfuscatedName())) { return; } - mapping.setDeobfuscatedName(mapping.getObfuscatedName()); + if (getType() == MemberType.FIELD) { + //noinspection ConstantConditions + parent.get().removeFieldMapping((FieldSignature) sig); + } else { + //noinspection ConstantConditions + parent.get().removeMethodMapping((MethodSignature) sig); + } + setDeobfuscated(false); + updateText(); } } break; @@ -197,8 +228,10 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de MenuItem toggleDeobf = new MenuItem(Main.getResourceBundle().getString("member.contextmenu.toggleDeobf")); toggleDeobf.setOnAction(event -> { - this.setDeobfuscated(!this.deobfuscated); - genMapping().setAdHoc(this.deobfuscated); // set as ad hoc if we've marked it as deobfuscated + // I know this is gross but it's a hell of a lot easier than fixing the problem the "proper" way + boolean shouldDeobf = !this.deobfuscated; + genMapping().setAdHoc(!this.deobfuscated); // set as ad hoc if we need to mark it as deobfuscated + MEMBERS.get(key).forEach(sm -> sm.setDeobfuscated(shouldDeobf)); }); MenuItem jumpToDefItem = new MenuItem(Main.getResourceBundle().getString("member.contextmenu.jumpToDef")); @@ -215,7 +248,7 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de contextMenu.getItems().add(jumpToDefItem); this.setOnContextMenuRequested(event -> { - Optional mapping = MappingsHelper.getClassMapping(Main.getMappingContext(), getClassName()); + Optional mapping = getMapping(); toggleDeobf.setDisable(mapping.isPresent() && !mapping.get().getObfuscatedName().equals(mapping.get().getDeobfuscatedName())); @@ -223,43 +256,6 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de }); - String qualName; - IndexedClass ic = IndexedClass.INDEXED_CLASSES.get(getParentClass()); - switch (type) { - case CLASS: - qualName = name; - break; - case FIELD: - //noinspection SuspiciousMethodCalls: sig must be a FieldSignature object - if (!ic.getFields().containsKey(sig)) { - throw new IllegalArgumentException(); - } - qualName = getParentClass() + CLASS_PATH_SEPARATOR_CHAR + name; - break; - case METHOD: - String parent = null; - //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object - if (ic.getMethods().containsKey(sig)) { - parent = getParentClass(); - } else { - for (IndexedClass hc : ic.getHierarchy()) { - //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object - if (hc.getMethods().containsKey(sig)) { - parent = hc.getName(); - break; - } - } - } - if (parent == null) { - throw new IllegalArgumentException(); //TODO - } - qualName = parent + CLASS_PATH_SEPARATOR_CHAR + name; - break; - default: - throw new AssertionError(); - } - MemberKey key = new MemberKey(type, qualName, - type == MemberType.FIELD || type == MemberType.METHOD ? descriptor : null); if (!MEMBERS.containsKey(key)) { MEMBERS.put(key, new ArrayList<>()); } @@ -570,4 +566,44 @@ private Optional getMapping() { } } + private String getQualifiedName() { + String qualName; + IndexedClass ic = IndexedClass.INDEXED_CLASSES.get(getParentClass()); + switch (type) { + case CLASS: + qualName = getName(); + break; + case FIELD: + //noinspection SuspiciousMethodCalls: sig must be a FieldSignature object + if (!ic.getFields().containsKey(sig)) { + throw new IllegalArgumentException(); + } + qualName = getParentClass() + CLASS_PATH_SEPARATOR_CHAR + getName(); + break; + case METHOD: + String parent = null; + //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object + if (ic.getMethods().containsKey(sig)) { + parent = getParentClass(); + } else { + for (IndexedClass hc : ic.getHierarchy()) { + //noinspection SuspiciousMethodCalls: sig must be a MethodSignature object + if (hc.getMethods().containsKey(sig)) { + parent = hc.getName(); + break; + } + } + } + if (parent == null) { + throw new IllegalArgumentException(); //TODO + } + qualName = parent + CLASS_PATH_SEPARATOR_CHAR + getName(); + break; + default: + throw new AssertionError(); + } + + return qualName; + } + } diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index 077c800..014d397 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -46,6 +46,7 @@ */ public class MethodMapping extends MemberMapping { + //TODO: this needs to have integers as keys. it doesn't make sense with strings. private final Map argumentMappings = new HashMap<>(); private final SelectableMember.MemberKey memberKey; private final MethodSignature sig; @@ -98,11 +99,15 @@ public ImmutableMap getParamMappings() { * @param propagate Whether to propagate this mapping to super- and * sub-classes */ - void addArgumentMapping(MethodParameterMapping mapping, boolean propagate) { + void addParamMapping(MethodParameterMapping mapping, boolean propagate) { mapping.initialize(propagate); argumentMappings.put(mapping.getObfuscatedName(), mapping); } + public void removeParamMapping(String name) { + argumentMappings.remove(name); + } + /** * Returns the {@link MethodDescriptor} of this method. * diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java index 9ee312f..00669a4 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodParameterMapping.java @@ -53,7 +53,7 @@ public MethodParameterMapping(MethodMapping parent, int index, String deobfName, this.parent = parent; this.index = index; - this.parent.addArgumentMapping(this, propagate); + this.parent.addParamMapping(this, propagate); } public void initialize(boolean propagate) { From 3bbc039827ea3a7d26a5c7eaff11887285a8386c Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:07:36 -0400 Subject: [PATCH 39/58] Fix bug with reset function --- .../lapis/nocturne/gui/scene/text/SelectableMember.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 2708b4c..040c016 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -212,8 +212,10 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de //noinspection ConstantConditions parent.get().removeMethodMapping((MethodSignature) sig); } - setDeobfuscated(false); - updateText(); + MEMBERS.get(key).forEach(sm -> { + sm.setDeobfuscated(false); + sm.updateText(); + }); } } break; From 001f630595dd286af91d132e11362b8e415a7644 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:15:15 -0400 Subject: [PATCH 40/58] Teach Nocturne not to merge mappings by default; add separate menu item for merging --- src/main/java/blue/lapis/nocturne/gui/MainController.java | 7 ++++++- .../nocturne/gui/io/mappings/MappingsOpenDialogHelper.java | 5 ++++- src/main/resources/fxml/main.fxml | 2 ++ src/main/resources/lang/de_DE.properties | 1 + src/main/resources/lang/en_US.properties | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index b10f4f8..29ad6e7 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -194,7 +194,12 @@ public void closeJar(ActionEvent actionEvent) throws IOException { } public void loadMappings(ActionEvent actionEvent) throws IOException { - MappingsOpenDialogHelper.openMappings(); + MappingsOpenDialogHelper.openMappings(false); + updateClassViews(); + } + + public void mergeMappings(ActionEvent actionEvent) throws IOException { + MappingsOpenDialogHelper.openMappings(true); updateClassViews(); } diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java index 4d76c03..10c04e8 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsOpenDialogHelper.java @@ -49,7 +49,7 @@ public final class MappingsOpenDialogHelper { private MappingsOpenDialogHelper() { } - public static void openMappings() throws IOException { + public static void openMappings(boolean merge) throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle(Main.getResourceBundle().getString("filechooser.open_mapping")); Arrays.asList(MappingReaderType.values()).forEach(t -> { @@ -81,6 +81,9 @@ public static void openMappings() throws IOException { .setProperty(PropertiesHelper.Key.LAST_MAPPING_LOAD_FORMAT, type.getFormatType().name()); try (MappingsReader reader = type.constructReader(new BufferedReader(new FileReader(selectedFile)))) { MappingContext context = reader.read(); + if (!merge) { + Main.getMappingContext().clear(); + } Main.getMappingContext().assimilate(context); MainController.INSTANCE.updateClassViews(); Main.getMappingContext().setDirty(false); diff --git a/src/main/resources/fxml/main.fxml b/src/main/resources/fxml/main.fxml index 6248acb..fb0c1ba 100644 --- a/src/main/resources/fxml/main.fxml +++ b/src/main/resources/fxml/main.fxml @@ -51,6 +51,8 @@ + Date: Sun, 11 Sep 2016 16:23:39 -0400 Subject: [PATCH 41/58] Update unit tests for code changes --- .../mapping/io/reader/ReaderTestHelper.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java index 7ced1b1..dcaacdf 100644 --- a/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java +++ b/src/test/java/blue/lapis/nocturne/test/mapping/io/reader/ReaderTestHelper.java @@ -40,6 +40,8 @@ import blue.lapis.nocturne.mapping.model.FieldMapping; import blue.lapis.nocturne.mapping.model.InnerClassMapping; import blue.lapis.nocturne.mapping.model.MethodMapping; +import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import java.io.IOException; @@ -112,8 +114,10 @@ void fieldTest() { assertTrue(mappings.getMappings().containsKey("a")); ClassMapping mapping = mappings.getMappings().get("a"); - assertTrue(mapping.getFieldMappings().containsKey("a")); - FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); + FieldSignature aSig = new FieldSignature("a", Type.fromString("I")); + + assertTrue(mapping.getFieldMappings().containsKey(aSig)); + FieldMapping fieldMapping = mapping.getFieldMappings().get(aSig); assertEquals("a", fieldMapping.getObfuscatedName()); assertEquals("someField", fieldMapping.getDeobfuscatedName()); } @@ -123,9 +127,12 @@ void fieldInnerClassTest() { assertTrue(mappings.getMappings().get("a").getInnerClassMappings().containsKey("b")); ClassMapping mapping = mappings.getMappings().get("a").getInnerClassMappings().get("b"); - assertTrue(mapping.getFieldMappings().containsKey("a")); - FieldMapping fieldMapping = mapping.getFieldMappings().get("a"); + FieldSignature aSig = new FieldSignature("a", Type.fromString("I")); + + assertTrue(mapping.getFieldMappings().containsKey(aSig)); + + FieldMapping fieldMapping = mapping.getFieldMappings().get(aSig); assertEquals("a", fieldMapping.getObfuscatedName()); assertEquals("someInnerField", fieldMapping.getDeobfuscatedName()); } @@ -136,9 +143,12 @@ void fieldNestedInnerClassTest() { ClassMapping inner = mappings.getMappings().get("a").getInnerClassMappings().get("b"); assertTrue(inner.getInnerClassMappings().containsKey("c")); ClassMapping deeper = inner.getInnerClassMappings().get("c"); - assertTrue(deeper.getFieldMappings().containsKey("a")); - FieldMapping fieldMapping = deeper.getFieldMappings().get("a"); + FieldSignature aSig = new FieldSignature("a", Type.fromString("I")); + + assertTrue(deeper.getFieldMappings().containsKey(aSig)); + + FieldMapping fieldMapping = deeper.getFieldMappings().get(aSig); assertEquals("a", fieldMapping.getObfuscatedName()); assertEquals("someDeeperField", fieldMapping.getDeobfuscatedName()); } @@ -147,9 +157,10 @@ void methodTest() { assertTrue(mappings.getMappings().containsKey("a")); ClassMapping mapping = mappings.getMappings().get("a"); - assertTrue(mapping.getMethodMappings().containsKey("a(ILa;I)La;")); + MethodSignature aSig = new MethodSignature("a", MethodDescriptor.fromString("(ILa;I)La;")); + assertTrue(mapping.getMethodMappings().containsKey(aSig)); - MethodMapping methodMapping = mapping.getMethodMappings().get("a(ILa;I)La;"); + MethodMapping methodMapping = mapping.getMethodMappings().get(aSig); assertEquals("a", methodMapping.getObfuscatedName()); assertEquals("someMethod", methodMapping.getDeobfuscatedName()); assertArrayEquals( From f6b42997338b02d06621eeea3df63376926f3353 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:24:33 -0400 Subject: [PATCH 42/58] Disable indentiation checks since checkstyle is still broken --- etc/checkstyle-suppressions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/checkstyle-suppressions.xml b/etc/checkstyle-suppressions.xml index 29d0b1e..76f481a 100644 --- a/etc/checkstyle-suppressions.xml +++ b/etc/checkstyle-suppressions.xml @@ -4,7 +4,7 @@ - + From d700e226ceef488bdebb7910b3249b7a09173ba4 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:31:21 -0400 Subject: [PATCH 43/58] Fix TextFlow not rendering horizontal scrollbar. Fixes #19. --- src/main/resources/fxml/CodeTab.fxml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/fxml/CodeTab.fxml b/src/main/resources/fxml/CodeTab.fxml index b513896..e1da093 100644 --- a/src/main/resources/fxml/CodeTab.fxml +++ b/src/main/resources/fxml/CodeTab.fxml @@ -58,7 +58,7 @@ - + From ed14199c97c37b8a0a0eae4a3a721519e45feddb Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:36:17 -0400 Subject: [PATCH 44/58] Properly integrate merge button throughout codebase --- .../lapis/nocturne/gui/MainController.java | 12 ++++ .../nocturne/gui/io/jar/JarDialogHelper.java | 1 + src/main/resources/fxml/CodeTab.fxml | 58 +++++++++---------- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index 29ad6e7..7f43a06 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -79,6 +79,7 @@ public class MainController implements Initializable { public MenuItem openJarButton; public MenuItem closeJarButton; public MenuItem loadMappingsButton; + public MenuItem mergeMappingsButton; public MenuItem saveMappingsButton; public MenuItem saveMappingsAsButton; public MenuItem closeButton; @@ -102,6 +103,7 @@ public MainController() { public void initialize(URL location, ResourceBundle resources) { closeJarButton.setDisable(Main.getLoadedJar() == null); loadMappingsButton.setDisable(Main.getLoadedJar() == null); + mergeMappingsButton.setDisable(Main.getLoadedJar() == null); saveMappingsButton.setDisable(Main.getLoadedJar() == null); saveMappingsAsButton.setDisable(Main.getLoadedJar() == null); resetMappingsButton.setDisable(Main.getLoadedJar() == null); @@ -161,6 +163,8 @@ private void initTreeViews() { private void setAccelerators() { openJarButton.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.CONTROL_DOWN)); loadMappingsButton.setAccelerator(new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN)); + mergeMappingsButton.setAccelerator(new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, + KeyCombination.ALT_DOWN)); saveMappingsButton.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN)); saveMappingsAsButton.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN, KeyCombination.ALT_DOWN)); @@ -183,6 +187,7 @@ public void closeJar(ActionEvent actionEvent) throws IOException { closeJarButton.setDisable(true); loadMappingsButton.setDisable(true); + mergeMappingsButton.setDisable(true); saveMappingsButton.setDisable(true); saveMappingsAsButton.setDisable(true); resetMappingsButton.setDisable(true); @@ -194,6 +199,13 @@ public void closeJar(ActionEvent actionEvent) throws IOException { } public void loadMappings(ActionEvent actionEvent) throws IOException { + try { + if (MappingsSaveDialogHelper.doDirtyConfirmation()) { + return; + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } MappingsOpenDialogHelper.openMappings(false); updateClassViews(); } diff --git a/src/main/java/blue/lapis/nocturne/gui/io/jar/JarDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/jar/JarDialogHelper.java index bd1faea..2d3d4e9 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/jar/JarDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/jar/JarDialogHelper.java @@ -89,6 +89,7 @@ public static void openJar(MainController controller) throws IOException { if (classSet != null) { controller.closeJarButton.setDisable(false); controller.loadMappingsButton.setDisable(false); + controller.mergeMappingsButton.setDisable(false); controller.saveMappingsAsButton.setDisable(false); controller.resetMappingsButton.setDisable(false); } diff --git a/src/main/resources/fxml/CodeTab.fxml b/src/main/resources/fxml/CodeTab.fxml index e1da093..6d76f37 100644 --- a/src/main/resources/fxml/CodeTab.fxml +++ b/src/main/resources/fxml/CodeTab.fxml @@ -33,34 +33,32 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + From 32f013e47c0852af21762da7c33d1862143633fe Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 16:48:06 -0400 Subject: [PATCH 45/58] Fix mappings not being properly reset --- .../lapis/nocturne/gui/MainController.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index 7f43a06..c0b4268 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -223,11 +223,27 @@ public void resetMappings(ActionEvent actionEvent) { } catch (IOException ex) { throw new RuntimeException(ex); } + Main.getMappingContext().getMappings().values().forEach(cm -> { + Main.getLoadedJar().getCurrentNames().put(cm.getObfuscatedName(), cm.getObfuscatedName()); + JarClassEntry jce = Main.getLoadedJar().getClass(cm.getObfuscatedName()).orElse(null); + if (jce == null) { + return; + } + cm.getInnerClassMappings().values() + .forEach(im -> jce.getCurrentInnerClassNames().put(im.getObfuscatedName(), im.getObfuscatedName())); + cm.getFieldMappings().values() + .forEach(fm -> jce.getCurrentFields().put(fm.getSignature(), fm.getSignature())); + cm.getMethodMappings().values() + .forEach(mm -> jce.getCurrentMethods().put(mm.getSignature(), mm.getSignature())); + }); Main.getMappingContext().clear(); Main.getLoadedJar().getClasses().forEach(jce -> jce.setDeobfuscated(false)); CodeTab.CODE_TABS.values().forEach(CodeTab::resetClassName); SelectableMember.MEMBERS.values() - .forEach(list -> list.forEach(member -> member.setAndProcessText(member.getName()))); + .forEach(list -> list.forEach(member -> { + member.setAndProcessText(member.getName()); + member.setDeobfuscated(false); + })); updateClassViews(); } From d4117e4459c780b01f1bd2ac81864cfab1eb519c Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Sun, 11 Sep 2016 22:17:46 +0100 Subject: [PATCH 46/58] Fix Enigma inner class support --- .../lapis/nocturne/mapping/io/reader/EnigmaReader.java | 1 - .../lapis/nocturne/mapping/io/writer/EnigmaWriter.java | 2 +- src/test/resources/mappings/example.eng | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java index 27762ec..668f26f 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/reader/EnigmaReader.java @@ -107,7 +107,6 @@ public MappingContext read() { String deobf = arr.length == 3 ? removeNonePrefix(arr[2]) : obf; if (lastIndentLevel != -1 && indentLevel > lastIndentLevel) { - obf = classStack.peek().getFullObfuscatedName() + INNER_CLASS_SEPARATOR_CHAR + obf; deobf = classStack.peek().getFullDeobfuscatedName() + INNER_CLASS_SEPARATOR_CHAR + deobf; } classStack.push(MappingsHelper.genClassMapping(mappings, obf, deobf, false)); diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index 26db472..a73e6a1 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -72,7 +72,7 @@ protected void writeClassMapping(ClassMapping classMapping, int depth) { } } else { out.println(getIndentForDepth(depth) + "CLASS " - + (inner ? classMapping.getObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + " " + + (inner ? classMapping.getFullObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + " " + (inner ? classMapping.getDeobfuscatedName() : addNonePrefix(classMapping.getDeobfuscatedName()))); } diff --git a/src/test/resources/mappings/example.eng b/src/test/resources/mappings/example.eng index a4eb5f1..7619adc 100644 --- a/src/test/resources/mappings/example.eng +++ b/src/test/resources/mappings/example.eng @@ -1,10 +1,10 @@ CLASS none/a com/example/project/Example - CLASS b Inner - CLASS c Deeper + CLASS none/a$b Inner + CLASS none/a$b$c Deeper FIELD a someDeeperField I FIELD a someInnerField I FIELD a someField I METHOD a someMethod (ILnone/a;I)Lnone/a; CLASS none/b com/example/project/Another - CLASS a Inner - CLASS c Deeper + CLASS none/b$a Inner + CLASS none/b$a$c Deeper From a9511dd0427024dc5c868e0527450a45fc141aa5 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 19:34:37 -0400 Subject: [PATCH 47/58] Update de_DE locale --- src/main/resources/lang/de_DE.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 446eb95..03d92a5 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -3,7 +3,7 @@ menu.file=_Datei menu.file.open_jar=_JAR \u00f6ffnen menu.file.close_jar=_Aktuelle JAR schlie\u00dfen menu.file.load_mappings=Zuordnungen _laden -menu.file.merge_mappings=Load and _Merge Mappings +menu.file.merge_mappings=Zuordnungen laden und _vereinigen menu.file.save_mappings=Zuordnungen _speichern menu.file.save_mappings_as=Zuordnungen speichern _Als menu.file.close=Schlie\u00dfen @@ -29,7 +29,7 @@ codetab.identifier.arg=Argument member.contextmenu.rename=Umbenennen member.contextmenu.reset=Zur\u00fccksetzen -member.contextmenu.toggleDeobf=Toggle Deobfuscated +member.contextmenu.toggleDeobf=Entschleierte umschalten member.contextmenu.jumpToDef=Springen zu definieren-Klasse about.title=\u00dcber Nocturne From aa7aa38810816e8ad5eed5e5c6a1a2c56fde692b Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 11 Sep 2016 19:43:54 -0400 Subject: [PATCH 48/58] Bump version for RC --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f1e7670..4585f7f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ defaultTasks 'clean', 'licenseFormat', 'build' // Project information allprojects { group = 'blue.lapis.nocturne' - version = '1.1.0-SNAPSHOT' + version = '1.1.0-rc1' sourceCompatibility = '1.8' targetCompatibility = '1.8' From 0fb75be4aa5b6702e771baf3a33df9c519419f26 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 12 Sep 2016 10:25:12 -0400 Subject: [PATCH 49/58] Use interface constants for FernFlower options --- build.gradle | 2 +- src/main/java/blue/lapis/nocturne/util/Constants.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 4585f7f..f1e7670 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ defaultTasks 'clean', 'licenseFormat', 'build' // Project information allprojects { group = 'blue.lapis.nocturne' - version = '1.1.0-rc1' + version = '1.1.0-SNAPSHOT' sourceCompatibility = '1.8' targetCompatibility = '1.8' diff --git a/src/main/java/blue/lapis/nocturne/util/Constants.java b/src/main/java/blue/lapis/nocturne/util/Constants.java index 970a2a9..dca4523 100644 --- a/src/main/java/blue/lapis/nocturne/util/Constants.java +++ b/src/main/java/blue/lapis/nocturne/util/Constants.java @@ -29,6 +29,7 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import java.util.regex.Pattern; @@ -64,8 +65,8 @@ public final class Constants { public static final Pattern TYPE_SEQUENCE_REGEX = Pattern.compile("(\\[*(?:(?:L.+?;)|.))"); public static final ImmutableMap FF_OPTIONS = ImmutableMap.builder() - .put("rsy", "1") // hide synthetic class members - .put("ind", " ") // set indentation string + .put(IFernflowerPreferences.REMOVE_SYNTHETIC, "1") + .put(IFernflowerPreferences.INDENT_STRING, " ") .build(); public static final String ENIGMA_ROOT_PACKAGE_PREFIX = "none/"; From 08bf5ac69c42e422a64a70afbd2e0b15c182c0ab Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 12 Sep 2016 10:37:48 -0400 Subject: [PATCH 50/58] Add es_ES and ar_SA locales; update existing locales --- .../nocturne/gui/scene/control/CodeTab.java | 2 +- src/main/resources/fxml/main.fxml | 8 +- src/main/resources/lang/ar_SA.properties | 77 +++++++++++++++++++ src/main/resources/lang/de_DE.properties | 5 +- src/main/resources/lang/en_US.properties | 5 +- src/main/resources/lang/es_ES.properties | 77 +++++++++++++++++++ 6 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/lang/ar_SA.properties create mode 100644 src/main/resources/lang/es_ES.properties diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java b/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java index 4f290b7..7f89190 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/control/CodeTab.java @@ -161,7 +161,7 @@ public void setCode(String code) { public enum SelectableMemberType { FIELD("codetab.identifier.field", "codetab.identifier.type"), METHOD("codetab.identifier.method", "codetab.identifier.descriptor"), - ARG("codetab.identifier.arg", "codetab.identifier.type"), + ARG("codetab.identifier.param", "codetab.identifier.type"), CLASS("codetab.identifier.class"), ; diff --git a/src/main/resources/fxml/main.fxml b/src/main/resources/fxml/main.fxml index fb0c1ba..1dd08d8 100644 --- a/src/main/resources/fxml/main.fxml +++ b/src/main/resources/fxml/main.fxml @@ -67,14 +67,20 @@

+ text="العربية" id="langRadio-ar_SA"> + + + + diff --git a/src/main/resources/lang/ar_SA.properties b/src/main/resources/lang/ar_SA.properties new file mode 100644 index 0000000..b081202 --- /dev/null +++ b/src/main/resources/lang/ar_SA.properties @@ -0,0 +1,77 @@ +#X-Generator: crowdin.com +menu.file=_\u0645\u0644\u0641 +menu.file.open_jar=_\u0627\u0641\u062a\u062d JAR +menu.file.close_jar=_\u0623\u063a\u0644\u0650\u0642 JAR \u0627\u0644\u062d\u0627\u0644\u064a +menu.file.load_mappings=_\u062a\u062d\u0645\u064a\u0644 \u0631\u0633\u0645 \u0627\u0644\u062e\u0631\u0627\u0626\u0637 +menu.file.merge_mappings=Load and _Merge Mappings +menu.file.save_mappings=_\u062d\u0641\u0638 \u0631\u0633\u0645 \u0627\u0644\u062e\u0631\u0627\u0626\u0637 +menu.file.save_mappings_as=\u062d\u0641\u0638 \u0631\u0633\u0645 \u0627\u0644\u062e\u0631\u0627\u0626\u0637 _\u0628\u0634\u0643\u0644 +menu.file.close=\u0623\u063a\u0644\u0650\u0642 + +menu.edit=_\u062a\u0639\u062f\u064a\u0644 +menu.file.reset_mappings=_Reset All Mappings + +menu.language=_\u0627\u0644\u0644\u063a\u0629 + +menu.help=_\u0645\u0633\u0627\u0639\u062f\u0629 +menu.help.about=_\u062d\u0648\u0644 + +classes.obfuscated=Obfuscated Classes +classes.deobfuscated=Deobfuscated Classes + +codetab.identifier=Identifier Info +codetab.identifier.field=Field +codetab.identifier.type=Type +codetab.identifier.method=Method +codetab.identifier.descriptor=Descriptor +codetab.identifier.class=Class +codetab.identifier.param=Parameter + +member.contextmenu.rename=Rename +member.contextmenu.reset=Reset +member.contextmenu.toggleDeobf=Toggle Deobfuscated +member.contextmenu.jumpToDef=Jump to Defining Class + +about.title=About Nocturne +about.copyright=Copyright +about.description=A graphical tool for creation of Java deobfuscation mappings. +about.license=Nocturne is open source software available under the MIT License. +about.github=The source code is available on GitHub. + +filechooser.type_jar=JAR Files +filechooser.type_srg=SRG Files +filechooser.type_jam=JAM Files +filechooser.type_enigma=Enigma Files +filechooser.type_all=All Files +filechooser.open_jar=Select JAR File +filechooser.open_mapping=Select Mapping File +filechooser.save_mapping=Select Destination File +filechooser.dirty.title=Save? +filechooser.dirty.content=Would you like to save the current mappings? + +exception.title=Aw, rats\! +exception.header=Something has broken inside Nocturne\! \:( +exception.dialog1=You may click "OK" to continue work within the program, or "Close" to exit. +exception.dialog2=You will lose all unsaved work if you exit\! +exception.dialog3=If you believe this to be a bug, please report it here\: +exception.dialog4=Below is a stack trace of the uncaught exception\: + +jarload.invalid=Failed to read JAR file\! (Maybe it's invalid?) +jarload.empty=No class entries were found in the selected JAR file. Not loading. + +rename.dupe.title=Duplicate member name +rename.dupe.content=A member with the specified name already exists\! +rename.dupe.content.hierarchy=A member with the specified name already exists in this method's hierarchy\! + +rename.illegal.title=Illegal member name +rename.illegal.content=The provided name is not a legal Java identifier. + +dialog.load_jar.title=Loading JAR +dialog.load_jar.content=Loading JAR file, please wait... + +dialog.decompile.title=Decompiling class +dialog.decompile.content=Decompiling class file, please wait... + +dialog.restart.title=Restart required +dialog.restart.content=You must restart Nocturne for this change to take effect. + diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 03d92a5..55bbf97 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -25,7 +25,7 @@ codetab.identifier.type=Typ codetab.identifier.method=Methode codetab.identifier.descriptor=Deskriptor codetab.identifier.class=Klasse -codetab.identifier.arg=Argument +codetab.identifier.param=Parameter member.contextmenu.rename=Umbenennen member.contextmenu.reset=Zur\u00fccksetzen @@ -49,9 +49,6 @@ filechooser.save_mapping=Zieldatei ausw\u00e4hlen filechooser.dirty.title=Speichern? filechooser.dirty.content=M\u00f6chtest du die gegenw\u00e4rtig Zuordnungen speichern? -enigma.support_notice=The parsing of Enigma files, is a flawed part of Nocturne however is provided to allow people \ - to convert their mappings. It may very well fail! - exception.title=Och N\u00f6\! exception.header=Etwas in Nocturne is kaputt\! \:( exception.dialog1=Du kannst "OK" zum Fortfahren oder "Schlie\u00dfen" zum Beenden klicken. diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 076f9e2..2b28d9c 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -24,7 +24,7 @@ codetab.identifier.type=Type codetab.identifier.method=Method codetab.identifier.descriptor=Descriptor codetab.identifier.class=Class -codetab.identifier.arg=Argument +codetab.identifier.param=Parameter member.contextmenu.rename=Rename member.contextmenu.reset=Reset @@ -48,9 +48,6 @@ filechooser.save_mapping=Select Destination File filechooser.dirty.title=Save? filechooser.dirty.content=Would you like to save the current mappings? -enigma.support_notice=The parsing of Enigma files, is a flawed part of Nocturne however is provided to allow people \ - to convert their mappings. It may very well fail! - exception.title=Aw, rats! exception.header=Something has broken inside Nocturne! :( exception.dialog1=You may click "OK" to continue work within the program, or "Close" to exit. diff --git a/src/main/resources/lang/es_ES.properties b/src/main/resources/lang/es_ES.properties new file mode 100644 index 0000000..d8c86cd --- /dev/null +++ b/src/main/resources/lang/es_ES.properties @@ -0,0 +1,77 @@ +#X-Generator: crowdin.com +menu.file=_Archivo +menu.file.open_jar=_Abrir JAR +menu.file.close_jar=_Cerrar este JAR +menu.file.load_mappings=_Cargar mapeado +menu.file.merge_mappings=Load and _Merge Mappings +menu.file.save_mappings=_Guardar mapeado +menu.file.save_mappings_as=Guardar mapeado _como +menu.file.close=Cerrar + +menu.edit=_Editar +menu.file.reset_mappings=_Reiniciar todos los mapeados + +menu.language=_Idioma + +menu.help=_Ayuda +menu.help.about=_Acerca de + +classes.obfuscated=Clases Ofuscadas +classes.deobfuscated=Clases Desofuscadas + +codetab.identifier=Informaci\u00f3n del identificador +codetab.identifier.field=Campo +codetab.identifier.type=Tipo +codetab.identifier.method=M\u00e9todo +codetab.identifier.descriptor=Descriptor +codetab.identifier.class=Clase +codetab.identifier.param=Parameter + +member.contextmenu.rename=Renombrar +member.contextmenu.reset=Reiniciar +member.contextmenu.toggleDeobf=Toggle Deobfuscated +member.contextmenu.jumpToDef=Saltar a clase en definici\u00f3n + +about.title=Acerca de Nocturne +about.copyright=Copyright +about.description=Una herramienta gr\u00e1fica para la creaci\u00f3n de mapeos de deofuscaci\u00f3n de Java. +about.license=Nocturne es un software libre disponible bajo la licencia MIT. +about.github=El c\u00f3digo fuente est\u00e1 disponible en GitHub. + +filechooser.type_jar=Archivos JAR +filechooser.type_srg=Archivos SRG +filechooser.type_jam=JAM Files +filechooser.type_enigma=Archivos Enigma +filechooser.type_all=Todos los archivos +filechooser.open_jar=Seleccionar archivo JAR +filechooser.open_mapping=Seleccionar archivo de mapeado +filechooser.save_mapping=Seleccionar archivo de destino +filechooser.dirty.title=\u00bfGuardar? +filechooser.dirty.content=\u00bfQuieres guardar el mapeado actual? + +exception.title=\u00a1Oh, demonios\! +exception.header=\u00a1Algo de Nocturne ha fallado\! \:( +exception.dialog1=Puedes hacer clic en "Aceptar" para continuar con el programa o en "Cerrar" para salir. +exception.dialog2=\u00a1Perder\u00e1s todo tu trabajo si sales\! +exception.dialog3=Si crees que esto es un error, inf\u00f3rmanos de ello aqu\u00ed\: +exception.dialog4=A continuaci\u00f3n tienes unas cuantas excepciones no capturadas\: + +jarload.invalid=\u00a1No se ha podido leer el archivo JAR\! (\u00bftal vez no sea v\u00e1lido?) +jarload.empty=No se han encontrado entradas de clases en este archivo JAR. No se puede cargar. + +rename.dupe.title=Nombre de miembro duplicado +rename.dupe.content=\u00a1Ya existe un miembro con ese nombre\! +rename.dupe.content.hierarchy=\u00a1Ya existe un miembro con ese nombre en la jerarqu\u00eda de este m\u00e9todo\! + +rename.illegal.title=El nombre del miembro no es v\u00e1lido +rename.illegal.content=El nombre proporcionado no es un identificador Java v\u00e1lido. + +dialog.load_jar.title=Cargando JAR +dialog.load_jar.content=Cargando archivo JAR. Por favor, espera... + +dialog.decompile.title=Descompilando clase +dialog.decompile.content=Descompilado archivo de clase. Por favor, espera... + +dialog.restart.title=Es necesario reiniciar +dialog.restart.content=Tienes que reiniciar Nocturne para que este cambio surta efecto. + From 6ff3d9ef00eed1625cb8e6fd0e788a12361244b7 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 12 Sep 2016 10:40:12 -0400 Subject: [PATCH 51/58] Fix derp --- .../lapis/nocturne/gui/MainController.java | 3 ++- .../gui/scene/text/SelectableMember.java | 2 +- .../mapping/io/writer/EnigmaWriter.java | 3 ++- .../blue/lapis/nocturne/util/MemberType.java | 24 +------------------ 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index c0b4268..c8e60ee 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -308,7 +308,8 @@ public void updateObfuscatedClassListView() { public void updateDeobfuscatedClassListView() { if (Main.getLoadedJar() != null) { - TreeItem root = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy(), deobfTree.getRoot()); + TreeItem root + = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy(), deobfTree.getRoot()); root.setExpanded(true); deobfTree.setRoot(root); } else { diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 040c016..1e85dc8 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -461,7 +461,7 @@ private void updateText() { public static SelectableMember fromMatcher(CodeTab codeTab, Matcher matcher) { MemberType type = matcher.group().startsWith(CLASS_PREFIX) ? MemberType.CLASS - : MemberType.fromString(matcher.group(1)); + : MemberType.valueOf(matcher.group(1)); if (type == MemberType.CLASS) { return new SelectableMember(codeTab, type, matcher.group(1)); diff --git a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java index a73e6a1..852d964 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java +++ b/src/main/java/blue/lapis/nocturne/mapping/io/writer/EnigmaWriter.java @@ -72,7 +72,8 @@ protected void writeClassMapping(ClassMapping classMapping, int depth) { } } else { out.println(getIndentForDepth(depth) + "CLASS " - + (inner ? classMapping.getFullObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + " " + + (inner ? classMapping.getFullObfuscatedName() : addNonePrefix(classMapping.getObfuscatedName())) + + " " + (inner ? classMapping.getDeobfuscatedName() : addNonePrefix(classMapping.getDeobfuscatedName()))); } diff --git a/src/main/java/blue/lapis/nocturne/util/MemberType.java b/src/main/java/blue/lapis/nocturne/util/MemberType.java index ea48233..2d2d26a 100644 --- a/src/main/java/blue/lapis/nocturne/util/MemberType.java +++ b/src/main/java/blue/lapis/nocturne/util/MemberType.java @@ -25,10 +25,6 @@ package blue.lapis.nocturne.util; -import com.google.common.base.Preconditions; - -import java.util.HashMap; - /** * Represents a particular type of member. */ @@ -37,24 +33,6 @@ public enum MemberType { CLASS, FIELD, METHOD, - ARG; - - private static HashMap index; - - MemberType() { - addToIndex(); - } - - private void addToIndex() { - if (index == null) { - index = new HashMap<>(); - } - index.put(name(), this); - } - - public static MemberType fromString(String name) { - Preconditions.checkArgument(index.containsKey(name), "Invalid key for MemberType"); - return index.get(name); - } + ARG } From 3c4dc75c158593733674a3acf780adebdc75073c Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 13 Sep 2016 20:56:49 -0400 Subject: [PATCH 52/58] Avoid unecessary object creation when resetting mappings --- .../java/blue/lapis/nocturne/mapping/model/FieldMapping.java | 4 +++- .../java/blue/lapis/nocturne/mapping/model/MethodMapping.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 64a14e0..9cd03a4 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -31,6 +31,7 @@ import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; +import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.MemberType; /** @@ -79,7 +80,8 @@ public void setDeobfuscatedName(String deobf) { super.setDeobfuscatedName(deobf); Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentFields().put(sig, new FieldSignature(getDeobfuscatedName(), sig.getType())); + .getCurrentFields().put(sig, getObfuscatedName().equals(getDeobfuscatedName()) ? sig + : new FieldSignature(getDeobfuscatedName(), sig.getType())); } @Override diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java index 014d397..836d363 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/MethodMapping.java @@ -164,7 +164,8 @@ public void setDeobfuscatedName(String deobf, boolean propagate) { } Main.getLoadedJar().getClass(getParent().getFullObfuscatedName()).get() - .getCurrentMethods().put(sig, new MethodSignature(deobf, sig.getDescriptor())); + .getCurrentMethods().put(sig, getObfuscatedName().equals(getDeobfuscatedName()) ? sig + : new MethodSignature(getDeobfuscatedName(), sig.getDescriptor())); } } From 2ced3d9d39a8207678b739be5e4378b76f7f2236 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 25 Dec 2016 13:54:57 -0500 Subject: [PATCH 53/58] Add safeguard against null mapping writer type. Probably closes #26. --- .../gui/io/mappings/MappingsSaveDialogHelper.java | 14 ++++++++++++++ src/main/resources/lang/ar_SA.properties | 2 ++ src/main/resources/lang/de_DE.properties | 2 ++ src/main/resources/lang/en_US.properties | 2 ++ src/main/resources/lang/es_ES.properties | 2 ++ 5 files changed, 22 insertions(+) diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java index 937b635..6a4f231 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java @@ -28,8 +28,12 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; import blue.lapis.nocturne.mapping.io.writer.MappingsWriter; +import blue.lapis.nocturne.util.Constants; import blue.lapis.nocturne.util.helper.PropertiesHelper; +import blue.lapis.nocturne.util.helper.SceneHelper; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; @@ -95,6 +99,16 @@ public static boolean saveMappingsAs() throws IOException { final MappingWriterType writerType = MappingWriterType.fromExtensionFilter(fileChooser.getSelectedExtensionFilter()); + + if (writerType == null) { + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle(Main.getResourceBundle().getString("filechooser.no_extension.title")); + alert.setContentText(Main.getResourceBundle().getString("filechooser.no_extension")); + + alert.showAndWait(); + return false; + } + Main.setCurrentMappingsPath(selectedFile.toPath()); Main.setCurrentWriterType(writerType); diff --git a/src/main/resources/lang/ar_SA.properties b/src/main/resources/lang/ar_SA.properties index b081202..d5ff7b4 100644 --- a/src/main/resources/lang/ar_SA.properties +++ b/src/main/resources/lang/ar_SA.properties @@ -48,6 +48,8 @@ filechooser.open_mapping=Select Mapping File filechooser.save_mapping=Select Destination File filechooser.dirty.title=Save? filechooser.dirty.content=Would you like to save the current mappings? +filechooser.no_extension.title=Invalid extension filter +filechooser.no_extension=Invalid extension filter selected! exception.title=Aw, rats\! exception.header=Something has broken inside Nocturne\! \:( diff --git a/src/main/resources/lang/de_DE.properties b/src/main/resources/lang/de_DE.properties index 55bbf97..320bb90 100644 --- a/src/main/resources/lang/de_DE.properties +++ b/src/main/resources/lang/de_DE.properties @@ -48,6 +48,8 @@ filechooser.open_mapping=W\u00e4hle Zuordnungsdatei filechooser.save_mapping=Zieldatei ausw\u00e4hlen filechooser.dirty.title=Speichern? filechooser.dirty.content=M\u00f6chtest du die gegenw\u00e4rtig Zuordnungen speichern? +filechooser.no_extension.title=Invalid extension filter +filechooser.no_extension=Invalid extension filter selected! exception.title=Och N\u00f6\! exception.header=Etwas in Nocturne is kaputt\! \:( diff --git a/src/main/resources/lang/en_US.properties b/src/main/resources/lang/en_US.properties index 2b28d9c..15f066f 100644 --- a/src/main/resources/lang/en_US.properties +++ b/src/main/resources/lang/en_US.properties @@ -47,6 +47,8 @@ filechooser.open_mapping=Select Mapping File filechooser.save_mapping=Select Destination File filechooser.dirty.title=Save? filechooser.dirty.content=Would you like to save the current mappings? +filechooser.no_extension.title=Invalid extension filter +filechooser.no_extension=Invalid extension filter selected! exception.title=Aw, rats! exception.header=Something has broken inside Nocturne! :( diff --git a/src/main/resources/lang/es_ES.properties b/src/main/resources/lang/es_ES.properties index d8c86cd..52fd77d 100644 --- a/src/main/resources/lang/es_ES.properties +++ b/src/main/resources/lang/es_ES.properties @@ -48,6 +48,8 @@ filechooser.open_mapping=Seleccionar archivo de mapeado filechooser.save_mapping=Seleccionar archivo de destino filechooser.dirty.title=\u00bfGuardar? filechooser.dirty.content=\u00bfQuieres guardar el mapeado actual? +filechooser.no_extension.title=Invalid extension filter +filechooser.no_extension=Invalid extension filter selected! exception.title=\u00a1Oh, demonios\! exception.header=\u00a1Algo de Nocturne ha fallado\! \:( From 7bb2d9100f8571aa9399e0a5b829bd224d13af56 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 25 Dec 2016 14:23:11 -0500 Subject: [PATCH 54/58] Revert "Prevent the tree list collapsing every rename" This reverts commit 0381ce2fa0331756372ef0d94bc1bb6938bef72b. --- .../lapis/nocturne/gui/MainController.java | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index c8e60ee..b14059a 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -47,6 +47,7 @@ import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.Alert; +import javafx.scene.control.Dialog; import javafx.scene.control.MenuItem; import javafx.scene.control.RadioMenuItem; import javafx.scene.control.TabPane; @@ -66,6 +67,7 @@ import java.util.Optional; import java.util.ResourceBundle; import java.util.function.BiConsumer; +import java.util.stream.Collectors; /** * The main JavaFX controller. @@ -297,7 +299,7 @@ public void onLanguageSelect(ActionEvent actionEvent) throws IOException { public void updateObfuscatedClassListView() { if (Main.getLoadedJar() != null) { - TreeItem root = generateTreeItem(Main.getLoadedJar().getObfuscatedHierarchy(), obfTree.getRoot()); + TreeItem root = generateTreeItem(Main.getLoadedJar().getObfuscatedHierarchy()); root.setExpanded(true); obfTree.setRoot(root); } else { @@ -308,8 +310,7 @@ public void updateObfuscatedClassListView() { public void updateDeobfuscatedClassListView() { if (Main.getLoadedJar() != null) { - TreeItem root - = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy(), deobfTree.getRoot()); + TreeItem root = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy()); root.setExpanded(true); deobfTree.setRoot(root); } else { @@ -317,7 +318,7 @@ public void updateDeobfuscatedClassListView() { } } - public TreeItem generateTreeItem(HierarchyElement element, TreeItem oldTreeItem) { + public TreeItem generateTreeItem(HierarchyElement element) { TreeItem treeItem; if (element instanceof HierarchyNode) { HierarchyNode node = (HierarchyNode) element; @@ -329,27 +330,11 @@ public TreeItem generateTreeItem(HierarchyElement element, TreeItem("(root)"); } - if (oldTreeItem != null) { - treeItem.setExpanded(oldTreeItem.isExpanded()); - } if (element instanceof Hierarchy || (element instanceof HierarchyNode && !((HierarchyNode) element).isTerminal())) { - for (HierarchyNode node : element.getChildren()) { - if (oldTreeItem != null) { - boolean added = false; - for (TreeItem child : oldTreeItem.getChildren()) { - if (node.getDisplayName().equalsIgnoreCase(child.getValue())) { - treeItem.getChildren().add(this.generateTreeItem(node, child)); - added = true; - } - } - if (!added) { - treeItem.getChildren().add(this.generateTreeItem(node, null)); - } - } else { - treeItem.getChildren().add(this.generateTreeItem(node, null)); - } - } + treeItem.getChildren().addAll( + element.getChildren().stream().map(this::generateTreeItem).collect(Collectors.toList()) + ); } treeItem.getChildren().setAll(treeItem.getChildren().sorted((t1, t2) -> { boolean c1 = t1.getChildren().size() > 0; From 7cca6fb256528e1103f06f48628d08df31cb6482 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 25 Dec 2016 15:10:57 -0500 Subject: [PATCH 55/58] Re-implement tree expansion memory. Closes #27. --- .../lapis/nocturne/gui/MainController.java | 62 ++++++++++++++----- ...reeItem.java => IdentifiableTreeItem.java} | 4 +- 2 files changed, 47 insertions(+), 19 deletions(-) rename src/main/java/blue/lapis/nocturne/gui/scene/control/{ClassTreeItem.java => IdentifiableTreeItem.java} (91%) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index b14059a..a022f5c 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -31,7 +31,7 @@ import blue.lapis.nocturne.gui.io.jar.JarDialogHelper; import blue.lapis.nocturne.gui.io.mappings.MappingsOpenDialogHelper; import blue.lapis.nocturne.gui.io.mappings.MappingsSaveDialogHelper; -import blue.lapis.nocturne.gui.scene.control.ClassTreeItem; +import blue.lapis.nocturne.gui.scene.control.IdentifiableTreeItem; import blue.lapis.nocturne.gui.scene.control.CodeTab; import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.JarClassEntry; @@ -42,12 +42,12 @@ import blue.lapis.nocturne.util.helper.PropertiesHelper; import blue.lapis.nocturne.util.helper.SceneHelper; +import com.google.common.collect.Maps; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.Alert; -import javafx.scene.control.Dialog; import javafx.scene.control.MenuItem; import javafx.scene.control.RadioMenuItem; import javafx.scene.control.TabPane; @@ -64,8 +64,12 @@ import java.io.IOException; import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.ResourceBundle; +import java.util.Set; import java.util.function.BiConsumer; import java.util.stream.Collectors; @@ -136,8 +140,8 @@ private void initTreeViews() { return; } - if (selected instanceof ClassTreeItem) { - String className = ((ClassTreeItem) selected).getId(); + if (selected instanceof IdentifiableTreeItem) { + String className = ((IdentifiableTreeItem) selected).getId().substring(1); if (Main.getLoadedJar() != null) { openTab(className, selected.getValue()); } @@ -299,7 +303,8 @@ public void onLanguageSelect(ActionEvent actionEvent) throws IOException { public void updateObfuscatedClassListView() { if (Main.getLoadedJar() != null) { - TreeItem root = generateTreeItem(Main.getLoadedJar().getObfuscatedHierarchy()); + TreeItem root = generateTreeItem(Main.getLoadedJar().getObfuscatedHierarchy(), + getExpandedIds((IdentifiableTreeItem) obfTree.getRoot())); root.setExpanded(true); obfTree.setRoot(root); } else { @@ -310,7 +315,8 @@ public void updateObfuscatedClassListView() { public void updateDeobfuscatedClassListView() { if (Main.getLoadedJar() != null) { - TreeItem root = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy()); + TreeItem root = generateTreeItem(Main.getLoadedJar().getDeobfuscatedHierarchy(), + getExpandedIds((IdentifiableTreeItem) deobfTree.getRoot())); root.setExpanded(true); deobfTree.setRoot(root); } else { @@ -318,23 +324,23 @@ public void updateDeobfuscatedClassListView() { } } - public TreeItem generateTreeItem(HierarchyElement element) { - TreeItem treeItem; + public TreeItem generateTreeItem(HierarchyElement element, Set expanded) { + IdentifiableTreeItem treeItem; if (element instanceof HierarchyNode) { HierarchyNode node = (HierarchyNode) element; - if (node.isTerminal()) { - treeItem = new ClassTreeItem(node.getId(), node.getDisplayName()); - } else { - treeItem = new TreeItem<>(node.getDisplayName()); - } + treeItem = new IdentifiableTreeItem((node.isTerminal() ? "C" : "P") + node.getId(), node.getDisplayName()); } else { - treeItem = new TreeItem<>("(root)"); + treeItem = new IdentifiableTreeItem("//root", "(root)"); + } + + if (expanded.contains(treeItem.getId())) { + treeItem.setExpanded(true); } + if (element instanceof Hierarchy || (element instanceof HierarchyNode && !((HierarchyNode) element).isTerminal())) { - treeItem.getChildren().addAll( - element.getChildren().stream().map(this::generateTreeItem).collect(Collectors.toList()) - ); + treeItem.getChildren().addAll(element.getChildren().stream() + .map(e -> this.generateTreeItem(e, expanded)).collect(Collectors.toList())); } treeItem.getChildren().setAll(treeItem.getChildren().sorted((t1, t2) -> { boolean c1 = t1.getChildren().size() > 0; @@ -390,4 +396,26 @@ public static boolean isInitialized() { return INSTANCE != null; } + private static Map flatten(IdentifiableTreeItem tree) { + Map map = new HashMap<>(); + map.put(tree.getId(), tree); + if (tree.getChildren().isEmpty()) { + return map; + } + + for (TreeItem child : tree.getChildren()) { + map.putAll(flatten((IdentifiableTreeItem) child)); + } + return map; + } + + private static Set getExpandedIds(IdentifiableTreeItem tree) { + if (tree == null) { + return Collections.emptySet(); + } + + return flatten(tree).entrySet().stream().filter(e -> e.getValue().isExpanded()).map(Map.Entry::getKey) + .collect(Collectors.toSet()); + } + } diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/control/ClassTreeItem.java b/src/main/java/blue/lapis/nocturne/gui/scene/control/IdentifiableTreeItem.java similarity index 91% rename from src/main/java/blue/lapis/nocturne/gui/scene/control/ClassTreeItem.java rename to src/main/java/blue/lapis/nocturne/gui/scene/control/IdentifiableTreeItem.java index 1eae157..3911752 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/control/ClassTreeItem.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/control/IdentifiableTreeItem.java @@ -27,11 +27,11 @@ import javafx.scene.control.TreeItem; -public class ClassTreeItem extends TreeItem { +public class IdentifiableTreeItem extends TreeItem { private final String id; - public ClassTreeItem(String id, String displayName) { + public IdentifiableTreeItem(String id, String displayName) { this.setValue(displayName); this.id = id; } From 0ef022915a8a06f9418756dde039532610e55a32 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 26 Dec 2016 15:29:24 -0500 Subject: [PATCH 56/58] Fix packages in tree hierarchy having wrong IDs --- src/main/java/blue/lapis/nocturne/gui/MainController.java | 2 +- .../blue/lapis/nocturne/jar/model/hierarchy/Hierarchy.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index a022f5c..c8c9072 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -140,7 +140,7 @@ private void initTreeViews() { return; } - if (selected instanceof IdentifiableTreeItem) { + if (selected.getChildren().isEmpty()) { String className = ((IdentifiableTreeItem) selected).getId().substring(1); if (Main.getLoadedJar() != null) { openTab(className, selected.getValue()); diff --git a/src/main/java/blue/lapis/nocturne/jar/model/hierarchy/Hierarchy.java b/src/main/java/blue/lapis/nocturne/jar/model/hierarchy/Hierarchy.java index 408c175..00b6c04 100644 --- a/src/main/java/blue/lapis/nocturne/jar/model/hierarchy/Hierarchy.java +++ b/src/main/java/blue/lapis/nocturne/jar/model/hierarchy/Hierarchy.java @@ -53,11 +53,13 @@ public static Hierarchy fromSet(Set entries, boolean deobfuscated String[] arr = CLASS_PATH_SEPARATOR_PATTERN.split(fullName); HierarchyElement parent = root; + StringBuilder qual = new StringBuilder(); for (int i = 0; i < arr.length - 1; i++) { - if (parent != null && parent.getChild(arr[i], false).isPresent()) { + qual.append(arr[i]); + if (parent.getChild(arr[i], false).isPresent()) { parent = parent.getChild(arr[i], false).get(); } else { - parent = new HierarchyNode(id, arr[i], false, parent); + parent = new HierarchyNode(qual.toString(), arr[i], false, parent); } } new HierarchyNode(id, arr[arr.length - 1], true, parent); From 3d9ed98d6cace06a589f26061286176db298edca Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Mon, 26 Dec 2016 15:40:00 -0500 Subject: [PATCH 57/58] Fix names of classes in packages always being marked deobfuscated --- .../lapis/nocturne/gui/scene/text/SelectableMember.java | 2 +- .../blue/lapis/nocturne/mapping/model/ClassMapping.java | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java index 1e85dc8..5f981eb 100644 --- a/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java +++ b/src/main/java/blue/lapis/nocturne/gui/scene/text/SelectableMember.java @@ -266,7 +266,7 @@ public SelectableMember(CodeTab codeTab, MemberType type, String name, String de updateText(); Optional mapping = getMapping(); - setDeobfuscated(!getName().equals(getText()) || (mapping.isPresent() && mapping.get().isAdHoc())); + setDeobfuscated(!getName().equals(fullName) || (mapping.isPresent() && mapping.get().isAdHoc())); } private String getClassName() { diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java index 29f1aec..6bca435 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/ClassMapping.java @@ -195,7 +195,7 @@ public void setDeobfuscatedName(String name, boolean updateClassViews) { String unqualName = this instanceof InnerClassMapping ? name : StringHelper.unqualify(name); memberList.forEach(member -> { member.setText(unqualName); - member.setDeobfuscated(!unqualName.equals(member.getName())); + member.setDeobfuscated(!name.equals(member.getName())); }); if (updateClassViews) { @@ -206,9 +206,7 @@ public void setDeobfuscatedName(String name, boolean updateClassViews) { private void updateEntryDeobfuscation() { if (Main.getInstance() != null && Main.getLoadedJar() != null) { // first check is to fix stupid unit tests Optional classEntry = Main.getLoadedJar().getClass(getFullObfuscatedName()); - if (classEntry.isPresent()) { - classEntry.get().setDeobfuscated(!getObfuscatedName().equals(getDeobfuscatedName())); - } + classEntry.ifPresent(jce -> jce.setDeobfuscated(!getObfuscatedName().equals(getDeobfuscatedName()))); } } From 5c8bc8d618cb284b237b4d429ce5bce298f6fef4 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 27 Dec 2016 19:29:28 -0500 Subject: [PATCH 58/58] Bump version to release --- build.gradle | 2 +- src/main/java/blue/lapis/nocturne/gui/MainController.java | 3 +-- .../nocturne/gui/io/mappings/MappingsSaveDialogHelper.java | 4 ---- .../java/blue/lapis/nocturne/mapping/model/FieldMapping.java | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index f1e7670..9cd35b7 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ defaultTasks 'clean', 'licenseFormat', 'build' // Project information allprojects { group = 'blue.lapis.nocturne' - version = '1.1.0-SNAPSHOT' + version = '1.1.0' sourceCompatibility = '1.8' targetCompatibility = '1.8' diff --git a/src/main/java/blue/lapis/nocturne/gui/MainController.java b/src/main/java/blue/lapis/nocturne/gui/MainController.java index c8c9072..d8b32a9 100644 --- a/src/main/java/blue/lapis/nocturne/gui/MainController.java +++ b/src/main/java/blue/lapis/nocturne/gui/MainController.java @@ -31,8 +31,8 @@ import blue.lapis.nocturne.gui.io.jar.JarDialogHelper; import blue.lapis.nocturne.gui.io.mappings.MappingsOpenDialogHelper; import blue.lapis.nocturne.gui.io.mappings.MappingsSaveDialogHelper; -import blue.lapis.nocturne.gui.scene.control.IdentifiableTreeItem; import blue.lapis.nocturne.gui.scene.control.CodeTab; +import blue.lapis.nocturne.gui.scene.control.IdentifiableTreeItem; import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.JarClassEntry; import blue.lapis.nocturne.jar.model.hierarchy.Hierarchy; @@ -42,7 +42,6 @@ import blue.lapis.nocturne.util.helper.PropertiesHelper; import blue.lapis.nocturne.util.helper.SceneHelper; -import com.google.common.collect.Maps; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; diff --git a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java index 6a4f231..4c5a40f 100644 --- a/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java +++ b/src/main/java/blue/lapis/nocturne/gui/io/mappings/MappingsSaveDialogHelper.java @@ -28,12 +28,8 @@ import blue.lapis.nocturne.Main; import blue.lapis.nocturne.mapping.io.writer.MappingWriterType; import blue.lapis.nocturne.mapping.io.writer.MappingsWriter; -import blue.lapis.nocturne.util.Constants; import blue.lapis.nocturne.util.helper.PropertiesHelper; -import blue.lapis.nocturne.util.helper.SceneHelper; -import javafx.fxml.FXMLLoader; -import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; diff --git a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java index 9cd03a4..9c81081 100644 --- a/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java +++ b/src/main/java/blue/lapis/nocturne/mapping/model/FieldMapping.java @@ -31,7 +31,6 @@ import blue.lapis.nocturne.gui.scene.text.SelectableMember; import blue.lapis.nocturne.jar.model.attribute.Type; import blue.lapis.nocturne.processor.index.model.signature.FieldSignature; -import blue.lapis.nocturne.processor.index.model.signature.MethodSignature; import blue.lapis.nocturne.util.MemberType; /**