From d6d39eb6a37e27fca992497401b4356fa19edfb1 Mon Sep 17 00:00:00 2001 From: Ralf Sternberg Date: Fri, 3 May 2013 11:57:53 +0200 Subject: [PATCH] Move content to Eclipse.org, update README --- ClientBuilder Tests.launch | 15 - JSCompressor.psf | 6 - JsCompressor Tests.launch | 15 - JsCompressor.launch | 15 - META-INF/MANIFEST.MF | 12 - README.md | 29 +- build.properties | 6 - .../yui/compressor/JavaScriptCompressor.java | 1337 ----------------- .../yui/compressor/JavaScriptIdentifier.java | 55 - .../yui/compressor/JavaScriptToken.java | 28 - .../yui/compressor/ScriptOrFnScope.java | 161 -- .../rap/clientbuilder/DebugFileWriter.java | 66 - src/org/eclipse/rap/clientbuilder/JSFile.java | 132 -- .../rap/clientbuilder/JavaScriptPrinter.java | 112 -- .../rap/clientbuilder/JsCompressor.java | 131 -- .../rap/clientbuilder/QxCodeCleaner.java | 263 ---- .../rap/clientbuilder/StringReplacer.java | 139 -- .../eclipse/rap/clientbuilder/TokenList.java | 259 ---- .../widgets/displaykit/JsFilesList.java | 36 - .../platform/yui/compressor/ParserTest.java | 60 - .../platform/yui/compressor/TestAdapter.java | 38 - .../yui/compressor/TestErrorReporter.java | 53 - .../rap/clientbuilder/CompressorTest.java | 46 - .../rap/clientbuilder/QxCleanupTest.java | 139 -- .../clientbuilder/StringReplacer_Test.java | 79 - .../eclipse/rap/clientbuilder/TestUtil.java | 71 - .../rap/clientbuilder/TokenList_Test.java | 157 -- 27 files changed, 11 insertions(+), 3449 deletions(-) delete mode 100644 ClientBuilder Tests.launch delete mode 100644 JSCompressor.psf delete mode 100644 JsCompressor Tests.launch delete mode 100644 JsCompressor.launch delete mode 100644 META-INF/MANIFEST.MF delete mode 100644 build.properties delete mode 100644 src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java delete mode 100644 src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java delete mode 100644 src/com/yahoo/platform/yui/compressor/JavaScriptToken.java delete mode 100644 src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java delete mode 100644 src/org/eclipse/rap/clientbuilder/DebugFileWriter.java delete mode 100644 src/org/eclipse/rap/clientbuilder/JSFile.java delete mode 100644 src/org/eclipse/rap/clientbuilder/JavaScriptPrinter.java delete mode 100644 src/org/eclipse/rap/clientbuilder/JsCompressor.java delete mode 100644 src/org/eclipse/rap/clientbuilder/QxCodeCleaner.java delete mode 100644 src/org/eclipse/rap/clientbuilder/StringReplacer.java delete mode 100644 src/org/eclipse/rap/clientbuilder/TokenList.java delete mode 100644 src/org/eclipse/swt/internal/widgets/displaykit/JsFilesList.java delete mode 100644 test/com/yahoo/platform/yui/compressor/ParserTest.java delete mode 100644 test/com/yahoo/platform/yui/compressor/TestAdapter.java delete mode 100644 test/com/yahoo/platform/yui/compressor/TestErrorReporter.java delete mode 100644 test/org/eclipse/rap/clientbuilder/CompressorTest.java delete mode 100644 test/org/eclipse/rap/clientbuilder/QxCleanupTest.java delete mode 100644 test/org/eclipse/rap/clientbuilder/StringReplacer_Test.java delete mode 100644 test/org/eclipse/rap/clientbuilder/TestUtil.java delete mode 100644 test/org/eclipse/rap/clientbuilder/TokenList_Test.java diff --git a/ClientBuilder Tests.launch b/ClientBuilder Tests.launch deleted file mode 100644 index 0b7d9d6..0000000 --- a/ClientBuilder Tests.launch +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/JSCompressor.psf b/JSCompressor.psf deleted file mode 100644 index f2717f3..0000000 --- a/JSCompressor.psf +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/JsCompressor Tests.launch b/JsCompressor Tests.launch deleted file mode 100644 index 954f9eb..0000000 --- a/JsCompressor Tests.launch +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/JsCompressor.launch b/JsCompressor.launch deleted file mode 100644 index a048a99..0000000 --- a/JsCompressor.launch +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF deleted file mode 100644 index 5d6e2ab..0000000 --- a/META-INF/MANIFEST.MF +++ /dev/null @@ -1,12 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Clientbuilder -Bundle-SymbolicName: com.eclipsesource.rap.clientbuilder -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: EclipseSource -Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Require-Bundle: org.mozilla.javascript;bundle-version="1.6.6", - org.eclipse.rap.rwt;bundle-version="1.5.0" -Export-Package: com.yahoo.platform.yui.compressor, - org.eclipse.rap.clientbuilder -Import-Package: junit.framework;version="3.8.2" diff --git a/README.md b/README.md index 3b93611..a8f50dc 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,14 @@ -Client library builder for RWT -============================== - -The JsCompressor is used for creating the client library for RAP [1]. It -reads JavaScript files from the project org.eclipse.rap.rwt, compresses and -concatenates them, and writes the resulting JavaScript file back into the -project as client.js. The list of files to be included is taken from the -class QooxdooResourcesUtil. - -Usage ------ -Place this project into the same workspace as the org.eclipse.rap.rwt -project. Use the included launch configuration JSCompressor.launch to create -a new client.js. This launch configuration calls JsCompressor as a plain -application, passing the root directory of the rwt project as parameter. -Remember to refresh (F5) the rwt project when the compressor is done. - -_Important:_ For RAP 1.4, checkout the 1.4-maintenance branch. +Client library builder for RWT WebClient +======================================== + +The JsCompressor is used for assembling the JavaScript library for the WebClient. +It reads JavaScript files from the project org.eclipse.rap.rwt, compresses and +concatenates them, and writes the resulting JavaScript file back into the project +as client.js. + +As of RAP 2.1, this project has been moved into the [RAP repository](http://git.eclipse.org/c/rap/org.eclipse.rap.git/tree/releng). + +For earlier versions, please check out the releated branch. Requires -------- diff --git a/build.properties b/build.properties deleted file mode 100644 index de218e3..0000000 --- a/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/,\ - test/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - README diff --git a/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java b/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java deleted file mode 100644 index ba4cdb7..0000000 --- a/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java +++ /dev/null @@ -1,1337 +0,0 @@ -/* - * YUI Compressor - * Author: Julien Lecomte - * Copyright (c) 2007, Yahoo! Inc. All rights reserved. - * Code licensed under the BSD License: - * http://developer.yahoo.net/yui/license.txt - */ - -package com.yahoo.platform.yui.compressor; - -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.mozilla.javascript.CompilerEnvirons; -import org.mozilla.javascript.ErrorReporter; -import org.mozilla.javascript.EvaluatorException; -import org.mozilla.javascript.Parser; -import org.mozilla.javascript.ScriptRuntime; -import org.mozilla.javascript.Token; - -@SuppressWarnings( { "unchecked", "rawtypes"} ) -public class JavaScriptCompressor { - - static final ArrayList ones; - static final ArrayList twos; - static final ArrayList threes; - - static final Set builtin = new HashSet(); - static final Map literals = new Hashtable(); - static final Set reserved = new HashSet(); - - static { - - // This list contains all the 3 characters or less built-in global - // symbols available in a browser. Please add to this list if you - // see anything missing. - builtin.add("NaN"); - builtin.add("top"); - - ones = new ArrayList(); - for (char c = 'a'; c <= 'z'; c++) - ones.add(Character.toString(c)); - for (char c = 'A'; c <= 'Z'; c++) - ones.add(Character.toString(c)); - - twos = new ArrayList(); - for (int i = 0; i < ones.size(); i++) { - String one = (String) ones.get(i); - for (char c = 'a'; c <= 'z'; c++) - twos.add(one + Character.toString(c)); - for (char c = 'A'; c <= 'Z'; c++) - twos.add(one + Character.toString(c)); - for (char c = '0'; c <= '9'; c++) - twos.add(one + Character.toString(c)); - } - - // Remove two-letter JavaScript reserved words and built-in globals... - twos.remove("as"); - twos.remove("is"); - twos.remove("do"); - twos.remove("if"); - twos.remove("in"); - twos.removeAll(builtin); - - threes = new ArrayList(); - for (int i = 0; i < twos.size(); i++) { - String two = (String) twos.get(i); - for (char c = 'a'; c <= 'z'; c++) - threes.add(two + Character.toString(c)); - for (char c = 'A'; c <= 'Z'; c++) - threes.add(two + Character.toString(c)); - for (char c = '0'; c <= '9'; c++) - threes.add(two + Character.toString(c)); - } - - // Remove three-letter JavaScript reserved words and built-in globals... - threes.remove("for"); - threes.remove("int"); - threes.remove("new"); - threes.remove("try"); - threes.remove("use"); - threes.remove("var"); - threes.removeAll(builtin); - - // That's up to ((26+26)*(1+(26+26+10)))*(1+(26+26+10))-8 - // (206,380 symbols per scope) - - // The following list comes from org/mozilla/javascript/Decompiler.java... - literals.put(new Integer(Token.GET), "get "); - literals.put(new Integer(Token.SET), "set "); - literals.put(new Integer(Token.TRUE), "true"); - literals.put(new Integer(Token.FALSE), "false"); - literals.put(new Integer(Token.NULL), "null"); - literals.put(new Integer(Token.THIS), "this"); - literals.put(new Integer(Token.FUNCTION), "function"); - literals.put(new Integer(Token.COMMA), ","); - literals.put(new Integer(Token.LC), "{"); - literals.put(new Integer(Token.RC), "}"); - literals.put(new Integer(Token.LP), "("); - literals.put(new Integer(Token.RP), ")"); - literals.put(new Integer(Token.LB), "["); - literals.put(new Integer(Token.RB), "]"); - literals.put(new Integer(Token.DOT), "."); - literals.put(new Integer(Token.NEW), "new "); - literals.put(new Integer(Token.DELPROP), "delete "); - literals.put(new Integer(Token.IF), "if"); - literals.put(new Integer(Token.ELSE), "else"); - literals.put(new Integer(Token.FOR), "for"); - literals.put(new Integer(Token.IN), " in "); - literals.put(new Integer(Token.WITH), "with"); - literals.put(new Integer(Token.WHILE), "while"); - literals.put(new Integer(Token.DO), "do"); - literals.put(new Integer(Token.TRY), "try"); - literals.put(new Integer(Token.CATCH), "catch"); - literals.put(new Integer(Token.FINALLY), "finally"); - literals.put(new Integer(Token.THROW), "throw"); - literals.put(new Integer(Token.SWITCH), "switch"); - literals.put(new Integer(Token.BREAK), "break"); - literals.put(new Integer(Token.CONTINUE), "continue"); - literals.put(new Integer(Token.CASE), "case"); - literals.put(new Integer(Token.DEFAULT), "default"); - literals.put(new Integer(Token.RETURN), "return"); - literals.put(new Integer(Token.VAR), "var "); - literals.put(new Integer(Token.SEMI), ";"); - literals.put(new Integer(Token.ASSIGN), "="); - literals.put(new Integer(Token.ASSIGN_ADD), "+="); - literals.put(new Integer(Token.ASSIGN_SUB), "-="); - literals.put(new Integer(Token.ASSIGN_MUL), "*="); - literals.put(new Integer(Token.ASSIGN_DIV), "/="); - literals.put(new Integer(Token.ASSIGN_MOD), "%="); - literals.put(new Integer(Token.ASSIGN_BITOR), "|="); - literals.put(new Integer(Token.ASSIGN_BITXOR), "^="); - literals.put(new Integer(Token.ASSIGN_BITAND), "&="); - literals.put(new Integer(Token.ASSIGN_LSH), "<<="); - literals.put(new Integer(Token.ASSIGN_RSH), ">>="); - literals.put(new Integer(Token.ASSIGN_URSH), ">>>="); - literals.put(new Integer(Token.HOOK), "?"); - literals.put(new Integer(Token.OBJECTLIT), ":"); - literals.put(new Integer(Token.COLON), ":"); - literals.put(new Integer(Token.OR), "||"); - literals.put(new Integer(Token.AND), "&&"); - literals.put(new Integer(Token.BITOR), "|"); - literals.put(new Integer(Token.BITXOR), "^"); - literals.put(new Integer(Token.BITAND), "&"); - literals.put(new Integer(Token.SHEQ), "==="); - literals.put(new Integer(Token.SHNE), "!=="); - literals.put(new Integer(Token.EQ), "=="); - literals.put(new Integer(Token.NE), "!="); - literals.put(new Integer(Token.LE), "<="); - literals.put(new Integer(Token.LT), "<"); - literals.put(new Integer(Token.GE), ">="); - literals.put(new Integer(Token.GT), ">"); - literals.put(new Integer(Token.INSTANCEOF), " instanceof "); - literals.put(new Integer(Token.LSH), "<<"); - literals.put(new Integer(Token.RSH), ">>"); - literals.put(new Integer(Token.URSH), ">>>"); - literals.put(new Integer(Token.TYPEOF), "typeof"); - literals.put(new Integer(Token.VOID), "void "); - literals.put(new Integer(Token.CONST), "const "); - literals.put(new Integer(Token.NOT), "!"); - literals.put(new Integer(Token.BITNOT), "~"); - literals.put(new Integer(Token.POS), "+"); - literals.put(new Integer(Token.NEG), "-"); - literals.put(new Integer(Token.INC), "++"); - literals.put(new Integer(Token.DEC), "--"); - literals.put(new Integer(Token.ADD), "+"); - literals.put(new Integer(Token.SUB), "-"); - literals.put(new Integer(Token.MUL), "*"); - literals.put(new Integer(Token.DIV), "/"); - literals.put(new Integer(Token.MOD), "%"); - literals.put(new Integer(Token.COLONCOLON), "::"); - literals.put(new Integer(Token.DOTDOT), ".."); - literals.put(new Integer(Token.DOTQUERY), ".("); - literals.put(new Integer(Token.XMLATTR), "@"); - - // See http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Reserved_Words - - // JavaScript 1.5 reserved words - reserved.add("break"); - reserved.add("case"); - reserved.add("catch"); - reserved.add("continue"); - reserved.add("default"); - reserved.add("delete"); - reserved.add("do"); - reserved.add("else"); - reserved.add("finally"); - reserved.add("for"); - reserved.add("function"); - reserved.add("if"); - reserved.add("in"); - reserved.add("instanceof"); - reserved.add("new"); - reserved.add("return"); - reserved.add("switch"); - reserved.add("this"); - reserved.add("throw"); - reserved.add("try"); - reserved.add("typeof"); - reserved.add("var"); - reserved.add("void"); - reserved.add("while"); - reserved.add("with"); - // Words reserved for future use - reserved.add("abstract"); - reserved.add("boolean"); - reserved.add("byte"); - reserved.add("char"); - reserved.add("class"); - reserved.add("const"); - reserved.add("debugger"); - reserved.add("double"); - reserved.add("enum"); - reserved.add("export"); - reserved.add("extends"); - reserved.add("final"); - reserved.add("float"); - reserved.add("goto"); - reserved.add("implements"); - reserved.add("import"); - reserved.add("int"); - reserved.add("interface"); - reserved.add("long"); - reserved.add("native"); - reserved.add("package"); - reserved.add("private"); - reserved.add("protected"); - reserved.add("public"); - reserved.add("short"); - reserved.add("static"); - reserved.add("super"); - reserved.add("synchronized"); - reserved.add("throws"); - reserved.add("transient"); - reserved.add("volatile"); - // These are not reserved, but should be taken into account - // in isValidIdentifier (See jslint source code) - reserved.add("arguments"); - reserved.add("eval"); - reserved.add("true"); - reserved.add("false"); - reserved.add("Infinity"); - reserved.add("NaN"); - reserved.add("null"); - reserved.add("undefined"); - } - - private static int countChar(String haystack, char needle) { - int idx = 0; - int count = 0; - int length = haystack.length(); - while (idx < length) { - char c = haystack.charAt(idx++); - if (c == needle) { - count++; - } - } - return count; - } - - static int printSourceString(String source, int offset, StringBuffer sb) { - int length = source.charAt(offset); - ++offset; - if ((0x8000 & length) != 0) { - length = ((0x7FFF & length) << 16) | source.charAt(offset); - ++offset; - } - if (sb != null) { - String str = source.substring(offset, offset + length); - sb.append(str); - } - return offset + length; - } - - static int printSourceNumber(String source, - int offset, StringBuffer sb) { - double number = 0.0; - char type = source.charAt(offset); - ++offset; - if (type == 'S') { - if (sb != null) { - number = source.charAt(offset); - } - ++offset; - } else if (type == 'J' || type == 'D') { - if (sb != null) { - long lbits; - lbits = (long) source.charAt(offset) << 48; - lbits |= (long) source.charAt(offset + 1) << 32; - lbits |= (long) source.charAt(offset + 2) << 16; - lbits |= (long) source.charAt(offset + 3); - if (type == 'J') { - number = lbits; - } else { - number = Double.longBitsToDouble(lbits); - } - } - offset += 4; - } else { - // Bad source - throw new RuntimeException(); - } - if (sb != null) { - sb.append(ScriptRuntime.numberToString(number, 10)); - } - return offset; - } - - static ArrayList parse(Reader in, ErrorReporter reporter) - throws IOException, EvaluatorException { - - CompilerEnvirons env = new CompilerEnvirons(); - Parser parser = new Parser(env, reporter); - parser.parse(in, null, 1); - String source = parser.getEncodedSource(); - - int offset = 0; - int length = source.length(); - ArrayList tokens = new ArrayList(); - StringBuffer sb = new StringBuffer(); - - while (offset < length) { - int tt = source.charAt(offset++); - switch (tt) { - -// case Token.CONDCOMMENT: -// case Token.KEEPCOMMENT: - case Token.NAME: - case Token.REGEXP: - case Token.STRING: - sb.setLength(0); - offset = printSourceString(source, offset, sb); - tokens.add(new JavaScriptToken(tt, sb.toString())); - break; - - case Token.NUMBER: - sb.setLength(0); - offset = printSourceNumber(source, offset, sb); - tokens.add(new JavaScriptToken(tt, sb.toString())); - break; - - default: - String literal = (String) literals.get(new Integer(tt)); - if (literal != null) { - tokens.add(new JavaScriptToken(tt, literal)); - } - break; - } - } - - return tokens; - } - - private static void processStringLiterals(ArrayList tokens, boolean merge) { - - String tv; - int i, length = tokens.size(); - JavaScriptToken token, prevToken, nextToken; - - if (merge) { - - // Concatenate string literals that are being appended wherever - // it is safe to do so. Note that we take care of the case: - // "a" + "b".toUpperCase() - - for (i = 0; i < length; i++) { - token = (JavaScriptToken) tokens.get(i); - switch (token.getType()) { - - case Token.ADD: - if (i > 0 && i < length) { - prevToken = (JavaScriptToken) tokens.get(i - 1); - nextToken = (JavaScriptToken) tokens.get(i + 1); - if (prevToken.getType() == Token.STRING && nextToken.getType() == Token.STRING && - (i == length - 1 || ((JavaScriptToken) tokens.get(i + 2)).getType() != Token.DOT)) { - tokens.set(i - 1, new JavaScriptToken(Token.STRING, - prevToken.getValue() + nextToken.getValue())); - tokens.remove(i + 1); - tokens.remove(i); - i = i - 1; - length = length - 2; - break; - } - } - } - } - - } - - // Second pass... - - for (i = 0; i < length; i++) { - token = (JavaScriptToken) tokens.get(i); - if (token.getType() == Token.STRING) { - tv = token.getValue(); - - // Finally, add the quoting characters and escape the string. We use - // the quoting character that minimizes the amount of escaping to save - // a few additional bytes. - - char quotechar; - int singleQuoteCount = countChar(tv, '\''); - int doubleQuoteCount = countChar(tv, '"'); - if (doubleQuoteCount <= singleQuoteCount) { - quotechar = '"'; - } else { - quotechar = '\''; - } - - tv = quotechar + escapeString(tv, quotechar) + quotechar; - - // String concatenation transforms the old script scheme: - // '<'+'/script>' - // into the following: - // '' - // which breaks if this code is embedded inside an HTML document. - // Since this is not the right way to do this, let's fix the code by - // transforming all "= 0) { - tv = tv.replaceAll("<\\/script", "<\\\\/script"); - } - - tokens.set(i, new JavaScriptToken(Token.STRING, tv)); - } - } - } - - // Add necessary escaping that was removed in Rhino's tokenizer. - private static String escapeString(String s, char quotechar) { - -// assert quotechar == '"' || quotechar == '\''; - - if (s == null) { - return null; - } - - StringBuffer sb = new StringBuffer(); - for (int i = 0, L = s.length(); i < L; i++) { - int c = s.charAt(i); - if(c == '\n') { - sb.append("\\n"); - } else if(c == '\r') { - sb.append("\\r"); - } else if(c == '\t') { - sb.append("\\t"); - } else if(c == '\\') { - sb.append("\\\\"); - } else { - if (c == quotechar) { - sb.append("\\"); - } - sb.append((char) c); - } - } - - return sb.toString(); - } - - /* - * Simple check to see whether a string is a valid identifier name. - * If a string matches this pattern, it means it IS a valid - * identifier name. If a string doesn't match it, it does not - * necessarily mean it is not a valid identifier name. - */ - private static final Pattern SIMPLE_IDENTIFIER_NAME_PATTERN = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$"); - - private static boolean isValidIdentifier(String s) { - Matcher m = SIMPLE_IDENTIFIER_NAME_PATTERN.matcher(s); - return (m.matches() && !reserved.contains(s)); - } - - /* - * Transforms obj["foo"] into obj.foo whenever possible, saving 3 bytes. - */ - private static void optimizeObjectMemberAccess(ArrayList tokens) { - - String tv; - int i, length; - JavaScriptToken token; - - for (i = 0, length = tokens.size(); i < length; i++) { - - if (((JavaScriptToken) tokens.get(i)).getType() == Token.LB && - i > 0 && i < length - 2 && - ((JavaScriptToken) tokens.get(i - 1)).getType() == Token.NAME && - ((JavaScriptToken) tokens.get(i + 1)).getType() == Token.STRING && - ((JavaScriptToken) tokens.get(i + 2)).getType() == Token.RB) { - token = (JavaScriptToken) tokens.get(i + 1); - tv = token.getValue(); - tv = tv.substring(1, tv.length() - 1); - if (isValidIdentifier(tv)) { - tokens.set(i, new JavaScriptToken(Token.DOT, ".")); - tokens.set(i + 1, new JavaScriptToken(Token.NAME, tv)); - tokens.remove(i + 2); - i = i + 2; - length = length - 1; - } - } - } - } - - /* - * Transforms 'foo': ... into foo: ... whenever possible, saving 2 bytes. - */ - private static void optimizeObjLitMemberDecl(ArrayList tokens) { - - String tv; - int i, length; - JavaScriptToken token; - - for (i = 0, length = tokens.size(); i < length; i++) { - if (((JavaScriptToken) tokens.get(i)).getType() == Token.OBJECTLIT && - i > 0 && ((JavaScriptToken) tokens.get(i - 1)).getType() == Token.STRING) { - token = (JavaScriptToken) tokens.get(i - 1); - tv = token.getValue(); - tv = tv.substring(1, tv.length() - 1); - if (isValidIdentifier(tv)) { - tokens.set(i - 1, new JavaScriptToken(Token.NAME, tv)); - } - } - } - } - - private ErrorReporter logger; - - private boolean munge; - private boolean verbose; - - private static final int BUILDING_SYMBOL_TREE = 1; - private static final int CHECKING_SYMBOL_TREE = 2; - - private int mode; - private int offset; - private int braceNesting; - private ArrayList tokens; - private Stack scopes = new Stack(); - private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null); - private Hashtable indexedScopes = new Hashtable(); - - public JavaScriptCompressor(Reader in, ErrorReporter reporter) - throws IOException, EvaluatorException { - - this.logger = reporter; - this.tokens = parse(in, reporter); - } - - public ArrayList getTokens() { - return this.tokens; - } - - public void compress(Writer out, int linebreak, boolean munge, boolean verbose, - boolean preserveAllSemiColons, boolean disableOptimizations) - throws IOException { - - this.munge = munge; - this.verbose = verbose; - - processStringLiterals(this.tokens, !disableOptimizations); - - if (!disableOptimizations) { - optimizeObjectMemberAccess(this.tokens); - optimizeObjLitMemberDecl(this.tokens); - } - - buildSymbolTree(); - // DO NOT TOUCH this.tokens BETWEEN THESE TWO PHASES (BECAUSE OF this.indexedScopes) - mungeSymboltree(); - StringBuffer sb = printSymbolTree(linebreak, preserveAllSemiColons); - - out.write(sb.toString()); - } - - private ScriptOrFnScope getCurrentScope() { - return (ScriptOrFnScope) scopes.peek(); - } - - private void enterScope(ScriptOrFnScope scope) { - scopes.push(scope); - } - - private void leaveCurrentScope() { - scopes.pop(); - } - - private JavaScriptToken consumeToken() { - return (JavaScriptToken) tokens.get(offset++); - } - - private JavaScriptToken getToken(int delta) { - return (JavaScriptToken) tokens.get(offset + delta); - } - - /* - * Returns the identifier for the specified symbol defined in - * the specified scope or in any scope above it. Returns null - * if this symbol does not have a corresponding identifier. - */ - private JavaScriptIdentifier getIdentifier(String symbol, ScriptOrFnScope scope) { - JavaScriptIdentifier identifier; - while (scope != null) { - identifier = scope.getIdentifier(symbol); - if (identifier != null) { - return identifier; - } - scope = scope.getParentScope(); - } - return null; - } - - /* - * If either 'eval' or 'with' is used in a local scope, we must make - * sure that all containing local scopes don't get munged. Otherwise, - * the obfuscation would potentially introduce bugs. - */ - private void protectScopeFromObfuscation(ScriptOrFnScope scope) { -// assert scope != null; - - if (scope == globalScope) { - // The global scope does not get obfuscated, - // so we don't need to worry about it... - return; - } - - // Find the highest local scope containing the specified scope. - while (scope.getParentScope() != globalScope) { - scope = scope.getParentScope(); - } - -// assert scope.getParentScope() == globalScope; - scope.preventMunging(); - } - - private String getDebugString(int max) { -// assert max > 0; - StringBuffer result = new StringBuffer(); - int start = Math.max(offset - max, 0); - int end = Math.min(offset + max, tokens.size()); - for (int i = start; i < end; i++) { - JavaScriptToken token = (JavaScriptToken) tokens.get(i); - if (i == offset - 1) { - result.append(" ---> "); - } - result.append(token.getValue()); - if (i == offset - 1) { - result.append(" <--- "); - } - } - return result.toString(); - } - - private void warn(String message, boolean showDebugString) { - if (verbose) { - if (showDebugString) { - message = message + "\n" + getDebugString(10); - } - logger.warning(message, null, -1, null, -1); - } - } - - private void parseFunctionDeclaration() { - - String symbol; - JavaScriptToken token; - ScriptOrFnScope currentScope, fnScope; - JavaScriptIdentifier identifier; - - currentScope = getCurrentScope(); - - token = consumeToken(); - if (token.getType() == Token.NAME) { - if (mode == BUILDING_SYMBOL_TREE) { - // Get the name of the function and declare it in the current scope. - symbol = token.getValue(); - if (currentScope.getIdentifier(symbol) != null) { - warn("The function " + symbol + " has already been declared in the same scope...", true); - } - currentScope.declareIdentifier(symbol); - } - token = consumeToken(); - } - -// assert token.getType() == Token.LP; - if (mode == BUILDING_SYMBOL_TREE) { - fnScope = new ScriptOrFnScope(braceNesting, currentScope); - indexedScopes.put(new Integer(offset), fnScope); - } else { - fnScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset)); - } - - // Parse function arguments. - int argpos = 0; - while ((token = consumeToken()).getType() != Token.RP) { -// assert token.getType() == Token.NAME || -// token.getType() == Token.COMMA; - if (token.getType() == Token.NAME && mode == BUILDING_SYMBOL_TREE) { - symbol = token.getValue(); - identifier = fnScope.declareIdentifier(symbol); - if (symbol.equals("$super") && argpos == 0) { - // Exception for Prototype 1.6... - identifier.preventMunging(); - } - argpos++; - } - } - - token = consumeToken(); -// assert token.getType() == Token.LC; - braceNesting++; - - token = getToken(0); - if (token.getType() == Token.STRING && - getToken(1).getType() == Token.SEMI) { - // This is a hint. Hints are empty statements that look like - // "localvar1:nomunge, localvar2:nomunge"; They allow developers - // to prevent specific symbols from getting obfuscated (some heretic - // implementations, such as Prototype 1.6, require specific variable - // names, such as $super for example, in order to work appropriately. - // Note: right now, only "nomunge" is supported in the right hand side - // of a hint. However, in the future, the right hand side may contain - // other values. - consumeToken(); - String hints = token.getValue(); - // Remove the leading and trailing quotes... - hints = hints.substring(1, hints.length() - 1).trim(); - StringTokenizer st1 = new StringTokenizer(hints, ","); - while (st1.hasMoreTokens()) { - String hint = st1.nextToken(); - int idx = hint.indexOf(':'); - if (idx <= 0 || idx >= hint.length() - 1) { - if (mode == BUILDING_SYMBOL_TREE) { - // No need to report the error twice, hence the test... - warn("Invalid hint syntax: " + hint, true); - } - break; - } - String variableName = hint.substring(0, idx).trim(); - String variableType = hint.substring(idx + 1).trim(); - if (mode == BUILDING_SYMBOL_TREE) { - fnScope.addHint(variableName, variableType); - } else if (mode == CHECKING_SYMBOL_TREE) { - identifier = fnScope.getIdentifier(variableName); - if (identifier != null) { - if (variableType.equals("nomunge")) { - identifier.preventMunging(); - } else { - warn("Unsupported hint value: " + hint, true); - } - } else { - warn("Hint refers to an unknown identifier: " + hint, true); - } - } - } - } - - parseScope(fnScope); - } - - private void parseCatch() { - - String symbol; - JavaScriptToken token; - ScriptOrFnScope currentScope; - JavaScriptIdentifier identifier; - - token = getToken(-1); -// assert token.getType() == Token.CATCH; - token = consumeToken(); -// assert token.getType() == Token.LP; - token = consumeToken(); -// assert token.getType() == Token.NAME; - - symbol = token.getValue(); - currentScope = getCurrentScope(); - - if (mode == BUILDING_SYMBOL_TREE) { - // We must declare the exception identifier in the containing function - // scope to avoid errors related to the obfuscation process. No need to - // display a warning if the symbol was already declared here... - currentScope.declareIdentifier(symbol); - } else { - identifier = getIdentifier(symbol, currentScope); - identifier.incrementRefcount(); - } - - token = consumeToken(); -// assert token.getType() == Token.RP; - } - - private void parseExpression() { - - // Parse the expression until we encounter a comma or a semi-colon - // in the same brace nesting, bracket nesting and paren nesting. - // Parse functions if any... - - String symbol; - JavaScriptToken token; - ScriptOrFnScope currentScope; - JavaScriptIdentifier identifier; - - int expressionBraceNesting = braceNesting; - int bracketNesting = 0; - int parensNesting = 0; - - int length = tokens.size(); - - while (offset < length) { - - token = consumeToken(); - currentScope = getCurrentScope(); - - switch (token.getType()) { - - case Token.SEMI: - case Token.COMMA: - if (braceNesting == expressionBraceNesting && - bracketNesting == 0 && - parensNesting == 0) { - return; - } - break; - - case Token.FUNCTION: - parseFunctionDeclaration(); - break; - - case Token.LC: - braceNesting++; - break; - - case Token.RC: - braceNesting--; -// assert braceNesting >= expressionBraceNesting; - break; - - case Token.LB: - bracketNesting++; - break; - - case Token.RB: - bracketNesting--; - break; - - case Token.LP: - parensNesting++; - break; - - case Token.RP: - parensNesting--; - break; - -// case Token.CONDCOMMENT: -// if (mode == BUILDING_SYMBOL_TREE) { -// protectScopeFromObfuscation(currentScope); -// warn("Using JScript conditional comments is not recommended." + (munge ? " Moreover, using JScript conditional comments reduces the level of compression!" : ""), true); -// } -// break; - - case Token.NAME: - symbol = token.getValue(); - - if (mode == BUILDING_SYMBOL_TREE) { - - if (symbol.equals("eval")) { - - protectScopeFromObfuscation(currentScope); - warn("Using 'eval' is not recommended." + (munge ? " Moreover, using 'eval' reduces the level of compression!" : ""), true); - - } - - } else if (mode == CHECKING_SYMBOL_TREE) { - - if ((offset < 2 || - (getToken(-2).getType() != Token.DOT && - getToken(-2).getType() != Token.GET && - getToken(-2).getType() != Token.SET)) && - getToken(0).getType() != Token.OBJECTLIT) { - - identifier = getIdentifier(symbol, currentScope); - - if (identifier == null) { - - if (symbol.length() <= 3 && !builtin.contains(symbol)) { - // Here, we found an undeclared and un-namespaced symbol that is - // 3 characters or less in length. Declare it in the global scope. - // We don't need to declare longer symbols since they won't cause - // any conflict with other munged symbols. - globalScope.declareIdentifier(symbol); - warn("Found an undeclared symbol: " + symbol, true); - } - - } else { - - identifier.incrementRefcount(); - } - } - } - break; - } - } - } - - private void parseScope(ScriptOrFnScope scope) { - - String symbol; - JavaScriptToken token; - JavaScriptIdentifier identifier; - - int length = tokens.size(); - - enterScope(scope); - - while (offset < length) { - - token = consumeToken(); - - switch (token.getType()) { - - case Token.VAR: - - if (mode == BUILDING_SYMBOL_TREE && scope.incrementVarCount() > 1) { - warn("Try to use a single 'var' statement per scope.", true); - } - - /* FALLSTHROUGH */ - - case Token.CONST: - - // The var keyword is followed by at least one symbol name. - // If several symbols follow, they are comma separated. - for (; ;) { - token = consumeToken(); - -// assert token.getType() == Token.NAME; - - if (mode == BUILDING_SYMBOL_TREE) { - symbol = token.getValue(); - if (scope.getIdentifier(symbol) == null) { - scope.declareIdentifier(symbol); - } else { - warn("The variable " + symbol + " has already been declared in the same scope...", true); - } - } - - token = getToken(0); - -// assert token.getType() == Token.SEMI || -// token.getType() == Token.ASSIGN || -// token.getType() == Token.COMMA || -// token.getType() == Token.IN; - - if (token.getType() == Token.IN) { - break; - } else { - parseExpression(); - token = getToken(-1); - if (token.getType() == Token.SEMI) { - break; - } - } - } - break; - - case Token.FUNCTION: - parseFunctionDeclaration(); - break; - - case Token.LC: - braceNesting++; - break; - - case Token.RC: - braceNesting--; -// assert braceNesting >= scope.getBraceNesting(); - if (braceNesting == scope.getBraceNesting()) { - leaveCurrentScope(); - return; - } - break; - - case Token.WITH: - if (mode == BUILDING_SYMBOL_TREE) { - // Inside a 'with' block, it is impossible to figure out - // statically whether a symbol is a local variable or an - // object member. As a consequence, the only thing we can - // do is turn the obfuscation off for the highest scope - // containing the 'with' block. - protectScopeFromObfuscation(scope); - warn("Using 'with' is not recommended." + (munge ? " Moreover, using 'with' reduces the level of compression!" : ""), true); - } - break; - - case Token.CATCH: - parseCatch(); - break; - -// case Token.CONDCOMMENT: -// if (mode == BUILDING_SYMBOL_TREE) { -// protectScopeFromObfuscation(scope); -// warn("Using JScript conditional comments is not recommended." + (munge ? " Moreover, using JScript conditional comments reduces the level of compression." : ""), true); -// } -// break; - - case Token.NAME: - symbol = token.getValue(); - - if (mode == BUILDING_SYMBOL_TREE) { - - if (symbol.equals("eval")) { - - protectScopeFromObfuscation(scope); - warn("Using 'eval' is not recommended." + (munge ? " Moreover, using 'eval' reduces the level of compression!" : ""), true); - - } - - } else if (mode == CHECKING_SYMBOL_TREE) { - - if ((offset < 2 || getToken(-2).getType() != Token.DOT) && - getToken(0).getType() != Token.OBJECTLIT) { - - identifier = getIdentifier(symbol, scope); - - if (identifier == null) { - - if (symbol.length() <= 3 && !builtin.contains(symbol)) { - // Here, we found an undeclared and un-namespaced symbol that is - // 3 characters or less in length. Declare it in the global scope. - // We don't need to declare longer symbols since they won't cause - // any conflict with other munged symbols. - globalScope.declareIdentifier(symbol); - warn("Found an undeclared symbol: " + symbol, true); - } - - } else { - - identifier.incrementRefcount(); - } - } - } - break; - } - } - } - - private void buildSymbolTree() { - offset = 0; - braceNesting = 0; - scopes.clear(); - indexedScopes.clear(); - indexedScopes.put(new Integer(0), globalScope); - mode = BUILDING_SYMBOL_TREE; - parseScope(globalScope); - } - - private void mungeSymboltree() { - - if (!munge) { - return; - } - - // One problem with obfuscation resides in the use of undeclared - // and un-namespaced global symbols that are 3 characters or less - // in length. Here is an example: - // - // var declaredGlobalVar; - // - // function declaredGlobalFn() { - // var localvar; - // localvar = abc; // abc is an undeclared global symbol - // } - // - // In the example above, there is a slim chance that localvar may be - // munged to 'abc', conflicting with the undeclared global symbol - // abc, creating a potential bug. The following code detects such - // global symbols. This must be done AFTER the entire file has been - // parsed, and BEFORE munging the symbol tree. Note that declaring - // extra symbols in the global scope won't hurt. - // - // Note: Since we go through all the tokens to do this, we also use - // the opportunity to count how many times each identifier is used. - - offset = 0; - braceNesting = 0; - scopes.clear(); - mode = CHECKING_SYMBOL_TREE; - parseScope(globalScope); - globalScope.munge(); - } - - private StringBuffer printSymbolTree(int linebreakpos, boolean preserveAllSemiColons) - throws IOException { - - offset = 0; - braceNesting = 0; - scopes.clear(); - - String symbol; - JavaScriptToken token; - ScriptOrFnScope currentScope; - JavaScriptIdentifier identifier; - - int length = tokens.size(); - StringBuffer result = new StringBuffer(); - - int linestartpos = 0; - - enterScope(globalScope); - - while (offset < length) { - - token = consumeToken(); - symbol = token.getValue(); - currentScope = getCurrentScope(); - - switch (token.getType()) { - - case Token.NAME: - - if (offset >= 2 && getToken(-2).getType() == Token.DOT || - getToken(0).getType() == Token.OBJECTLIT) { - - result.append(symbol); - - } else { - - identifier = getIdentifier(symbol, currentScope); - if (identifier != null) { - if (identifier.getMungedValue() != null) { - result.append(identifier.getMungedValue()); - } else { - result.append(symbol); - } - if (currentScope != globalScope && identifier.getRefcount() == 0) { - warn("The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more compact way.", true); - } - } else { - result.append(symbol); - } - } - break; - - case Token.REGEXP: - case Token.NUMBER: - case Token.STRING: - result.append(symbol); - break; - - case Token.ADD: - case Token.SUB: - result.append((String) literals.get(new Integer(token.getType()))); - if (offset < length) { - token = getToken(0); - if (token.getType() == Token.INC || - token.getType() == Token.DEC || - token.getType() == Token.ADD || - token.getType() == Token.DEC) { - // Handle the case x +/- ++/-- y - // We must keep a white space here. Otherwise, x +++ y would be - // interpreted as x ++ + y by the compiler, which is a bug (due - // to the implicit assignment being done on the wrong variable) - result.append(' '); - } else if (token.getType() == Token.POS && getToken(-1).getType() == Token.ADD || - token.getType() == Token.NEG && getToken(-1).getType() == Token.SUB) { - // Handle the case x + + y and x - - y - result.append(' '); - } - } - break; - - case Token.FUNCTION: - result.append("function"); - token = consumeToken(); - if (token.getType() == Token.NAME) { - result.append(' '); - symbol = token.getValue(); - identifier = getIdentifier(symbol, currentScope); -// assert identifier != null; - if (identifier.getMungedValue() != null) { - result.append(identifier.getMungedValue()); - } else { - result.append(symbol); - } - if (currentScope != globalScope && identifier.getRefcount() == 0) { - warn("The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more compact way.", true); - } - token = consumeToken(); - } -// assert token.getType() == Token.LP; - result.append('('); - currentScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset)); - enterScope(currentScope); - while ((token = consumeToken()).getType() != Token.RP) { -// assert token.getType() == Token.NAME || token.getType() == Token.COMMA; - if (token.getType() == Token.NAME) { - symbol = token.getValue(); - identifier = getIdentifier(symbol, currentScope); -// assert identifier != null; - if (identifier.getMungedValue() != null) { - result.append(identifier.getMungedValue()); - } else { - result.append(symbol); - } - } else if (token.getType() == Token.COMMA) { - result.append(','); - } - } - result.append(')'); - token = consumeToken(); -// assert token.getType() == Token.LC; - result.append('{'); - braceNesting++; - token = getToken(0); - if (token.getType() == Token.STRING && - getToken(1).getType() == Token.SEMI) { - // This is a hint. Skip it! - consumeToken(); - consumeToken(); - } - break; - - case Token.RETURN: - case Token.TYPEOF: - result.append(literals.get(new Integer(token.getType()))); - // No space needed after 'return' and 'typeof' when followed - // by '(', '[', '{', a string or a regexp. - if (offset < length) { - token = getToken(0); - if (token.getType() != Token.LP && - token.getType() != Token.LB && - token.getType() != Token.LC && - token.getType() != Token.STRING && - token.getType() != Token.REGEXP && - token.getType() != Token.SEMI) { - result.append(' '); - } - } - break; - - case Token.CASE: - case Token.THROW: - result.append(literals.get(new Integer(token.getType()))); - // White-space needed after 'case' and 'throw' when not followed by a string. - if (offset < length && getToken(0).getType() != Token.STRING) { - result.append(' '); - } - break; - - case Token.BREAK: - case Token.CONTINUE: - result.append(literals.get(new Integer(token.getType()))); - if (offset < length && getToken(0).getType() != Token.SEMI) { - // If 'break' or 'continue' is not followed by a semi-colon, it must - // be followed by a label, hence the need for a white space. - result.append(' '); - } - break; - - case Token.LC: - result.append('{'); - braceNesting++; - break; - - case Token.RC: - result.append('}'); - braceNesting--; -// assert braceNesting >= currentScope.getBraceNesting(); - if (braceNesting == currentScope.getBraceNesting()) { - leaveCurrentScope(); - } - break; - - case Token.SEMI: - // No need to output a semi-colon if the next character is a right-curly... - if (preserveAllSemiColons || offset < length && getToken(0).getType() != Token.RC) { - result.append(';'); - } - - if (linebreakpos >= 0 && result.length() - linestartpos > linebreakpos) { - // Some source control tools don't like it when files containing lines longer - // than, say 8000 characters, are checked in. The linebreak option is used in - // that case to split long lines after a specific column. - result.append('\n'); - linestartpos = result.length(); - } - break; - -// case Token.CONDCOMMENT: -// case Token.KEEPCOMMENT: -// if (result.length() > 0 && result.charAt(result.length() - 1) != '\n') { -// result.append("\n"); -// } -// result.append("/*"); -// result.append(symbol); -// result.append("*/\n"); -// break; - - default: - String literal = (String) literals.get(new Integer(token.getType())); - if (literal != null) { - result.append(literal); - } else { - warn("This symbol cannot be printed: " + symbol, true); - } - break; - } - } - - // Append a semi-colon at the end, even if unnecessary semi-colons are - // supposed to be removed. This is especially useful when concatenating - // several minified files (the absence of an ending semi-colon at the - // end of one file may very likely cause a syntax error) - if (!preserveAllSemiColons && - result.length() > 0 -// && -// getToken(-1).getType() != Token.CONDCOMMENT && -// getToken(-1).getType() != Token.KEEPCOMMENT - ) { - if (result.charAt(result.length() - 1) == '\n') { - result.setCharAt(result.length() - 1, ';'); - } else { - result.append(';'); - } - } - - return result; - } -} diff --git a/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java b/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java deleted file mode 100644 index 127fe23..0000000 --- a/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * YUI Compressor - * Author: Julien Lecomte - * Copyright (c) 2007, Yahoo! Inc. All rights reserved. - * Code licensed under the BSD License: - * http://developer.yahoo.net/yui/license.txt - */ - -package com.yahoo.platform.yui.compressor; - -import org.mozilla.javascript.Token; - -/** - * JavaScriptIdentifier represents a variable/function identifier. - */ -class JavaScriptIdentifier extends JavaScriptToken { - - private int refcount = 0; - private String mungedValue; - private ScriptOrFnScope declaredScope; - private boolean markedForMunging = true; - - JavaScriptIdentifier(String value, ScriptOrFnScope declaredScope) { - super(Token.NAME, value); - this.declaredScope = declaredScope; - } - - ScriptOrFnScope getDeclaredScope() { - return declaredScope; - } - - void setMungedValue(String value) { - mungedValue = value; - } - - String getMungedValue() { - return mungedValue; - } - - void preventMunging() { - markedForMunging = false; - } - - boolean isMarkedForMunging() { - return markedForMunging; - } - - void incrementRefcount() { - refcount++; - } - - int getRefcount() { - return refcount; - } -} diff --git a/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java b/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java deleted file mode 100644 index 4579f9b..0000000 --- a/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * YUI Compressor - * Author: Julien Lecomte - * Copyright (c) 2007, Yahoo! Inc. All rights reserved. - * Code licensed under the BSD License: - * http://developer.yahoo.net/yui/license.txt - */ - -package com.yahoo.platform.yui.compressor; - -public class JavaScriptToken { - - private int type; - private String value; - - public JavaScriptToken(int type, String value) { - this.type = type; - this.value = value; - } - - public int getType() { - return type; - } - - public String getValue() { - return value; - } -} diff --git a/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java b/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java deleted file mode 100644 index 408ca6a..0000000 --- a/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * YUI Compressor - * Author: Julien Lecomte - * Copyright (c) 2007, Yahoo! Inc. All rights reserved. - * Code licensed under the BSD License: - * http://developer.yahoo.net/yui/license.txt - */ - -package com.yahoo.platform.yui.compressor; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Hashtable; - -@SuppressWarnings( { "unchecked", "rawtypes"} ) -class ScriptOrFnScope { - - private int braceNesting; - private ScriptOrFnScope parentScope; - private ArrayList subScopes; - private Hashtable identifiers = new Hashtable(); - private Hashtable hints = new Hashtable(); - private boolean markedForMunging = true; - private int varcount = 0; - - ScriptOrFnScope(int braceNesting, ScriptOrFnScope parentScope) { - this.braceNesting = braceNesting; - this.parentScope = parentScope; - this.subScopes = new ArrayList(); - if (parentScope != null) { - parentScope.subScopes.add(this); - } - } - - int getBraceNesting() { - return braceNesting; - } - - ScriptOrFnScope getParentScope() { - return parentScope; - } - - JavaScriptIdentifier declareIdentifier(String symbol) { - JavaScriptIdentifier identifier = (JavaScriptIdentifier) identifiers.get(symbol); - if (identifier == null) { - identifier = new JavaScriptIdentifier(symbol, this); - identifiers.put(symbol, identifier); - } - return identifier; - } - - JavaScriptIdentifier getIdentifier(String symbol) { - return (JavaScriptIdentifier) identifiers.get(symbol); - } - - void addHint(String variableName, String variableType) { - hints.put(variableName, variableType); - } - - void preventMunging() { - if (parentScope != null) { - // The symbols in the global scope don't get munged, - // but the sub-scopes it contains do get munged. - markedForMunging = false; - } - } - - private ArrayList getUsedSymbols() { - ArrayList result = new ArrayList(); - Enumeration elements = identifiers.elements(); - while (elements.hasMoreElements()) { - JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement(); - String mungedValue = identifier.getMungedValue(); - if (mungedValue == null) { - mungedValue = identifier.getValue(); - } - result.add(mungedValue); - } - return result; - } - - private ArrayList getAllUsedSymbols() { - ArrayList result = new ArrayList(); - ScriptOrFnScope scope = this; - while (scope != null) { - result.addAll(scope.getUsedSymbols()); - scope = scope.parentScope; - } - return result; - } - - int incrementVarCount() { - varcount++; - return varcount; - } - - void munge() { - - if (!markedForMunging) { - // Stop right here if this scope was flagged as unsafe for munging. - return; - } - - int pickFromSet = 1; - - // Do not munge symbols in the global scope! - if (parentScope != null) { - - ArrayList freeSymbols = new ArrayList(); - - freeSymbols.addAll(JavaScriptCompressor.ones); - freeSymbols.removeAll(getAllUsedSymbols()); - if (freeSymbols.size() == 0) { - pickFromSet = 2; - freeSymbols.addAll(JavaScriptCompressor.twos); - freeSymbols.removeAll(getAllUsedSymbols()); - } - if (freeSymbols.size() == 0) { - pickFromSet = 3; - freeSymbols.addAll(JavaScriptCompressor.threes); - freeSymbols.removeAll(getAllUsedSymbols()); - } - if (freeSymbols.size() == 0) { - throw new IllegalStateException("The YUI Compressor ran out of symbols. Aborting..."); - } - - Enumeration elements = identifiers.elements(); - while (elements.hasMoreElements()) { - if (freeSymbols.size() == 0) { - pickFromSet++; - if (pickFromSet == 2) { - freeSymbols.addAll(JavaScriptCompressor.twos); - } else if (pickFromSet == 3) { - freeSymbols.addAll(JavaScriptCompressor.threes); - } else { - throw new IllegalStateException("The YUI Compressor ran out of symbols. Aborting..."); - } - // It is essential to remove the symbols already used in - // the containing scopes, or some of the variables declared - // in the containing scopes will be redeclared, which can - // lead to errors. - freeSymbols.removeAll(getAllUsedSymbols()); - } - - String mungedValue; - JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement(); - if (identifier.isMarkedForMunging()) { - mungedValue = (String) freeSymbols.remove(0); - } else { - mungedValue = identifier.getValue(); - } - identifier.setMungedValue(mungedValue); - } - } - - for (int i = 0; i < subScopes.size(); i++) { - ScriptOrFnScope scope = (ScriptOrFnScope) subScopes.get(i); - scope.munge(); - } - } -} diff --git a/src/org/eclipse/rap/clientbuilder/DebugFileWriter.java b/src/org/eclipse/rap/clientbuilder/DebugFileWriter.java deleted file mode 100644 index e896ded..0000000 --- a/src/org/eclipse/rap/clientbuilder/DebugFileWriter.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -final class DebugFileWriter { - - private final File directoryForDebugFiles; - - public DebugFileWriter( File parentDirectory ) { - this.directoryForDebugFiles = parentDirectory; - } - - public void beforeCleanup( TokenList tokens, String fileName ) { - if( directoryForDebugFiles != null ) { - String code = getCodeForDebugFile( tokens ); - createDebugFile( "orig", fileName, code ); - } - } - - public void afterCleanup( TokenList tokens, String fileName ) { - if( directoryForDebugFiles != null ) { - String code = getCodeForDebugFile( tokens ); - createDebugFile( "clean", fileName, code ); - } - } - - private void createDebugFile( String dirName, String fileName, String code ) { - File subDir = new File( directoryForDebugFiles, dirName ); - subDir.mkdirs(); - File file = new File( subDir, fileName ); - try { - writeToFile( code, file ); - } catch( IOException e ) { - System.err.println( "Failed to write to file " + file.getAbsolutePath() ); - e.printStackTrace(); - } - } - - private String getCodeForDebugFile( TokenList tokens ) { - String code = null; - if( directoryForDebugFiles != null ) { - code = JavaScriptPrinter.printTokens( tokens ); - } - return code; - } - - private static void writeToFile( String Code, File file ) throws IOException { - FileWriter fileWriter = new FileWriter( file ); - try { - fileWriter.write( Code ); - } finally { - fileWriter.close(); - } - } -} diff --git a/src/org/eclipse/rap/clientbuilder/JSFile.java b/src/org/eclipse/rap/clientbuilder/JSFile.java deleted file mode 100644 index 059268e..0000000 --- a/src/org/eclipse/rap/clientbuilder/JSFile.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; - -import org.mozilla.javascript.ErrorReporter; -import org.mozilla.javascript.EvaluatorException; - -import com.yahoo.platform.yui.compressor.JavaScriptCompressor; - -public class JSFile { - - private static final String CHARSET = "UTF-8"; - private static final boolean PRESERVE_ALL_SEMICOLONS = false; - private static final boolean DISABLE_OPTIMIZATIONS = false; - private static final boolean VERBOSE = false; - private static final ErrorReporter REPORTER = new SystemErrorReporter(); - - private final File file; - private final JavaScriptCompressor compressor; - private final TokenList tokens; - - @SuppressWarnings( "unchecked" ) - public JSFile( File file ) throws IOException { - this.file = file; - InputStream inputStream = new FileInputStream( file ); - Reader inputReader = new InputStreamReader( inputStream, CHARSET ); - try { - compressor = new JavaScriptCompressor( inputReader, REPORTER ); - } finally { - inputReader.close(); - } - tokens = new TokenList( compressor.getTokens() ); - } - - public File getFile() { - return file; - } - - public TokenList getTokens() { - return tokens; - } - - public String compress( DebugFileWriter debugFileWriter ) throws IOException { - String result; - StringWriter stringWriter = new StringWriter(); - String fileName = file.getName(); - debugFileWriter.beforeCleanup( tokens, fileName ); - QxCodeCleaner codeCleaner = new QxCodeCleaner( tokens ); - codeCleaner.cleanupQxCode(); - debugFileWriter.afterCleanup( tokens, fileName ); - compressor.compress( stringWriter, - -1, - true, - VERBOSE, - PRESERVE_ALL_SEMICOLONS, - DISABLE_OPTIMIZATIONS ); - stringWriter.flush(); - result = stringWriter.getBuffer().toString(); - stringWriter.close(); - return result; - } - - public static void writeToFile( File outputFile, String compressed ) - throws IOException - { - FileOutputStream outputStream = new FileOutputStream( outputFile ); - Writer outputWriter = new OutputStreamWriter( outputStream, CHARSET ); - try { - outputWriter.write( compressed ); - } finally { - outputWriter.close(); - } - } - - private static final class SystemErrorReporter implements ErrorReporter { - - public void warning( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - System.out.println( getMessage( "WARNING", message ) ); - } - - public void error( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - System.out.println( getMessage( "ERROR", message ) ); - } - - public EvaluatorException runtimeError( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - error( message, sourceName, line, lineSource, lineOffset ); - return new EvaluatorException( message ); - } - - private String getMessage( String severity, String message ) { - StringBuffer result = new StringBuffer(); - result.append( "\n[" ); - result.append( severity ); - result.append( "] " ); - result.append( message ); - return result.toString(); - } - } -} diff --git a/src/org/eclipse/rap/clientbuilder/JavaScriptPrinter.java b/src/org/eclipse/rap/clientbuilder/JavaScriptPrinter.java deleted file mode 100644 index 0c1ff01..0000000 --- a/src/org/eclipse/rap/clientbuilder/JavaScriptPrinter.java +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptToken; - -/** - * Can be used to turn a list of JavaScriptTokens into formatted JavaScript - * code. The generated code might not be perfect, it is used mostly for - * debugging. - */ -public class JavaScriptPrinter { - - private static final String INDENT = " "; - private static final String NEWLINE = "\n"; - - private final StringBuffer code; - - private String indent; - private String nextPrefix; - - public JavaScriptPrinter() { - code = new StringBuffer(); - indent = ""; - nextPrefix = ""; - } - - public void appendToken( JavaScriptToken token ) { - int type = token.getType(); - if( type == Token.RC ) { - code.append( NEWLINE ); - if( indent.length() >= INDENT.length() ) { - indent = indent.substring( INDENT.length() ); - code.append( indent ); - } - code.append( token.getValue() ); - nextPrefix = NEWLINE + indent; - } else if( type == Token.LC ) { - code.append( nextPrefix ); - code.append( token.getValue() ); - indent += INDENT; - nextPrefix = NEWLINE + indent; - } else if( type == Token.COMMA ) { - code.append( token.getValue() ); - } else if( type == Token.SEMI ) { - code.append( token.getValue() ); - nextPrefix = NEWLINE + indent; - } else if( type == Token.DOT ) { - code.append( token.getValue() ); - nextPrefix = ""; - } else if( type == Token.STRING ) { - code.append( nextPrefix + "\"" + escapeString( token.getValue() ) + "\"" ); - nextPrefix = " "; - } else { - code.append( nextPrefix + token.getValue() ); - nextPrefix = " "; - } - } - - public String toString() { - return code.toString(); - } - - /** - * Turns a list of JavaScriptTokens into JavaScript code. - */ - public static String printTokens( TokenList tokens ) { - return printTokens( tokens, 0, tokens.size() - 1 ); - } - - /** - * Turns a range of a list of JavaScriptTokens into JavaScript code. - */ - public static String printTokens( TokenList tokens, int first, int last ) { - JavaScriptPrinter printer = new JavaScriptPrinter(); - for( int i = first; i <= last; i++ ) { - printer.appendToken( tokens.getToken( i ) ); - } - return printer.toString(); - } - - public static String escapeString( String value ) { - StringBuffer result = new StringBuffer(); - int length = value.length(); - for( int i = 0; i < length; i++ ) { - char ch = value.charAt( i ); - if( ch == '"' ) { - result.append( "\\\"" ); - } else if( ch == '\n' ) { - result.append( "\\n" ); - } else if( ch == '\r' ) { - result.append( "\\r" ); - } else if( ch == '\t' ) { - result.append( "\\t" ); - } else if( ch == '\\' ) { - result.append( "\\\\" ); - } else { - result.append( ch ); - } - } - return result.toString(); - } -} diff --git a/src/org/eclipse/rap/clientbuilder/JsCompressor.java b/src/org/eclipse/rap/clientbuilder/JsCompressor.java deleted file mode 100644 index 8bf680a..0000000 --- a/src/org/eclipse/rap/clientbuilder/JsCompressor.java +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.File; -import java.io.IOException; - -import org.eclipse.swt.internal.widgets.displaykit.JsFilesList; - - -public class JsCompressor { - private static final String JS_SOURCE_DIR = "js"; - private static final String TARGET_JS_FILE = "resources/client.js"; - private static final boolean CREATE_DEBUG_FILES - = "true".equals( System.getProperty( "jscompressor.debug" ) ); - private final DebugFileWriter debugFileWriter; - - public static void main( String[] args ) { - if( args.length < 1 ) { - String message = "Parameter missing (rwt project directory)"; - throw new IllegalArgumentException( message ); - } - File projectDir = new File( args[ 0 ] ); - if( !projectDir.exists() ) { - String message = "Project directory not found: " + projectDir; - throw new IllegalArgumentException( message ); - } - File inputDir = new File( projectDir, JS_SOURCE_DIR ); - if( !inputDir.exists() ) { - String message = "Javascript source directory not found: " + inputDir; - throw new IllegalArgumentException( message ); - } - JSFile[] inputFiles = JsCompressor.getJsFilesList( inputDir ); - File outputFile = new File( projectDir, JsCompressor.TARGET_JS_FILE ); - JsCompressor compressor = new JsCompressor( projectDir ); - compressor.compressFiles( inputFiles, outputFile ); - } - - public JsCompressor( File projectDir ) { - debugFileWriter = createDebugFileWriter( projectDir ); - } - - private void compressFiles( JSFile[] inputFiles, File outputFile ) { - try { - long start = System.currentTimeMillis(); - String compressed = compressFiles( inputFiles ); - long time = System.currentTimeMillis() - start; - JSFile.writeToFile( outputFile, compressed ); - int count = inputFiles.length; - System.out.println( "Compressed " + count + " files in " + time + " ms" ); - System.out.println( "Result size: " + compressed.length() + " bytes" ); - } catch( IOException e ) { - throw new RuntimeException( "Failed to compress Javascript files", e ); - } - } - - private String compressFiles( JSFile[] inputFiles ) throws IOException { - StringReplacer stringReplacer = new StringReplacer(); - for( int i = 0; i < inputFiles.length; i++ ) { - JSFile inputFile = inputFiles[ i ]; - stringReplacer.discoverStrings( inputFile.getTokens() ); - } - stringReplacer.optimize(); - StringBuffer buffer = new StringBuffer(); - buffer.append( "(function($){" ); - for( int i = 0; i < inputFiles.length; i++ ) { - JSFile inputFile = inputFiles[ i ]; - stringReplacer.replaceStrings( inputFile.getTokens() ); - String result = inputFile.compress( debugFileWriter ); - buffer.append( result ); - buffer.append( "\n" ); - System.out.println( inputFile.getFile().getAbsolutePath() - + "\t" - + result.length() ); - } - buffer.append( "})("); - String[] strings = stringReplacer.getStrings(); - String stringArrayCode = createStringArray( strings ); - System.out.println( "Replaced " + strings.length + " strings" ); - buffer.append( stringArrayCode ); - buffer.append( ");" ); - return buffer.toString(); - } - - private static DebugFileWriter createDebugFileWriter( File projectDir ) { - File debugDir = null; - if( CREATE_DEBUG_FILES ) { - debugDir = new File( projectDir, "tmp" ); - debugDir.mkdir(); - System.out.println( "Creating debug files in " + debugDir ); - } - return new DebugFileWriter( debugDir ); - } - - private static JSFile[] getJsFilesList( File inputDir ) { - JSFile[] inputFiles; - try { - String[] fileNames = JsFilesList.getFiles(); - inputFiles = new JSFile[ fileNames.length ]; - for( int i = 0; i < inputFiles.length; i++ ) { - File file = new File( inputDir, fileNames[ i ] ); - inputFiles[ i ] = new JSFile( file ); - } - } catch( Exception e ) { - String message = "Failed to get JS files list from rwt project"; - throw new RuntimeException( message, e ); - } - return inputFiles; - } - - private static String createStringArray( String[] strings ) { - StringBuffer buffer = new StringBuffer(); - buffer.append( "[" ); - for( int i = 0; i < strings.length; i++ ) { - String string = strings[ i ]; - buffer.append( "\"" + JavaScriptPrinter.escapeString( string ) + "\"," ); - } - if( buffer.charAt( buffer.length() - 1 ) == ',' ) { - buffer.setLength( buffer.length() - 1 ); - } - buffer.append( "]" ); - return buffer.toString(); - } -} diff --git a/src/org/eclipse/rap/clientbuilder/QxCodeCleaner.java b/src/org/eclipse/rap/clientbuilder/QxCodeCleaner.java deleted file mode 100644 index e3cc049..0000000 --- a/src/org/eclipse/rap/clientbuilder/QxCodeCleaner.java +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2012 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.rap.clientbuilder.TokenList.TokenMatcher; -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptToken; - - -public class QxCodeCleaner { - - private final TokenList tokens; - - private final List replacements; - - public QxCodeCleaner( TokenList tokens ) { - this.tokens = tokens; - replacements = new ArrayList(); - } - - public void cleanupQxCode() { - int pos = 0; - while( pos < tokens.size() ) { - int nextPos = removeVariantConditional( pos ); - if( nextPos == pos ) { - nextPos = replaceVariantSelection( pos ); - } - if( nextPos == pos ) { - nextPos = replaceBaseCall( pos ); - } - if( nextPos == pos ) { - nextPos++; - } - pos = nextPos; - } - doReplacements(); - } - - private int removeVariantConditional( int offset ) { - int nextPos = offset; - VariantConditional conditional = readVariantConditional( offset ); - if( conditional != null ) { - if( canRemoveVariant( conditional.variant ) ) { - int endExpr = tokens.readExpression( conditional.end + 1 ); - if( endExpr != -1 ) { - markTokensForRemoval( conditional.begin, endExpr ); - nextPos = endExpr + 1; - if( TokenMatcher.ELSE.matches( tokens.getToken( nextPos ) ) ) { - markTokensForRemoval( nextPos, nextPos ); - nextPos++; - if( TokenMatcher.LEFT_BRACE.matches( tokens.getToken( nextPos ) ) ) { - int closingBrace = tokens.findClosing( nextPos ); - if( closingBrace != -1 ) { - markTokensForRemoval( nextPos, nextPos ); - markTokensForRemoval( closingBrace, closingBrace ); - nextPos++; - } - } - } - } - } - } - return nextPos; - } - - private int replaceVariantSelection( int offset ) { - int nextPos = offset; - VariantSelection selection = readVariantSelection( offset ); - if( selection != null ) { - int closingBrace = tokens.findClosing( selection.end ); - if( closingBrace != -1 ) { - if( TokenMatcher.RIGHT_PAREN.matches( tokens.getToken( closingBrace + 1 ) ) ) { - int closingParen = closingBrace + 1; - nextPos = selection.end + 1; - if( canRemoveVariant( selection.variant ) ) { - int selectedExpression - = tokens.findInObjectLiteral( "off", selection.end ); - if( selectedExpression != -1 ) { - int endExpression = tokens.readExpression( selectedExpression ); - if( endExpression != -1 ) { - markTokensForRemoval( offset, selectedExpression - 1 ); - markTokensForRemoval( endExpression + 1, closingParen ); - nextPos = closingParen + 1; - } - } - } - } - } - } - return nextPos; - } - - private int replaceBaseCall( int offset ) { - int nextPos = offset; - Range baseCall = readBaseCall( offset ); - if( baseCall != null ) { - JavaScriptToken[] replacement = new JavaScriptToken[] { - new JavaScriptToken( Token.NAME, "arguments" ), - new JavaScriptToken( Token.DOT, "." ), - new JavaScriptToken( Token.NAME, "callee" ), - new JavaScriptToken( Token.DOT, "." ), - new JavaScriptToken( Token.NAME, "base" ), - new JavaScriptToken( Token.DOT, "." ), - new JavaScriptToken( Token.NAME, "call" ), - new JavaScriptToken( Token.LP, "(" ), - new JavaScriptToken( Token.NAME, "this" ) - }; - markRangeForReplacement( baseCall, replacement ); - nextPos = baseCall.end + 1; - } - return nextPos; - } - - private int markTokensForRemoval( int first, int last ) { - replacements.add( new Replacement( first, last, null ) ); - return last - first + 1; - } - - private void markRangeForReplacement( Range range, - JavaScriptToken[] replacementTokens ) - { - replacements.add( new Replacement( range.begin, - range.end, - replacementTokens ) ); - } - - private void doReplacements() { - Collections.sort( replacements, new Comparator() { - public int compare( Replacement repl1, Replacement repl2 ) { - return repl1.end < repl2.end ? 1 : repl1.end == repl2.end ? 0 : -1; - } - } ); - for( Iterator iterator = replacements.iterator(); iterator.hasNext(); ) { - Replacement replacement = iterator.next(); - tokens.replaceTokens( replacement.begin, replacement.end, replacement.replacement ); - } - } - - private static boolean canRemoveVariant( String variantName ) { - return "qx.debug".equals( variantName ) - || "qx.compatibility".equals( variantName ) - || "qx.aspects".equals( variantName ); - } - - VariantConditional readVariantConditional( int offset ) { - VariantConditional result = null; - int pos = offset; - boolean matched = true; - TokenMatcher nameMatcher = TokenMatcher.string(); - matched &= TokenMatcher.IF.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.LEFT_PAREN.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "rwt" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "util" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "Variant" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "isSet" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.LEFT_PAREN.matches( tokens.getToken( pos++ ) ); - matched &= nameMatcher.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.COMMA.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.string( "on" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.RIGHT_PAREN.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.RIGHT_PAREN.matches( tokens.getToken( pos++ ) ); - if( matched ) { - result = new VariantConditional( offset, pos - 1, nameMatcher.matchedValue ); - } - return result; - } - - VariantSelection readVariantSelection( int offset ) { - VariantSelection result = null; - int pos = offset; - boolean matched = true; - TokenMatcher nameMatcher = TokenMatcher.string(); - matched &= TokenMatcher.name( "rwt" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "util" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "Variant" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "select" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.LEFT_PAREN.matches( tokens.getToken( pos++ ) ); - matched &= nameMatcher.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.COMMA.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.LEFT_BRACE.matches( tokens.getToken( pos++ ) ); - if( matched ) { - result = new VariantSelection( offset, pos - 1, nameMatcher.matchedValue ); - } - return result; - } - - Range readBaseCall( int offset ) { - Range result = null; - int pos = offset; - boolean matched = true; - TokenMatcher nameMatcher = TokenMatcher.name( "arguments" ); - matched &= TokenMatcher.literal( Token.THIS ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.DOT.matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.name( "base" ).matches( tokens.getToken( pos++ ) ); - matched &= TokenMatcher.LEFT_PAREN.matches( tokens.getToken( pos++ ) ); - matched &= nameMatcher.matches( tokens.getToken( pos++ ) ); - if( matched ) { - result = new Range( offset, pos - 1 ); - } - return result; - } - - public static class Range { - public final int begin; - public final int end; - - public Range( int begin, int end ) { - this.begin = begin; - this.end = end; - } - } - - public static class Replacement extends Range { - - public final JavaScriptToken[] replacement; - - public Replacement( int begin, int end, JavaScriptToken[] replacement ) { - super( begin, end ); - this.replacement = replacement; - } - } - - static class VariantConditional extends Range { - - public final String variant; - - public VariantConditional( int begin, int end, String variant ) { - super( begin, end ); - this.variant = variant; - } - } - - static class VariantSelection extends Range { - - public final String variant; - - public VariantSelection( int begin, int end, String variant ) { - super( begin, end ); - this.variant = variant; - } - } -} diff --git a/src/org/eclipse/rap/clientbuilder/StringReplacer.java b/src/org/eclipse/rap/clientbuilder/StringReplacer.java deleted file mode 100644 index 3fb20ce..0000000 --- a/src/org/eclipse/rap/clientbuilder/StringReplacer.java +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; - -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptToken; - - -public final class StringReplacer { - - private HashMap stringMap = new HashMap(); - private List strings; - - public void discoverStrings( TokenList tokens ) { - if( strings != null ) { - throw new IllegalStateException( "Can not add strings after computing indexes" ); - } - int length = tokens.size(); - for( int pos = 0; pos < length; pos++ ) { - if( isReplacableString( tokens, pos ) ) { - String value = tokens.getToken( pos ).getValue(); - Integer count = stringMap.get( value ); - if( count == null ) { - stringMap.put( value, new Integer( 1 ) ); - } else { - stringMap.put( value, new Integer( count.intValue() + 1 ) ); - } - } - } - } - - public void replaceStrings( TokenList tokens ) { - ensureStringListCreated(); - int length = tokens.size(); - for( int pos = length - 1; pos >= 0; pos-- ) { - if( isReplacableString( tokens, pos ) ) { - String string = tokens.getToken( pos ).getValue(); - int index = getIndex( string ); - if( index != -1 ) { - JavaScriptToken[] replacement = createTokensForArrayAccess( "$", index ); - tokens.replaceToken( pos, replacement ); - } - } - } - } - - public void optimize() { - ensureStringListCreated(); - for( int i = strings.size() - 1; i >= 0; i-- ) { - String string = strings.get( i ); - if( !isWorthReplacing( string ) ) { - strings.remove( i ); - } - } - } - - public String[] getStrings() { - ensureStringListCreated(); - String[] result = new String[ strings.size() ]; - strings.toArray( result ); - return result; - } - - private boolean isWorthReplacing( String string ) { - int freq = getFrequency( string ); - return freq > 1 && ( string.length() + 2 ) * ( freq - 1 ) > freq * 6; - } - - private int getFrequency( String string ) { - Integer frequency = stringMap.get( string ); - return frequency == null ? 0 : frequency.intValue(); - } - - private int getIndex( String string ) { - return strings.indexOf( string ); - } - - private void ensureStringListCreated() { - if( strings == null ) { - strings = new ArrayList( stringMap.keySet() ); - Comparator comparator = new Comparator() { - - public int compare( String string1, String string2 ) { - int freq1 = getFrequency( string1 ); - int freq2 = getFrequency( string2 ); - return freq1 < freq2 ? 1 : ( freq1 == freq2 ? 0 : -1 ); - } - }; - Collections.sort( strings, comparator ); - } - } - - private static JavaScriptToken[] createTokensForArrayAccess( String arrayName, - int index ) - { - JavaScriptToken[] replacement = new JavaScriptToken[] { - new JavaScriptToken( Token.NAME, arrayName ), - new JavaScriptToken( Token.LB, "[" ), - new JavaScriptToken( Token.NUMBER, String.valueOf( index ) ), - new JavaScriptToken( Token.RB, "]" ) - }; - return replacement; - } - - private static boolean isReplacableString( TokenList tokens, int pos ) { - boolean result = false; - JavaScriptToken token = tokens.getToken( pos ); - if( isString( token ) ) { - JavaScriptToken nextToken = tokens.getToken( pos + 1 ); - if( !isColonInObjectLiteral( nextToken ) ) { - result = true; - } - } - return result; - } - - static boolean isString( JavaScriptToken token ) { - return token != null && token.getType() == Token.STRING; - } - - static boolean isColonInObjectLiteral( JavaScriptToken token ) { - return token != null && token.getType() == Token.OBJECTLIT; - } -} diff --git a/src/org/eclipse/rap/clientbuilder/TokenList.java b/src/org/eclipse/rap/clientbuilder/TokenList.java deleted file mode 100644 index 1d41808..0000000 --- a/src/org/eclipse/rap/clientbuilder/TokenList.java +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.util.List; - -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptToken; - - -public class TokenList { - - private final List tokens; - - public TokenList( List tokens ) { - this.tokens = tokens; - } - - public int size() { - return tokens.size(); - } - - public JavaScriptToken getToken( int index ) { - JavaScriptToken token = null; - if( index >= 0 && index < tokens.size() ) { - token = tokens.get( index ); - } - return token; - } - - public void removeToken( int index ) { - replaceToken( index, null ); - } - - public void replaceToken( int index, JavaScriptToken[] replacement ) { - replaceTokens( index, index, replacement ); - } - - public void replaceTokens( int begin, int end, JavaScriptToken[] replacement ) { - if( begin >= 0 && begin <= end && end < tokens.size() ) { - for( int i = begin; i <= end; i++ ) { - tokens.remove( begin ); - } - if( replacement != null ) { - for( int i = 0; i < replacement.length; i++ ) { - tokens.add( begin + i, replacement[ i ] ); - } - } - } - } - - public int readExpression( int offset ) { - int result = -1; - JavaScriptToken token = getToken( offset ); - if( TokenMatcher.LEFT_BRACE.matches( token ) || TokenMatcher.LEFT_BRACKET.matches( token ) ) { - result = findClosing( offset ); - } - int pos = offset; - while( pos >= 0 && pos < size() && result == -1 ) { - token = getToken( pos ); - if( TokenMatcher.LEFT_BRACE.matches( token ) - || TokenMatcher.LEFT_BRACKET.matches( token ) - || TokenMatcher.LEFT_PAREN.matches( token ) ) - { - pos = findClosing( pos ) + 1; - } else if( TokenMatcher.RIGHT_BRACE.matches( token ) - || TokenMatcher.RIGHT_BRACKET.matches( token ) - || TokenMatcher.RIGHT_PAREN.matches( token ) - || TokenMatcher.COMMA.matches( token ) - || TokenMatcher.SEMI.matches( token ) ) - { - result = pos - 1; - } else { - pos++; - } - } - if( result == -1 ) { - result = pos - 1; - } - return result; - } - - public int findClosing( int offset ) { - int result = -1; - TokenMatcher leftMatcher; - TokenMatcher rightMatcher; - JavaScriptToken token = getToken( offset ); - if( TokenMatcher.LEFT_BRACE.matches( token ) ) { - leftMatcher = TokenMatcher.LEFT_BRACE; - rightMatcher = TokenMatcher.RIGHT_BRACE; - } else if( TokenMatcher.LEFT_BRACKET.matches( token ) ) { - leftMatcher = TokenMatcher.LEFT_BRACKET; - rightMatcher = TokenMatcher.RIGHT_BRACKET; - } else if( TokenMatcher.LEFT_PAREN.matches( token ) ) { - leftMatcher = TokenMatcher.LEFT_PAREN; - rightMatcher = TokenMatcher.RIGHT_PAREN; - } else { - String message = "Not an opening brace, bracket or parenthesis at pos " + offset; - throw new IllegalArgumentException( message ); - } - int level = 0; - int pos = offset; - while( pos < tokens.size() && result == -1 ) { - token = getToken( pos ); - if( leftMatcher.matches( token ) ) { - level++; - } else if( rightMatcher.matches( token ) ) { - level--; - if( level == 0 ) { - result = pos; - } - } - pos++; - } - return result; - } - - public int findInObjectLiteral( String key, int offset ) { - if( !TokenMatcher.LEFT_BRACE.matches( getToken( offset ) ) ) { - throw new IllegalArgumentException( "Not an object literal at pos " + offset ); - } - int result = -1; - int closingBrace = findClosing( offset ); - if( closingBrace == -1 ) { - throw new IllegalArgumentException( "No closing brace found for pos " + offset ); - } - int pos = offset + 1; - TokenMatcher keyStringMatcher = TokenMatcher.string(); - TokenMatcher keyNameMatcher = TokenMatcher.name(); - while( pos < closingBrace - 2 ) { - JavaScriptToken token = getToken( pos ); - if( keyStringMatcher.matches( token ) || keyNameMatcher.matches( token ) ) { - if( key.equals( keyStringMatcher.matchedValue ) - || key.equals( keyNameMatcher.matchedValue ) - || "default".equals( keyStringMatcher.matchedValue ) - || "default".equals( keyNameMatcher.matchedValue ) ) - { - if( TokenMatcher.OBJECTLIT.matches( getToken( pos + 1 ) ) ) { - result = pos + 2; - } - } - } - pos++; - } - return result; - } - - public static class TokenPattern { - - private final TokenMatcher[] matchers; - - public TokenPattern( TokenMatcher[] matchers ) { - this.matchers = matchers; - } - - public int read( TokenList reader, int offset ) { - boolean result = true; - for( int i = 0; i < matchers.length && result; i++ ) { - matchers[ i ].clear(); - } - int pos = offset; - for( int i = 0; i < matchers.length && result; i++ ) { - result &= matchers[ i ].matches( reader.getToken( pos ) ); - pos++; - } - if( result ) { - return pos - 1; - } - return -1; - } - } - - public static class TokenMatcher { - - public static final TokenMatcher DOT = TokenMatcher.literal( Token.DOT ); - - public static final TokenMatcher IF = TokenMatcher.literal( Token.IF ); - - public static final TokenMatcher ELSE = TokenMatcher.literal( Token.ELSE ); - - public static final TokenMatcher COMMA = TokenMatcher.literal( Token.COMMA ); - - public static final TokenMatcher SEMI = TokenMatcher.literal( Token.SEMI ); - - public static final TokenMatcher OBJECTLIT = TokenMatcher.literal( Token.OBJECTLIT ); - - public static final TokenMatcher LEFT_PAREN = TokenMatcher.literal( Token.LP ); - - public static final TokenMatcher RIGHT_PAREN = TokenMatcher.literal( Token.RP ); - - public static final TokenMatcher LEFT_BRACE = TokenMatcher.literal( Token.LC ); - - public static final TokenMatcher RIGHT_BRACE = TokenMatcher.literal( Token.RC ); - - public static final TokenMatcher LEFT_BRACKET = TokenMatcher.literal( Token.LB ); - - public static final TokenMatcher RIGHT_BRACKET = TokenMatcher.literal( Token.RB ); - - private final int expectedType; - private final String expectedValue; - public String matchedValue; - - public static TokenMatcher string() { - return new TokenMatcher( Token.STRING, null ); - } - - public static TokenMatcher name() { - return new TokenMatcher( Token.NAME, null ); - } - - public static TokenMatcher string( String string ) { - return new TokenMatcher( Token.STRING, string ); - } - - public static TokenMatcher name( String string ) { - return new TokenMatcher( Token.NAME, string ); - } - - public static TokenMatcher literal( int type ) { - return new TokenMatcher( type, null ); - } - - private TokenMatcher( int type, String value ) { - this.expectedType = type; - this.expectedValue = value; - } - - public boolean matches( JavaScriptToken token ) { - boolean result = false; - matchedValue = null; - if( token != null ) { - result = token.getType() == expectedType; - if( expectedValue != null ) { - result &= expectedValue.equals( token.getValue() ); - } else { - matchedValue = token.getValue(); - } - } - return result; - } - - public String getMatchedValue() { - return matchedValue; - } - - public void clear() { - matchedValue = null; - } - } -} diff --git a/src/org/eclipse/swt/internal/widgets/displaykit/JsFilesList.java b/src/org/eclipse/swt/internal/widgets/displaykit/JsFilesList.java deleted file mode 100644 index adc2ff7..0000000 --- a/src/org/eclipse/swt/internal/widgets/displaykit/JsFilesList.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.swt.internal.widgets.displaykit; - -import java.lang.reflect.Field; - - -public final class JsFilesList { - - private JsFilesList() { - // prevent instantiation - } - - public static String[] getFiles() - throws SecurityException, NoSuchFieldException, IllegalAccessException - { - Class clazz = ClientResources.class; - Field field = clazz.getDeclaredField( "JAVASCRIPT_FILES" ); - field.setAccessible( true ); - String[] files = ( String[] )field.get( null ); - for( int i = 0; i < files.length; i++ ) { - if( "debug-settings.js".equals( files[ i ] ) ) { - files[ i ] = "settings.js"; - } - } - return files; - } -} diff --git a/test/com/yahoo/platform/yui/compressor/ParserTest.java b/test/com/yahoo/platform/yui/compressor/ParserTest.java deleted file mode 100644 index 8db5bbd..0000000 --- a/test/com/yahoo/platform/yui/compressor/ParserTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.yahoo.platform.yui.compressor; - -import junit.framework.TestCase; - -import org.eclipse.rap.clientbuilder.TestUtil; -import org.eclipse.rap.clientbuilder.TokenList; -import org.mozilla.javascript.ErrorReporter; -import org.mozilla.javascript.Token; - -public class ParserTest extends TestCase { - - static final ErrorReporter REPORTER = new TestErrorReporter(); - - public void testParseNumber() throws Exception { - TokenList result = TestUtil.parse( "23.0" ); - assertEquals( 2, result.size() ); - assertEquals( Token.NUMBER, result.getToken( 0 ).getType() ); - assertEquals( Token.SEMI, result.getToken( 1 ).getType() ); - } - - public void testParseVar() throws Exception { - TokenList tokens = TestUtil.parse( "var x = 12;" ); - assertEquals( 5, tokens.size() ); - assertEquals( Token.VAR, tokens.getToken( 0 ).getType() ); - assertEquals( Token.NAME, tokens.getToken( 1 ).getType() ); - assertEquals( Token.ASSIGN, tokens.getToken( 2 ).getType() ); - assertEquals( Token.NUMBER, tokens.getToken( 3 ).getType() ); - assertEquals( Token.SEMI, tokens.getToken( 4 ).getType() ); - } - - public void testParseAssignment() throws Exception { - TokenList tokens = TestUtil.parse( "a = 1;" ); - assertEquals( 4, tokens.size() ); - assertEquals( Token.NAME, tokens.getToken( 0 ).getType() ); - assertEquals( Token.ASSIGN, tokens.getToken( 1 ).getType() ); - assertEquals( Token.NUMBER, tokens.getToken( 2 ).getType() ); - assertEquals( Token.SEMI, tokens.getToken( 3 ).getType() ); - } - - public void testParseArrayAccess() throws Exception { - TokenList tokens = TestUtil.parse( "a = $[23];" ); - assertEquals( 7, tokens.size() ); - assertEquals( Token.NAME, tokens.getToken( 0 ).getType() ); - assertEquals( Token.ASSIGN, tokens.getToken( 1 ).getType() ); - assertEquals( Token.NAME, tokens.getToken( 2 ).getType() ); - assertEquals( Token.LB, tokens.getToken( 3 ).getType() ); - assertEquals( Token.NUMBER, tokens.getToken( 4 ).getType() ); - assertEquals( Token.RB, tokens.getToken( 5 ).getType() ); - assertEquals( Token.SEMI, tokens.getToken( 6 ).getType() ); - } -} diff --git a/test/com/yahoo/platform/yui/compressor/TestAdapter.java b/test/com/yahoo/platform/yui/compressor/TestAdapter.java deleted file mode 100644 index b3bc517..0000000 --- a/test/com/yahoo/platform/yui/compressor/TestAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.yahoo.platform.yui.compressor; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import org.mozilla.javascript.EvaluatorException; - -/** - * Adapter to access package private fields and methods of the YUI Compressor. - */ -public final class TestAdapter { - - public static List parseString( String input ) - throws EvaluatorException, IOException - { - Reader inputReader = new StringReader( input ); - TestErrorReporter reporter = new TestErrorReporter(); - @SuppressWarnings( "unchecked" ) - ArrayList tokens = JavaScriptCompressor.parse( inputReader, reporter ); - return tokens; - } - - public static String getLiteralString( int type ) { - return ( String )JavaScriptCompressor.literals.get( new Integer( type ) ); - } -} diff --git a/test/com/yahoo/platform/yui/compressor/TestErrorReporter.java b/test/com/yahoo/platform/yui/compressor/TestErrorReporter.java deleted file mode 100644 index 2196df3..0000000 --- a/test/com/yahoo/platform/yui/compressor/TestErrorReporter.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.yahoo.platform.yui.compressor; - -import org.mozilla.javascript.ErrorReporter; -import org.mozilla.javascript.EvaluatorException; - -public final class TestErrorReporter implements ErrorReporter { - - public void warning( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - System.out.println( getMessage( "WARNING", message ) ); - } - - public void error( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - System.out.println( getMessage( "ERROR", message ) ); - } - - public EvaluatorException runtimeError( String message, - String sourceName, - int line, - String lineSource, - int lineOffset ) - { - error( message, sourceName, line, lineSource, lineOffset ); - return new EvaluatorException( message ); - } - - private String getMessage( String severity, String message ) { - StringBuffer result = new StringBuffer(); - result.append( "\n[" ); - result.append( severity ); - result.append( "] " ); - result.append( message ); - return result.toString(); - } -} diff --git a/test/org/eclipse/rap/clientbuilder/CompressorTest.java b/test/org/eclipse/rap/clientbuilder/CompressorTest.java deleted file mode 100644 index c16a4a3..0000000 --- a/test/org/eclipse/rap/clientbuilder/CompressorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 EclipseSource and others. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.IOException; - - -import junit.framework.TestCase; - -public class CompressorTest extends TestCase { - - public void testCompressEmpty() throws IOException { - assertEquals( "", TestUtil.compress( "" ) ); - } - - public void testCompressNumbers() throws IOException { - assertEquals( "23;", TestUtil.compress( "23" ) ); - assertEquals( "23;", TestUtil.compress( " 23.0 " ) ); - } - - public void testCompressStrings() throws IOException { - assertEquals( "\"\";", TestUtil.compress( "''" ) ); - assertEquals( "\"a\";", TestUtil.compress( "'a'" ) ); - } - - public void testCompressExpressions() throws IOException { - assertEquals( "23+\"\";", TestUtil.compress( " 23 + ''" ) ); - } - - public void testCompressEscapes() throws IOException { - assertEquals( "\"\";", TestUtil.compress( "\"\"" ) ); - assertEquals( "\"\\\\\";", TestUtil.compress( "\"\\\\\"" ) ); - // Unicode characters are not escaped as the output file is in UTF-8 - assertEquals( "\"\u0416\";", TestUtil.compress( "\"\u0416\"" ) ); - // Unicode escapes are transformed into Unicode characters - assertEquals( "\"\u0416\";", TestUtil.compress( "\"\\u0416\"" ) ); - assertEquals( "\"\u00CF\";", TestUtil.compress( "\"\\xCF\"" ) ); - } -} diff --git a/test/org/eclipse/rap/clientbuilder/QxCleanupTest.java b/test/org/eclipse/rap/clientbuilder/QxCleanupTest.java deleted file mode 100644 index 76bd02d..0000000 --- a/test/org/eclipse/rap/clientbuilder/QxCleanupTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2012 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import junit.framework.TestCase; - - -public class QxCleanupTest extends TestCase { - - public void testRemoveEmptyDebugVariantConditional() throws Exception { - String input = "if( rwt.util.Variant.isSet( \"qx.debug\", \"on\" ) ) {\n" - + "}\n"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - assertEquals( 0, tokens.size() ); - } - - public void testRemoveCompatVariantConditional() throws Exception { - String input = "if( rwt.util.Variant.isSet( \"qx.compatibility\", \"on\" ) ) {\n" - + "}\n"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - assertEquals( 0, tokens.size() ); - } - - public void testRemoveAspectVariantConditional() throws Exception { - String input = "if( rwt.util.Variant.isSet( \"qx.aspects\", \"on\" ) ) {\n" - + "}\n"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - assertEquals( 0, tokens.size() ); - } - - public void testRemoveMultipleVariantConditionals() throws Exception { - String input = "if( rwt.util.Variant.isSet( \"qx.debug\", \"on\" ) ) {\n" - + "}\n"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - assertEquals( 0, tokens.size() ); - } - - public void testRemoveVariantConditionalBetweenStatements() throws Exception { - String input = "a = 1;\n" - + "if( rwt.util.Variant.isSet( \"qx.debug\", \"on\" ) ) {\n" - + " if( false ) { throw \"ERROR\" }\n" - + "}\n" - + "b = 2;"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - assertEquals( "a = 1;\nb = 2;", result ); - } - - public void testRemoveVariantConditionalWithElseBlock() throws Exception { - String input = "if( rwt.util.Variant.isSet( \"qx.debug\", \"on\" ) ) {\n" - + " a = 1;\n" - + "}\n else {\n" - + " b = 2;\n" - + "}"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - assertEquals( "b = 2;", result ); - } - - public void testRemoveNestedVariantConditional() throws Exception { - String input = "if( vObject && vObject.__disposed === false ) {\n" - + " try {\n" - + " vObject.dispose();\n" - + " }\n" - + " catch( ex ) {\n" - + " if( rwt.util.Variant.isSet( \"qx.debug\", \"on\" ) ) {\n" - + " qx.core.Log.warn( \"Could not dispose: \" + vObject + \":\", ex );\n" - + " }\n" - + " }\n" - + "}\n"; - String expected = "if ( vObject && vObject.__disposed === false ) {\n" - + " try {\n" - + " vObject.dispose ( );\n" - + " }\n" - + " catch ( ex ) {\n" - + " }\n" - + "}"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - assertEquals( expected, result ); - } - - public void testReplaceVariantSelection() throws Exception { - String input = "result = rwt.util.Variant.select( \"qx.debug\", {\n" - + " \"on\": {\n" - + " \"foo\" : 23,\n" - + " \"bar\" : 42\n" - + " },\n" - + " \"default\" : null\n" - + "} )"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - assertEquals( "result = null;", result ); - } - - public void testReplaceBaseCall() throws Exception { - String input = "result = this.base( arguments );"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - String expected = "result = arguments.callee.base.call ( this );"; - assertEquals( expected, result ); - } - - public void testReplaceBaseCallWithParameters() throws Exception { - String input = "result = this.base( arguments, 23, 'foo' );"; - TokenList tokens = TestUtil.parse( input ); - QxCodeCleaner cleaner = new QxCodeCleaner( tokens ); - cleaner.cleanupQxCode(); - String result = JavaScriptPrinter.printTokens( tokens ); - String expected = "result = arguments.callee.base.call ( this, 23, \"foo\" );"; - assertEquals( expected, result ); - } -} diff --git a/test/org/eclipse/rap/clientbuilder/StringReplacer_Test.java b/test/org/eclipse/rap/clientbuilder/StringReplacer_Test.java deleted file mode 100644 index aacf5fb..0000000 --- a/test/org/eclipse/rap/clientbuilder/StringReplacer_Test.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -import junit.framework.TestCase; - - -public class StringReplacer_Test extends TestCase { - - public void testDiscoverStrings() throws IOException { - TokenList tokens = TestUtil.parse( "var foo = 'foo';" ); - StringReplacer replacer = new StringReplacer(); - replacer.discoverStrings( tokens ); - assertEquals( 1, replacer.getStrings().length ); - } - - public void testDiscoverStrings_NoMatches() throws IOException { - TokenList tokens = TestUtil.parse( "var foo = 1; var bar = { 'foo' : 1 };" ); - StringReplacer replacer = new StringReplacer(); - replacer.discoverStrings( tokens ); - assertEquals( 0, replacer.getStrings().length ); - } - - public void testDiscoverStrings_MultipleOccurences() throws IOException { - TokenList tokens = TestUtil.parse( "var foo1 = 'foo';\n" - + "var foo2 = 'foo';\n" - + "var bar1 = 'bar';\n" - + "var bar2 = 'bar';" ); - StringReplacer replacer = new StringReplacer(); - replacer.discoverStrings( tokens ); - assertEquals( 2, replacer.getStrings().length ); - } - - public void testGetStrings_SortedByFrequency() throws IOException { - List list = new ArrayList(); - for( int frequency = 1; frequency <= 10; frequency++ ) { - for( int i = 0; i < frequency; i++ ) { - list.add( "var v" + frequency + "_" + i + " = '" + frequency + "x';" ); - } - } - Collections.shuffle( list, new Random() ); - StringBuffer buffer = new StringBuffer(); - for( String string : list ) { - buffer.append( string ); - } - TokenList tokens = TestUtil.parse( buffer.toString() ); - StringReplacer replacer = new StringReplacer(); - replacer.discoverStrings( tokens ); - assertEquals( 10, replacer.getStrings().length ); - assertEquals( "10x", replacer.getStrings()[ 0 ] ); - assertEquals( "9x", replacer.getStrings()[ 1 ] ); - assertEquals( "2x", replacer.getStrings()[ 8 ] ); - assertEquals( "1x", replacer.getStrings()[ 9 ] ); - } - - public void testReplaceStrings() throws IOException { - TokenList tokens = TestUtil.parse( "var foo = 'foo' + 'foo'; var bar = 'bar';" ); - StringReplacer replacer = new StringReplacer(); - replacer.discoverStrings( tokens ); - replacer.replaceStrings( tokens ); - String result = JavaScriptPrinter.printTokens( tokens ); - String expected = "var foo = $ [ 0 ] + $ [ 0 ];\n" + "var bar = $ [ 1 ];"; - assertEquals( expected, result ); - } -} diff --git a/test/org/eclipse/rap/clientbuilder/TestUtil.java b/test/org/eclipse/rap/clientbuilder/TestUtil.java deleted file mode 100644 index 879c02e..0000000 --- a/test/org/eclipse/rap/clientbuilder/TestUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.List; - -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptCompressor; -import com.yahoo.platform.yui.compressor.JavaScriptToken; -import com.yahoo.platform.yui.compressor.TestAdapter; -import com.yahoo.platform.yui.compressor.TestErrorReporter; - - -public class TestUtil { - - public static TokenList parse( String input ) throws IOException { - List tokens = TestAdapter.parseString( input ); - return new TokenList( tokens ); - } - - public static String compress( String input ) throws IOException { - Reader inputReader = new StringReader( input ); - TestErrorReporter errorReporter = new TestErrorReporter(); - JavaScriptCompressor compressor = new JavaScriptCompressor( inputReader, errorReporter ); - StringWriter outputWriter = new StringWriter(); - compressor.compress( outputWriter, -1, true, false, false, false ); - return outputWriter.toString(); - } - - public static void printTokens( TokenList tokens ) { - int size = tokens.size(); - for( int i = 0; i < size; i++ ) { - printToken( i, tokens.getToken( i ) ); - } - } - - private static void printToken( int n, JavaScriptToken token ) { - int type = token.getType(); - switch( type ) { - case Token.NAME: - System.out.println( n + ". name: " + token.getValue() ); - break; - case Token.REGEXP: - System.out.println( n + ". regexp: " + token.getValue() ); - break; - case Token.STRING: - System.out.println( n + ". string: " + token.getValue() ); - break; - case Token.NUMBER: - System.out.println( n + ". number: " + token.getValue() ); - break; - default: - String litStr = TestAdapter.getLiteralString( type ); - System.out.println( n + ". literal: " + litStr ); - break; - } - } -} diff --git a/test/org/eclipse/rap/clientbuilder/TokenList_Test.java b/test/org/eclipse/rap/clientbuilder/TokenList_Test.java deleted file mode 100644 index c831434..0000000 --- a/test/org/eclipse/rap/clientbuilder/TokenList_Test.java +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package org.eclipse.rap.clientbuilder; - -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.mozilla.javascript.Token; - -import com.yahoo.platform.yui.compressor.JavaScriptToken; - - -public class TokenList_Test extends TestCase { - - public void testCreate() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "Test" ) ); - tokens.add( new JavaScriptToken( Token.LB, "[" ) ); - TokenList tokenList = new TokenList( tokens ); - assertEquals( 2, tokenList.size() ); - } - - public void testGetToken() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "Test" ) ); - tokens.add( new JavaScriptToken( Token.LB, "[" ) ); - TokenList tokenList = new TokenList( tokens ); - assertNull( tokenList.getToken( -1 ) ); - assertEquals( tokens.get( 0 ), tokenList.getToken( 0 ) ); - assertEquals( tokens.get( 1 ), tokenList.getToken( 1 ) ); - assertNull( tokenList.getToken( 2 ) ); - } - - public void testRemoveToken() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "First" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "Second" ) ); - TokenList tokenList = new TokenList( tokens ); - tokenList.removeToken( 0 ); - assertEquals( 1, tokenList.size() ); - assertEquals( "Second", tokenList.getToken( 0 ).getValue() ); - } - - public void testRemoveToken_ModifiesOriginalList() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "First" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "Second" ) ); - TokenList tokenList = new TokenList( tokens ); - tokenList.removeToken( 0 ); - assertEquals( 1, tokens.size() ); - assertEquals( "Second", tokens.get( 0 ).getValue() ); - } - - public void testReplaceToken() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "orig 1" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 2" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 3" ) ); - TokenList tokenList = new TokenList( tokens ); - JavaScriptToken[] replacement = new JavaScriptToken[] { - new JavaScriptToken( Token.STRING, "new 1" ), - new JavaScriptToken( Token.STRING, "new 2" ) - }; - tokenList.replaceToken( 1, replacement ); - assertEquals( 4, tokenList.size() ); - assertEquals( "orig 1", tokenList.getToken( 0 ).getValue() ); - assertEquals( "new 1", tokenList.getToken( 1 ).getValue() ); - assertEquals( "new 2", tokenList.getToken( 2 ).getValue() ); - assertEquals( "orig 3", tokenList.getToken( 3 ).getValue() ); - } - - public void testReplaceToken_WithNull() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "orig 1" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 2" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 3" ) ); - TokenList tokenList = new TokenList( tokens ); - tokenList.replaceToken( 1, null ); - assertEquals( 2, tokenList.size() ); - assertEquals( "orig 1", tokenList.getToken( 0 ).getValue() ); - assertEquals( "orig 3", tokenList.getToken( 1 ).getValue() ); - } - - public void testReplaceToken_ModifiesOriginalList() { - List tokens = new ArrayList(); - tokens.add( new JavaScriptToken( Token.STRING, "orig 1" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 2" ) ); - tokens.add( new JavaScriptToken( Token.STRING, "orig 3" ) ); - TokenList tokenList = new TokenList( tokens ); - JavaScriptToken[] replacement = new JavaScriptToken[] { - new JavaScriptToken( Token.STRING, "new 1" ), - new JavaScriptToken( Token.STRING, "new 2" ) - }; - tokenList.replaceToken( 1, replacement ); - assertEquals( 4, tokenList.size() ); - assertEquals( "orig 1", tokens.get( 0 ).getValue() ); - assertEquals( "new 1", tokens.get( 1 ).getValue() ); - assertEquals( "new 2", tokens.get( 2 ).getValue() ); - assertEquals( "orig 3", tokens.get( 3 ).getValue() ); - } - - public void testFindClosingFailsIfNotOnOpeningBrace() throws Exception { - String input = "a, b, c"; - TokenList tokens = TestUtil.parse( input ); - try { - tokens.findClosing( 0 ); - fail(); - } catch( IllegalArgumentException e ) { - // expected - } - } - - public void testFindClosingBrace() throws Exception { - String input = "a = { foo : 23, bar : { x : 7, y : [ 1, 2, 3 ] } }"; - TokenList tokens = TestUtil.parse( input ); - int closingBrace = tokens.findClosing( 2 ); - assertEquals( 24, closingBrace ); - } - - public void testFindClosingBracket() throws Exception { - String input = "a = [ \"foo\", 23, { x : 7, y : [ 1, 2, 3 ] } ]"; - TokenList tokens = TestUtil.parse( input ); - int closingBrace = tokens.findClosing( 2 ); - assertEquals( 22, closingBrace ); - } - - public void testFindInObjectLiteral() throws Exception { - String input = "a = { \"foo\" : {}, \"bar\" : {} }"; - TokenList tokens = TestUtil.parse( input ); - int startSelectedExpr = tokens.findInObjectLiteral( "foo", 2 ); - assertEquals( 5, startSelectedExpr ); - } - - public void testFindInObjectLiteralUnquoted() throws Exception { - String input = "a = { foo : {}, bar : {} }"; - TokenList tokens = TestUtil.parse( input ); - int startSelectedExpr = tokens.findInObjectLiteral( "bar", 2 ); - assertEquals( 10, startSelectedExpr ); - } - - public void testFindInObjectLiteralDefault() throws Exception { - String input = "a = { \"foo\" : {}, \"default\" : {} }"; - TokenList tokens = TestUtil.parse( input ); - int startSelectedExpr = tokens.findInObjectLiteral( "bar", 2 ); - assertEquals( 10, startSelectedExpr ); - } -}