|
17 | 17 | import com.laytonsmith.core.Security; |
18 | 18 | import com.laytonsmith.core.Static; |
19 | 19 | import com.laytonsmith.core.constructs.CBoolean; |
| 20 | +import com.laytonsmith.core.compiler.analysis.StaticAnalysis; |
20 | 21 | import com.laytonsmith.core.constructs.CByteArray; |
21 | 22 | import com.laytonsmith.core.constructs.CDouble; |
22 | 23 | import com.laytonsmith.core.constructs.CInt; |
|
46 | 47 | import java.io.IOException; |
47 | 48 | import java.nio.charset.Charset; |
48 | 49 | import java.util.HashMap; |
| 50 | +import java.util.Map; |
49 | 51 | import java.util.Random; |
50 | 52 | import org.apache.commons.io.FileUtils; |
51 | 53 |
|
@@ -491,8 +493,9 @@ public Integer[] numArgs() { |
491 | 493 |
|
492 | 494 | @Override |
493 | 495 | public String docs() { |
494 | | - return "int {path} Reads and compiles specified *.ms files. This can be used for files already compiled" |
495 | | - + " with include(). Scripts that then include() these files will use the updated code." |
| 496 | + return "int {path} Recompiles specified files already compiled with include()." |
| 497 | + + " If there's no compile errors, scripts that then include() these files will use the updated code." |
| 498 | + + " Note that this bypasses Static Analysis, even if you have it enabled." |
496 | 499 | + " The path can be a directory or file. It is executed recursively through all subdirectories." |
497 | 500 | + " If there's a compile error in any of the files, the function will throw an exception and other" |
498 | 501 | + " scripts will continue to use the previous version of the code when included. Returns number" |
@@ -521,49 +524,48 @@ public Boolean runAsync() { |
521 | 524 |
|
522 | 525 | @Override |
523 | 526 | public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntimeException { |
524 | | - File file = Static.GetFileFromArgument(args[0].val(), env, t, null); |
525 | | - int num = 0; |
526 | 527 | try { |
527 | | - if(Static.InCmdLine(env, true) || Security.CheckSecurity(file)) { |
528 | | - IncludeCache includeCache = env.getEnv(StaticRuntimeEnv.class).getIncludeCache(); |
529 | | - if(file.isDirectory()) { |
530 | | - HashMap<File, ParseTree> files = compileDirectory(file, env, t); |
531 | | - includeCache.addAll(files); |
532 | | - num = files.size(); |
533 | | - } else if(includeCache.has(file)) { |
534 | | - includeCache.add(file, compileFile(file, env, t)); |
535 | | - num = 1; |
536 | | - } |
537 | | - } else { |
| 528 | + File file = Static.GetFileFromArgument(args[0].val(), env, t, null).getCanonicalFile(); |
| 529 | + if(!Static.InCmdLine(env, true) && !Security.CheckSecurity(file)) { |
538 | 530 | throw new CRESecurityException("The script cannot access " + file |
539 | 531 | + " due to restrictions imposed by the base-dir setting.", t); |
540 | 532 | } |
| 533 | + IncludeCache cache = env.getEnv(StaticRuntimeEnv.class).getIncludeCache(); |
| 534 | + if(file.isDirectory()) { |
| 535 | + Map<File, ParseTree> includes = new HashMap<>(); |
| 536 | + compileDirectory(includes, file, env, cache, t); |
| 537 | + cache.addAll(includes); |
| 538 | + return new CInt(includes.size(), t); |
| 539 | + } else if(cache.has(file)) { |
| 540 | + cache.add(file, compileFile(file, env, t)); |
| 541 | + return new CInt(1, t); |
| 542 | + } |
| 543 | + return new CInt(0, t); |
541 | 544 | } catch (IOException ex) { |
542 | 545 | throw new CREIOException(ex.getMessage(), t, ex); |
543 | 546 | } |
544 | | - return new CInt(num, t); |
545 | 547 | } |
546 | 548 |
|
547 | | - private HashMap<File, ParseTree> compileDirectory(File file, Environment env, Target t) { |
548 | | - HashMap<File, ParseTree> newFiles = new HashMap<>(); |
549 | | - File[] files = file.listFiles(); |
| 549 | + private void compileDirectory(Map<File, ParseTree> includes, File dir, Environment env, IncludeCache cache, Target t) { |
| 550 | + File[] files = dir.listFiles(); |
550 | 551 | if(files != null) { |
551 | | - IncludeCache includeCache = env.getEnv(StaticRuntimeEnv.class).getIncludeCache(); |
552 | 552 | for(File f : files) { |
553 | 553 | if(f.isDirectory()) { |
554 | | - newFiles.putAll(compileDirectory(f, env, t)); |
555 | | - } else if(includeCache.has(f)) { |
556 | | - newFiles.put(f, compileFile(f, env, t)); |
| 554 | + compileDirectory(includes, f, env, cache, t); |
| 555 | + } else if(cache.has(f)) { |
| 556 | + includes.put(f, compileFile(f, env, t)); |
557 | 557 | } |
558 | 558 | } |
559 | 559 | } |
560 | | - return newFiles; |
561 | 560 | } |
562 | 561 |
|
563 | 562 | private ParseTree compileFile(File file, Environment env, Target t) { |
564 | 563 | try { |
565 | 564 | String s = new ZipReader(file).getFileContents(); |
566 | | - return MethodScriptCompiler.compile(MethodScriptCompiler.lex(s, env, file, true), env, env.getEnvClasses()); |
| 565 | + StaticAnalysis staticAnalysis = new StaticAnalysis(true); |
| 566 | + staticAnalysis.setLocalDisabled(true); |
| 567 | + return MethodScriptCompiler.compile(MethodScriptCompiler.lex(s, env, file, true), env, env.getEnvClasses(), |
| 568 | + staticAnalysis); |
567 | 569 | } catch (ConfigCompileException ex) { |
568 | 570 | throw new CREIncludeException("There was a compile error when trying to recompile the script at " |
569 | 571 | + file + "\n" + ex.getMessage() + " :: " + file.getName() + ":" + ex.getLineNum(), t); |
|
0 commit comments