Initial commit of COMPCExterns - This is messy and I will clean it up, I need to add my tests as well.
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/4ca23e3b Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/4ca23e3b Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/4ca23e3b Branch: refs/heads/develop Commit: 4ca23e3b049ed0e1afc7a1523edde6646ea480eb Parents: 8d0d623 Author: Michael Schmalle <[email protected]> Authored: Tue Jun 9 16:04:21 2015 -0400 Committer: Michael Schmalle <[email protected]> Committed: Tue Jun 9 16:04:21 2015 -0400 ---------------------------------------------------------------------- .../javascript/jscomp/JXCompilerOptions.java | 34 ++ .../codegen/externals/pass/AddMemberPass.java | 347 ++++++++++++++ .../externals/pass/CollectTypesPass.java | 186 ++++++++ .../externals/reference/BaseReference.java | 176 ++++++++ .../externals/reference/ClassReference.java | 416 +++++++++++++++++ .../externals/reference/ConstantReference.java | 82 ++++ .../externals/reference/FieldReference.java | 122 +++++ .../externals/reference/FunctionReference.java | 144 ++++++ .../externals/reference/MemberReference.java | 50 +++ .../externals/reference/MethodReference.java | 138 ++++++ .../externals/reference/ReferenceModel.java | 450 +++++++++++++++++++ .../codegen/externals/utils/FunctionUtils.java | 124 +++++ .../codegen/externals/utils/JSTypeUtils.java | 198 ++++++++ .../codegen/externals/utils/TypeUtils.java | 402 +++++++++++++++++ 14 files changed, 2869 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/com/google/javascript/jscomp/JXCompilerOptions.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/com/google/javascript/jscomp/JXCompilerOptions.java b/compiler.jx/src/com/google/javascript/jscomp/JXCompilerOptions.java new file mode 100644 index 0000000..c31c46d --- /dev/null +++ b/compiler.jx/src/com/google/javascript/jscomp/JXCompilerOptions.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.google.javascript.jscomp; + +public class JXCompilerOptions extends CompilerOptions +{ + + private static final long serialVersionUID = 2021530437904249081L; + + public JXCompilerOptions() + { + super(); + + declaredGlobalExternsOnWindow = false; + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java new file mode 100644 index 0000000..9df1fb3 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java @@ -0,0 +1,347 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.pass; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ClassReference; +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel; + +import com.google.javascript.jscomp.AbstractCompiler; +import com.google.javascript.jscomp.CompilerPass; +import com.google.javascript.jscomp.NodeTraversal; +import com.google.javascript.jscomp.NodeTraversal.Callback; +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.jstype.JSType; + +public class AddMemberPass implements CompilerPass, Callback +{ + private ReferenceModel model; + private AbstractCompiler compiler; + + public AddMemberPass(ReferenceModel model, AbstractCompiler compiler) + { + this.model = model; + this.compiler = compiler; + } + + @Override + public void process(Node externs, Node root) + { + //NodeTraversal.traverse(compiler, root, this); + NodeTraversal.traverseRoots(compiler, this, externs, root); + } + + @Override + public void visit(NodeTraversal t, Node n, Node parent) + { + if (n.getParent() == null || n.isScript() || n.isSyntheticBlock()) + return; + + JSDocInfo jsDoc = n.getJSDocInfo(); //NodeUtil.getBestJSDocInfo(n); + if (jsDoc != null) + { + if (n.isVar()) + { + visitVar(t, n); + } + else if (n.isFunction()) + { + visitFunction(t, n); + } + else if (n.isAssign()) + { + if (n.getFirstChild().isGetProp() + && n.getLastChild().isFunction()) + { + // instance or static method + visitMethod(t, n); + } + else + { + // DOMException.INDEX_SIZE_ERR = 1; + // The first child of the assign is the GetProp node, + // if later you need the value, either change this or check + // for a parent assign node when creating the FieldReference + // which the value would be n.getLastChild() + // XXX visitStaticField(t, n); + //System.err.println(n.toStringTree()); + } + } + else if (n.isGetProp()) + { + if (n.getFirstChild().isName()) + { + visitStaticField(t, n); + //System.err.println(n.toStringTree()); + } + else if (n.getFirstChild().isGetProp()) + { + try + { + if (n.getFirstChild().getFirstChild().isGetProp()) + { + // XXX TODO qualified class names 'chrome.runtime.lastError ' + } + else + { + visitInstanceField(t, n); + } + + } + catch (Exception e) + { + + /* + * + GETPROP 438 [jsdoc_info: JSDocInfo] [source_file: [chrome]] [length: 32] + GETPROP 438 [source_file: [chrome]] [length: 24] + GETPROP 438 [source_file: [chrome]] [length: 14] + NAME chrome 438 [source_file: [chrome]] [length: 6] + STRING runtime 438 [source_file: [chrome]] [length: 7] + STRING lastError 438 [source_file: [chrome]] [length: 9] + STRING message 438 [source_file: [chrome]] [length: 7] + * + */ + // TODO Auto-generated catch block + System.err.println(n.toStringTree()); + e.printStackTrace(); + } + } + + // System.err.println(n.toStringTree()); + } + } + + } + + /* + ASSIGN 48 [jsdoc_info: JSDocInfo] [source_file: [w3c_dom1]] [length: 38] + GETPROP 48 [source_file: [w3c_dom1]] [length: 34] + NAME DOMException 48 [source_file: [w3c_dom1]] [length: 12] + STRING HIERARCHY_REQUEST_ERR 48 [source_file: [w3c_dom1]] [length: 21] + NUMBER 3.0 48 [source_file: [w3c_dom1]] [length: 1] + */ + + // Instance Field (prototype) + // GETPROP 2026 [jsdoc_info: JSDocInfo] [source_file: [es3]] [length: 27] + // GETPROP 2026 [source_file: [es3]] [length: 16] + // NAME RegExp 2026 [source_file: [es3]] [length: 6] + // STRING prototype 2026 [source_file: [es3]] [length: 9] + // STRING ignoreCase 2026 [source_file: [es3]] [length: 10] + + private void visitInstanceField(NodeTraversal t, Node n) + { + Node className = n.getFirstChild().getFirstChild(); + Node name = n.getLastChild(); + model.addField(n, className.getString(), name.getString()); + } + + // Static Field + // GETPROP 1994 [jsdoc_info: JSDocInfo] [source_file: [es3]] [length: 9] + // NAME RegExp 1994 [source_file: [es3]] [length: 6] + // STRING $6 1994 [source_file: [es3]] [length: 2] + + private void visitStaticField(NodeTraversal t, Node n) + { + Node className = n.getFirstChild(); + Node name = n.getLastChild(); + model.addStaticField(n, className.getString(), name.getString()); + } + + /* + + Instance + + ASSIGN 194 [jsdoc_info: JSDocInfo] [source_file: [es3]] [length: 44] + GETPROP 194 [source_file: [es3]] [length: 28] + GETPROP 194 [source_file: [es3]] [length: 16] + NAME Object 194 [source_file: [es3]] [length: 6] + STRING prototype 194 [source_file: [es3]] [length: 9] + STRING constructor 194 [source_file: [es3]] [length: 11] + FUNCTION 194 [source_file: [es3]] [length: 13] + NAME 194 [source_file: [es3]] [length: 13] + PARAM_LIST 194 [source_file: [es3]] [length: 2] + BLOCK 194 [source_file: [es3]] [length: 2] + + Static + + ASSIGN 770 [jsdoc_info: JSDocInfo] [source_file: [es3]] [length: 52] + GETPROP 770 [source_file: [es3]] [length: 10] + NAME Array 770 [source_file: [es3]] [length: 5] + STRING some 770 [source_file: [es3]] [length: 4] + + + */ + + // n == ASSIGN + @SuppressWarnings("unused") + private void visitMethod(NodeTraversal t, Node n) + { + JSDocInfo jsDoc = n.getJSDocInfo(); + if (jsDoc == null) + { + // XXX Waring + return; + } + + //System.out.println(n.toStringTree()); + Node getProp = n.getFirstChild(); + Node getProp2 = getProp.getFirstChild(); + + Node function = n.getLastChild(); + + Node className = getProp2.getFirstChild(); + Node prototype = getProp2.getLastChild(); // check for static + Node functionName = getProp.getLastChild(); + + //Node name = function.getChildAtIndex(0); + Node paramList = function.getChildAtIndex(1); + // if (!getProp.isQualifiedName()) + // { + // + // } + + if (getProp.getFirstChild().isGetProp()) + { + ClassReference classReference = model.getClassReference(className.getString()); + if (classReference != null) + { + classReference.addMethod(n, functionName.getString(), jsDoc, + false); + } + else + { + System.err.println(">>>> {AddMemberPass.addMethod()} Class [" + + className + "] not found in " + n.getSourceFileName()); + } + } + else if (getProp.getFirstChild().isName()) + { + className = getProp.getFirstChild(); + functionName = getProp.getLastChild(); // Same + + //System.err.println(n.toStringTree()); + ClassReference classReference = model.getClassReference(className.getString()); + if (classReference != null) + { + classReference.addMethod(n, functionName.getString(), jsDoc, + true); + } + else + { + System.err.println(">>>> {AddMemberPass.addMethod()} Class [" + + className + "] not found in " + n.getSourceFileName()); + } + + } + + //System.out.println(n.toStringTree()); + } + + /* + + FUNCTION Arguments 34 [jsdoc_info: JSDocInfo] [source_file: [test]] [length: 23] + NAME Arguments 34 [source_file: [test]] [length: 9] + PARAM_LIST 34 [source_file: [test]] [length: 2] + BLOCK 34 [source_file: [test]] [length: 2] + + */ + + @SuppressWarnings("unused") + private void visitFunction(NodeTraversal t, Node n) + { + + JSDocInfo jsDoc = n.getJSDocInfo(); + + if (jsDoc != null) + { + if (jsDoc.isConstructor()) + { + //System.out.println("---------------------------------------------"); + Node name = n.getChildAtIndex(0); + //System.out.println("Class " + name.getString()); + + Node paramList = n.getChildAtIndex(1); + + JSTypeExpression returnType = jsDoc.getReturnType(); + if (returnType != null) + { + JSType jsReturnType = returnType.evaluate(null, + compiler.getTypeRegistry()); + //System.out.println("Returns: " + jsReturnType); + } + + Node block = n.getChildAtIndex(2); + //System.out.println(">>>>>>--------------------------------------"); + //System.out.println(n.toStringTree()); + } + else + { + // XX Global function parseInt(num, base) + //System.out.println(n.toStringTree()); + } + } + } + + private void visitVar(NodeTraversal t, Node n) + { + JSDocInfo jsDoc = n.getJSDocInfo(); + + if (jsDoc != null) + { + if (jsDoc.isConstant()) + { + Node first = n.getFirstChild(); + if (first.isName()) + { + Node second = first.getFirstChild(); + if (second != null && second.isObjectLit()) + { + // * @const + // var Math = {}; + //System.out.println("Final Class " + // + n.getFirstChild().getString()); + //System.out.println(n.toStringTree()); + } + else + { + // * @const + // var Infinity; + //System.out.println("var " + // + n.getFirstChild().getString()); + //System.out.println(n.toStringTree()); + } + } + } + else if (jsDoc.isConstructor()) + { + } + } + } + + @Override + public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n, + Node parent) + { + return true; + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java new file mode 100644 index 0000000..9a20c54 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java @@ -0,0 +1,186 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.pass; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel; + +import com.google.javascript.jscomp.AbstractCompiler; +import com.google.javascript.jscomp.CompilerPass; +import com.google.javascript.jscomp.NodeTraversal; +import com.google.javascript.jscomp.NodeTraversal.Callback; +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.jstype.JSType; + +public class CollectTypesPass implements CompilerPass, Callback +{ + protected AbstractCompiler compiler; + private ReferenceModel model; + + public CollectTypesPass(ReferenceModel model, AbstractCompiler compiler) + { + this.model = model; + this.compiler = compiler; + } + + @Override + public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n, + Node parent) + { + return true; + } + + @Override + public void visit(NodeTraversal t, Node n, Node parent) + { + JSDocInfo jsDoc = n.getJSDocInfo(); + if (jsDoc != null) + { + if (n.isVar()) + { + visitVar(t, n, jsDoc); + } + else if (n.isFunction()) + { + visitFunction(t, n, jsDoc); + } + else if (n.isAssign()) + { + if (n.getFirstChild().isGetProp() + && n.getChildAtIndex(1).isFunction()) + { + // instance or static method + visitMethod(t, n, jsDoc); + } + } + + } + + } + + private void visitVar(NodeTraversal t, Node n, JSDocInfo jsDoc) + { + + Node first = n.getFirstChild(); + if (first.isName()) + { + Node second = first.getFirstChild(); + if (second != null && second.isObjectLit()) + { + if (jsDoc.isConstant()) + { + // * @const + // var Math = {}; + model.addFinalClass(n, n.getFirstChild().getQualifiedName()); + } + } + else if (jsDoc.isConstructor()) + { + /* + VAR 241 [jsdoc_info: JSDocInfo] [source_file: [es5]] [length: 29] + NAME JSONType 241 [source_file: [es5]] [length: 8] + FUNCTION 241 [source_file: [es5]] [length: 13] + NAME 241 [source_file: [es5]] [length: 13] + PARAM_LIST 241 [source_file: [es5]] [length: 2] + BLOCK 241 [source_file: [es5]] [length: 2] + */ + // * @constructor + // var JSONType = function() {}; + Node name = n.getFirstChild(); + if (name.getFirstChild().isFunction()) + { + model.addClass(n, name.getString()); + } + //System.err.println(n.toStringTree()); + } + else + { + if (jsDoc.isConstant()) + { + // * @const + // var Infinity; + model.addConstant(n, n.getFirstChild().getQualifiedName()); + } + else if (jsDoc.getTypedefType() != null) + { + // * @typedef {{prp(foo)}} + // var MyStrcut; + JSTypeExpression typedefType = jsDoc.getTypedefType(); + System.out.println("@typedef " + + n.getFirstChild().getString()); + System.out.println(typedefType); + + JSType jsReturnType = typedefType.evaluate(null, + compiler.getTypeRegistry()); + if (jsReturnType.isRecordType()) + { + // property map of JSType + } + + model.addClass(n, n.getFirstChild().getQualifiedName()); + + //System.out.println(" : " + jsReturnType); + } + } + } + + } + + private void visitFunction(NodeTraversal t, Node n, JSDocInfo jsDoc) + { + if (jsDoc.isConstructor()) + { + Node name = n.getChildAtIndex(0); + //System.out.println("Class " + name.getString()); + //System.out.println(n.toStringTree()); + + model.addClass(n, name.getQualifiedName()); + } + else if (jsDoc.isInterface()) + { + Node name = n.getChildAtIndex(0); + //System.out.println("Interface " + name.getString()); + + model.addInterface(n, name.getQualifiedName()); + } + else + { + // XX Global function parseInt(num, base) + //System.out.println(n.toStringTree()); + Node name = n.getChildAtIndex(0); + //System.out.println("Function " + name.getString()); + + model.addFunction(n, name.getQualifiedName()); + } + } + + private void visitMethod(NodeTraversal t, Node n, JSDocInfo jsDoc) + { + + } + + @Override + public void process(Node externs, Node root) + { + NodeTraversal.traverseRoots(compiler, this, externs, root); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/BaseReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/BaseReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/BaseReference.java new file mode 100644 index 0000000..2b235ef --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/BaseReference.java @@ -0,0 +1,176 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import java.io.File; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel.ExcludedMemeber; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.JSDocInfo.Marker; +import com.google.javascript.rhino.JSDocInfo.StringPosition; +import com.google.javascript.rhino.JSDocInfo.TypePosition; +import com.google.javascript.rhino.Node; + +public abstract class BaseReference +{ + private String qualfiedName; + + protected JSDocInfo comment; + + private File currentFile; + + private Node node; + + private ReferenceModel model; + + public File getCurrentFile() + { + return currentFile; + } + + public void setCurrentFile(File currentFile) + { + this.currentFile = currentFile; + } + + public String getCurrentFileBaseName() + { + return ""; + // return FilenameUtils.getBaseName(currentFile.getAbsolutePath()); + } + + public String getQualifiedName() + { + return qualfiedName; + } + + public Node getNode() + { + return node; + } + + public void setNode(Node node) + { + this.node = node; + } + + public void setComment(JSDocInfo comment) + { + this.comment = comment; + } + + public JSDocInfo getComment() + { + return comment; + } + + public ReferenceModel getModel() + { + return model; + } + + public BaseReference(ReferenceModel model, Node node, String qualfiedName, + JSDocInfo comment) + { + this.model = model; + this.node = node; + this.qualfiedName = qualfiedName; + this.comment = comment; + } + + public void printComment(StringBuilder sb) + { + sb.append(" /**\n"); + + String blockDescription = getComment().getBlockDescription(); + if (blockDescription != null) + { + sb.append(" * "); + sb.append(blockDescription.replaceAll("\\n", "\n * ")); + sb.append("\n *\n"); + } + + for (Marker marker : getComment().getMarkers()) + { + StringPosition name = marker.getAnnotation(); + TypePosition typePosition = marker.getType(); + StringPosition descriptionPosition = marker.getDescription(); + StringBuilder desc = new StringBuilder(); + + // XXX Figure out how to toString() a TypePosition Node for markers + // XXX Figure out how to get a @param name form the Marker + if (!name.getItem().equals("see")) + continue; + + if (name != null) + { + desc.append(name.getItem()); + desc.append(" "); + } + + if (typePosition != null) + { + //desc.append(typePosition.getItem().getString()); + //desc.append(" "); + } + + if (descriptionPosition != null) + { + desc.append(descriptionPosition.getItem()); + desc.append(" "); + } + + sb.append(" * @" + desc.toString() + "\n"); + } + + sb.append(" * @see " + getNode().getSourceFileName() + "\n"); + sb.append(" */\n"); + } + + public ExcludedMemeber isExcluded() + { + return null; + } + + public abstract void emit(StringBuilder sb); + + // public DocletTag findDocTagByName(String tagName) + // { + // for (DocletTag tag : getComment().getTags()) + // { + // if (tag.getName().equals(tagName)) + // { + // return tag; + // } + // } + // return null; + // } + // + // public boolean hasTag(String tagName) + // { + // for (DocletTag tag : getComment().getTags()) + // { + // if (tag.getName().equals(tagName)) + // return true; + // } + // return false; + // } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java new file mode 100644 index 0000000..fe4898d --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java @@ -0,0 +1,416 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.flex.compiler.internal.codegen.externals.utils.JSTypeUtils; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.jstype.JSType; + +public class ClassReference extends BaseReference +{ + + private boolean isFinal; + + private Map<String, FieldReference> fields = new HashMap<String, FieldReference>(); + private Map<String, MethodReference> methods = new HashMap<String, MethodReference>(); + + public Map<String, FieldReference> getFields() + { + return fields; + } + + public Map<String, MethodReference> getMethods() + { + return methods; + } + + public boolean isFinal() + { + return isFinal; + } + + public void setFinal(boolean isFinal) + { + this.isFinal = isFinal; + } + + public final boolean isInterface() + { + return getComment().isInterface(); + } + + public ClassReference(ReferenceModel model, Node node, String qualfiedName, + JSDocInfo comment) + { + super(model, node, qualfiedName, comment); + } + + public FieldReference addField(Node node, String fieldName, + JSDocInfo comment, boolean isStatic) + { + if (hasField(fieldName)) + { + // XXX Warning + return null; + } + + FieldReference field = new FieldReference(getModel(), this, node, + fieldName, comment, isStatic); + + fields.put(fieldName, field); + return field; + } + + public boolean hasSuperField(String fieldName) + { + List<ClassReference> list = getSuperClasses(); + for (ClassReference reference : list) + { + if (reference.hasField(fieldName)) + return true; + } + return false; + } + + public boolean hasSuperMethod(String methodName) + { + List<ClassReference> list = getSuperClasses(); + for (ClassReference reference : list) + { + if (reference.hasMethod(methodName)) + return true; + } + return false; + } + + public List<ClassReference> getSuperClasses() + { + ArrayList<ClassReference> result = new ArrayList<>(); + ClassReference superClass = getSuperClass(); + while (superClass != null) + { + result.add(superClass); + superClass = superClass.getSuperClass(); + } + return result; + } + + public boolean hasField(String fieldName) + { + return fields.containsKey(fieldName); + } + + public boolean hasMethod(String methodName) + { + return methods.containsKey(methodName); + } + + public MethodReference addMethod(Node node, String functionName, + JSDocInfo comment, boolean isStatic) + { + MethodReference method = new MethodReference(getModel(), this, node, + functionName, comment, isStatic); + methods.put(functionName, method); + return method; + } + + @Override + public void emit(StringBuilder sb) + { + String packageName = ""; + + sb.append("package "); + sb.append(packageName + " "); + sb.append("{\n"); + sb.append("\n"); + + printImports(); + + boolean isInterface = isInterface(); + + if (isInterface) + { + printInterface(sb); + } + else + { + printClass(sb); + } + + sb.append("{\n"); + sb.append("\n"); + + if (!isInterface) + { + printConstructor(sb); + sb.append("\n"); + } + + // for (Entry<String, FieldReference> fieldSet : getStaticFields().entrySet()) + // { + // fieldSet.getValue().emit(sb); + // sb.append("\n"); + // } + + for (Entry<String, FieldReference> fieldSet : getFields().entrySet()) + { + fieldSet.getValue().emit(sb); + sb.append("\n"); + } + + for (Entry<String, MethodReference> methodSet : getMethods().entrySet()) + { + MethodReference method = methodSet.getValue(); + //if (!method.isOverride()) + //{ + method.emit(sb); + sb.append("\n"); + //} + } + + sb.append("}\n"); + sb.append("}\n"); // package + + //System.out.println(sb.toString()); + } + + private void printClass(StringBuilder sb) + { + boolean isDynamic = false; + + sb.append("public "); + if (isDynamic) + { + sb.append("dynamic "); + } + + if (isFinal) + { + sb.append("final "); + } + + sb.append("class "); + sb.append(getQualifiedName() + " "); + + if (getComment().hasBaseType()) + { + printSuperClass(sb); + sb.append(" "); + } + // + // if (TagUtils.hasTags(this, "implements")) + // { + // printImplements(sb); + // sb.append(" "); + // } + } + + private void printInterface(StringBuilder sb) + { + sb.append("public interface "); + + sb.append(getQualifiedName() + " "); + + // if (TagUtils.hasTags(this, "extends")) + // { + // printSuperClass(sb); + // sb.append(" "); + // } + } + + private void printSuperClass(StringBuilder sb) + { + sb.append("extends "); + String value = JSTypeUtils.toTypeJsType(getModel().getCompiler(), + getComment().getBaseType()).toString(); + sb.append(value); + } + + @SuppressWarnings("unused") + private void printImplements(StringBuilder sb) + { + // if (TagUtils.hasTags(this, "implements")) + // { + // sb.append("implements "); + // List<DocletTag> impls = TagUtils.getTags(this, "implements"); + // int len = impls.size(); + // for (int i = 0; i < len; i++) + // { + // String value = impls.get(0).getValue(); + // sb.append(value.substring(1, value.length() - 1)); + // if (i < len - 1) + // sb.append(", "); + // } + // } + } + + private void printConstructor(StringBuilder sb) + { + sb.append(" native public function " + getQualifiedName() + "();\n"); + } + + private void printImports() + { + // TODO Auto-generated method stub + + } + + public File getFile(File asSourceRoot) + { + String packageName = ""; + + return new File(asSourceRoot, packageName + File.separator + + getQualifiedName() + ".as"); + } + + public boolean isMethodOverrideFromInterface(MethodReference reference) + { + // if (!hasImplementations()) + // return false; + // + // List<DocletTag> impls = TagUtils.getTags(this, "implements"); + // for (DocletTag docletTag : impls) + // { + // String interfaceName = docletTag.getValue().trim(); + // interfaceName = interfaceName.substring(1, + // interfaceName.length() - 1); + // ClassReference2 classReference = model.getClassReference(interfaceName); + // return classReference.hasMethod(reference.getName()); + // } + + return false; + } + + public MethodReference getMethodOverrideFromInterface( + MethodReference reference) + { + // if (!hasImplementations()) + // return null; + // + // List<DocletTag> impls = TagUtils.getTags(this, "implements"); + // for (DocletTag docletTag : impls) + // { + // String interfaceName = docletTag.getValue().trim(); + // interfaceName = interfaceName.substring(1, + // interfaceName.length() - 1); + // ClassReference2 classReference = model.getClassReference(interfaceName); + // return classReference.getMethods().get(reference.getName()); + // } + + return null; + } + + @SuppressWarnings("unused") + private boolean hasImplementations() + { + return getComment().getImplementedInterfaceCount() > 0; + } + + public boolean hasImplements(String interfaceName) + { + // boolean hasImplements = TagUtils.hasTags(this, "implements"); + // if (hasImplements) + // { + // List<DocletTag> impls = TagUtils.getTags(this, "implements"); + // for (DocletTag tag : impls) + // { + // String value = tag.getValue(); + // value = value.substring(1, value.indexOf("}")); + // return value.equals(interfaceName); + // } + // } + return false; + } + + public ClassReference getSuperClass() + { + JSTypeExpression baseType = getComment().getBaseType(); + if (baseType != null) + { + JSType jsType = baseType.evaluate(null, + getModel().getCompiler().getTypeRegistry()); + if (jsType != null) + return getModel().getClassReference(jsType.getDisplayName()); + } + return null; + } + + public boolean hasSuperFieldConflict(FieldReference reference) + { + // ClassReference2 superClass = getSuperClass(); + // if (superClass != null) + // return superClass.getInstanceFields().containsKey( + // reference.getName()); + return false; + } + + public boolean isPropertyInterfaceImplementation(FieldReference reference) + { + // List<ClassReference2> superInterfaces = getSuperInterfaces(); + // for (ClassReference2 interfaceRef : superInterfaces) + // { + // if (interfaceRef == null) + // { + // System.err.println("isPropertyInterfaceImplementation() null"); + // continue; + // } + // if (interfaceRef.hasFieldConflict(reference)) + // return true; + // } + return false; + } + + @SuppressWarnings("unused") + private List<ClassReference> getSuperInterfaces() + { + ArrayList<ClassReference> result = new ArrayList<>(); + // if (!TagUtils.hasTags(this, "implements")) + // return result; + // + // List<DocletTag> impls = TagUtils.getTags(this, "implements"); + // for (DocletTag tag : impls) + // { + // String type = TagUtils.getType(tag); + // result.add(model.getClassReference(type)); + // } + return result; + } + + public boolean hasLocalMethodConflict(String functionName) + { + return methods.containsKey(functionName); + } + + public boolean hasFieldConflict(FieldReference reference) + { + return getFields().containsKey(reference.getQualifiedName()); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ConstantReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ConstantReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ConstantReference.java new file mode 100644 index 0000000..f920fff --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ConstantReference.java @@ -0,0 +1,82 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import java.util.HashMap; + +import org.apache.flex.compiler.internal.codegen.externals.utils.JSTypeUtils; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public class ConstantReference extends ClassReference +{ + + public ConstantReference(ReferenceModel model, Node node, String name, + JSDocInfo comment) + { + super(model, node, name, comment); + } + + @Override + public void emit(StringBuilder sb) + { + @SuppressWarnings("unused") + String packageName = ""; + + sb.append("package "); + + //sb.append(packageName + " "); + + sb.append("{\n"); + sb.append("\n"); + + String type = JSTypeUtils.toConstantTypeString(this); + String value = resolveValue(type); + + // String type = TypeUtils.getType(findDocTagByName("type")); + // String value = resolveValue(type); + + if (getQualifiedName().equals("undefined")) + { + sb.append(" public const undefined:* = 0;\n"); + } + else + { + sb.append(" public const " + getQualifiedName() + ":" + type + + " = " + value + ";\n"); + } + + sb.append("}\n"); // package + } + + private String resolveValue(String type) + { + HashMap<String, String> map = new HashMap<>(); + map.put("Number", "0"); + map.put("undefined", "0"); + + if (map.containsKey(type)) + return map.get(type); + + return "undefined"; + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java new file mode 100644 index 0000000..5d8e849 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java @@ -0,0 +1,122 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel.ExcludedMemeber; +import org.apache.flex.compiler.internal.codegen.externals.utils.FunctionUtils; +import org.apache.flex.compiler.internal.codegen.externals.utils.JSTypeUtils; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public class FieldReference extends MemberReference +{ + + private boolean isStatic; + + public boolean isStatic() + { + return isStatic; + } + + public void setStatic(boolean isStatic) + { + this.isStatic = isStatic; + } + + public FieldReference(ReferenceModel model, ClassReference classReference, + Node node, String name, JSDocInfo comment, boolean isStatic) + { + super(model, classReference, node, name, comment); + this.isStatic = isStatic; + } + + @Override + public void emit(StringBuilder sb) + { + // Window has a global var Window that conflicts with the constructor. + if (getQualifiedName().equals(getClassReference().getQualifiedName())) + return; + + if (getClassReference().hasSuperField(getQualifiedName())) + return; + + printComment(sb); + + ExcludedMemeber excluded = isExcluded(); + if (excluded != null) + { + excluded.print(sb); + } + + if (!getClassReference().isInterface() && !getComment().isOverride()) + //&& !getClassReference().isPropertyInterfaceImplementation(this)) + { + printVar(sb); + } + else + { + printAccessor(sb); + } + + } + + private void printAccessor(StringBuilder sb) + { + String staticValue = "";//(isStatic) ? "static " : ""; + + String isPublic = getClassReference().isInterface() ? "" : "public "; + + sb.append(" " + isPublic + staticValue + "function get " + + getQualifiedName() + "():" + toReturnString() + ";\n"); + sb.append(" " + isPublic + staticValue + "function set " + + getQualifiedName() + "(" + toPrameterString() + "):void" + + ";\n"); + } + + private void printVar(StringBuilder sb) + { + String staticValue = (isStatic) ? "static " : ""; + + String type = toTypeString(); + if (type.indexOf("|") != -1 || type.indexOf("?") != -1) + type = "*"; + + sb.append(" public " + staticValue + "var " + getQualifiedName() + + ":" + type + ";\n"); + } + + private String toTypeString() + { + return JSTypeUtils.toFieldString(this); + } + + private String toReturnString() + { + return toPrameterString().replace("value:", ""); + } + + private String toPrameterString() + { + return FunctionUtils.toParameter(this, getComment(), "value", + getComment().getType()); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FunctionReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FunctionReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FunctionReference.java new file mode 100644 index 0000000..3cda1c1 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/FunctionReference.java @@ -0,0 +1,144 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import java.io.File; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel.ExcludedMemeber; +import org.apache.flex.compiler.internal.codegen.externals.utils.FunctionUtils; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public class FunctionReference extends BaseReference +{ + private boolean isStatic; + private FunctionReference override; + private Node paramNode; + + public File getFile(File asSourceRoot) + { + String packageName = ""; + + return new File(asSourceRoot, packageName + File.separator + + getQualifiedName() + ".as"); + } + + private FunctionReference getContext() + { + return override == null ? this : override; + } + + public boolean isStatic() + { + return isStatic; + } + + public void setStatic(boolean isStatic) + { + this.isStatic = isStatic; + } + + /* + FUNCTION [node] Scope:Global + NAME + PARAM_LIST + NAME + NAME + BLOCK + */ + + public FunctionReference(ReferenceModel model, Node node, + String qualifiedName, JSDocInfo comment) + { + super(model, node, qualifiedName, comment); + this.paramNode = node.getChildAtIndex(1); + } + + @Override + public void emit(StringBuilder sb) + { + String packageName = ""; + + sb.append("package "); + sb.append(packageName + " "); + sb.append("{\n"); + sb.append("\n"); + + printImports(); + + printComment(sb); + + ExcludedMemeber excluded = isExcluded(); + if (excluded != null) + { + excluded.print(sb); + } + + String staticValue = (isStatic) ? "static " : ""; + + String publicModifier = "public "; + String braces = ""; + + String returns = ""; + if (!transformReturnString().equals("void")) + { + returns = " return null;"; + } + + braces = " { " + returns + " }"; + + sb.append(" "); + sb.append(publicModifier); + sb.append(staticValue); + sb.append("function "); + sb.append(getQualifiedName()); + sb.append(toPrameterString()); + sb.append(":"); + sb.append(transformReturnString()); + sb.append(braces); + sb.append("\n"); + + sb.append("}\n"); // package + } + + private void printImports() + { + // TODO Auto-generated method stub + + } + + private String transformReturnString() + { + return FunctionUtils.transformReturnString(getContext(), getComment()); + } + + private String toPrameterString() + { + return FunctionUtils.toPrameterString(getContext(), getComment(), + paramNode); + } + + public boolean isOverride() + { + return getComment().isOverride(); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MemberReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MemberReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MemberReference.java new file mode 100644 index 0000000..2cb78e5 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MemberReference.java @@ -0,0 +1,50 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel.ExcludedMemeber; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public abstract class MemberReference extends BaseReference +{ + + private ClassReference classReference; + + public ClassReference getClassReference() + { + return classReference; + } + + public MemberReference(ReferenceModel model, ClassReference classReference, + Node node, String name, JSDocInfo comment) + { + super(model, node, name, comment); + this.classReference = classReference; + } + + public ExcludedMemeber isExcluded() + { + return getClassReference().getModel().isExcludedMember( + getClassReference(), this); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java new file mode 100644 index 0000000..2a0db9c --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java @@ -0,0 +1,138 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel.ExcludedMemeber; +import org.apache.flex.compiler.internal.codegen.externals.utils.FunctionUtils; + +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public class MethodReference extends MemberReference +{ + + private boolean isStatic; + private MethodReference override; + private Node paramNode; + + private MethodReference getContext() + { + return override == null ? this : override; + } + + public boolean isStatic() + { + return isStatic; + } + + public void setStatic(boolean isStatic) + { + this.isStatic = isStatic; + } + + public MethodReference(ReferenceModel model, ClassReference classReference, + Node node, String name, JSDocInfo comment, boolean isStatic) + { + super(model, classReference, node, name, comment); + this.isStatic = isStatic; + this.paramNode = node.getLastChild().getChildAtIndex(1); + } + + @Override + public void emit(StringBuilder sb) + { + if (isOverride()) + return; + + if (getClassReference().hasSuperMethod(getQualifiedName())) + return; + + printComment(sb); + + ExcludedMemeber excluded = isExcluded(); + if (excluded != null) + { + excluded.print(sb); + } + + String staticValue = (isStatic) ? "static " : ""; + if (getClassReference().isInterface()) + staticValue = ""; + + String isOverride = ""; + // if (TagUtils.hasTags(this, "override")) + // { + // isOverride = "override "; + // if (getClassReference().isMethodOverrideFromInterface(this)) + // { + // override = getClassReference().getMethodOverrideFromInterface( + // this); + // + // isOverride = ""; + // } + // } + + String publicModifier = ""; + String braces = ""; + String returns = ""; + + if (!transformReturnString().equals("void")) + { + returns = " return null;"; + } + + if (!getClassReference().isInterface()) + { + publicModifier = "public "; + braces = " { " + returns + " }"; + } + + sb.append(" "); + sb.append(publicModifier); + sb.append(isOverride); + sb.append(staticValue); + sb.append("function "); + sb.append(getQualifiedName()); + sb.append(toPrameterString()); + sb.append(":"); + sb.append(transformReturnString()); + sb.append(braces); + sb.append("\n"); + + override = null; + } + + private String transformReturnString() + { + return FunctionUtils.transformReturnString(getContext(), getComment()); + } + + private String toPrameterString() + { + return FunctionUtils.toPrameterString(getContext(), getComment(), + paramNode); + } + + public boolean isOverride() + { + return getComment().isOverride(); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ReferenceModel.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ReferenceModel.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ReferenceModel.java new file mode 100644 index 0000000..60f4bea --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/reference/ReferenceModel.java @@ -0,0 +1,450 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.externals.reference; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.flex.compiler.internal.codegen.externals.pass.AddMemberPass; +import org.apache.flex.compiler.internal.codegen.externals.pass.CollectTypesPass; + +import com.google.common.collect.ImmutableList; +import com.google.javascript.jscomp.CustomPassExecutionTime; +import com.google.javascript.jscomp.JXCompilerOptions; +import com.google.javascript.jscomp.NodeUtil; +import com.google.javascript.jscomp.Result; +import com.google.javascript.jscomp.SourceFile; +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.Node; + +public class ReferenceModel +{ + private static final List<SourceFile> EMPTY_EXTERNS = ImmutableList.of(SourceFile.fromCode( + "externs", "")); + + private File jsRoot; + private File asRoot; + private File asFunctionRoot; + private File asConstantRoot; + + private List<ExcludedMemeber> excludesClass = new ArrayList<>(); + private List<ExcludedMemeber> excludesField = new ArrayList<>(); + private List<ExcludedMemeber> excludes = new ArrayList<>(); + private List<ExternalFile> externals = new ArrayList<>(); + + private HashMap<String, ClassReference> classes = new HashMap<String, ClassReference>(); + //private HashMap<String, ClassReference2> interfaces = new HashMap<String, ClassReference2>(); + private HashMap<String, FunctionReference> functions = new HashMap<String, FunctionReference>(); + private HashMap<String, ConstantReference> constants = new HashMap<String, ConstantReference>(); + + private com.google.javascript.jscomp.Compiler compiler; + + public void setJSRoot(File file) + { + this.jsRoot = file; + } + + public void setASRoot(File file) + { + this.asRoot = file; + + asFunctionRoot = new File(asRoot.getParent(), "as_functions"); + asConstantRoot = new File(asRoot.getParent(), "as_constants"); + } + + public com.google.javascript.jscomp.Compiler getCompiler() + { + return compiler; + } + + public ReferenceModel() + { + //walker = new JSBlockWalker(this); + } + + public void addExclude(String className, String name) + { + excludes.add(new ExcludedMemeber(className, name)); + } + + public void addExclude(String className, String name, String description) + { + excludes.add(new ExcludedMemeber(className, name, description)); + } + + public void addFieldExclude(String className, String fieldName) + { + excludesField.add(new ExcludedMemeber(className, fieldName, "")); + } + + public void addClassExclude(String className) + { + excludesClass.add(new ExcludedMemeber(className, null, "")); + } + + public void addExternal(String name) + { + File file = new File(jsRoot, name + ".js"); + externals.add(new ExternalFile(file)); + } + + public ClassReference getClassReference(String qualifiedName) + { + return classes.get(qualifiedName); + } + + public void addClass(Node node, String qualfiedName) + { + if (classes.containsKey(qualfiedName)) + { + // XXX Record warning; + return; + } + + System.out.println("Model.addClass(" + qualfiedName + ")"); + + ClassReference reference = new ClassReference(this, node, qualfiedName, + node.getJSDocInfo()); + classes.put(qualfiedName, reference); + } + + public void addInterface(Node node, String qualfiedName) + { + if (classes.containsKey(qualfiedName)) + { + // XXX Record warning; + return; + } + + System.out.println("Model.addInterface(" + qualfiedName + ")"); + + ClassReference reference = new ClassReference(this, node, qualfiedName, + node.getJSDocInfo()); + classes.put(qualfiedName, reference); + } + + public void addFinalClass(Node node, String qualfiedName) + { + if (classes.containsKey(qualfiedName)) + { + // XXX Record warning; + return; + } + + System.out.println("Model.addFinalClass(" + qualfiedName + ")"); + + ClassReference reference = new ClassReference(this, node, qualfiedName, + node.getJSDocInfo()); + reference.setFinal(true); + classes.put(qualfiedName, reference); + } + + public void addFunction(Node node, String qualfiedName) + { + if (functions.containsKey(qualfiedName)) + { + // XXX Record warning; + return; + } + + System.out.println("Model.addFunction(" + qualfiedName + ")"); + //System.err.println(node.toStringTree()); + FunctionReference reference = new FunctionReference(this, node, + qualfiedName, node.getJSDocInfo()); + functions.put(qualfiedName, reference); + } + + public void addConstant(Node node, String qualfiedName) + { + if (constants.containsKey(qualfiedName)) + { + // XXX Record warning; + return; + } + + System.out.println("Model.addConstant(" + qualfiedName + ")"); + + ConstantReference reference = new ConstantReference(this, node, + qualfiedName, node.getJSDocInfo()); + constants.put(qualfiedName, reference); + } + + public void addField(Node node, String className, String qualfiedName) + { + ClassReference classReference = getClassReference(className); + classReference.addField(node, qualfiedName, node.getJSDocInfo(), false); + } + + public void addStaticField(Node node, String className, String qualfiedName) + { + ClassReference classReference = getClassReference(className); + // XXX this is here because for now, the doc might be on the parent ASSIGN node + // if it's a static property with a value + JSDocInfo comment = NodeUtil.getBestJSDocInfo(node); + if (classReference != null) + { + classReference.addField(node, qualfiedName, comment, true); + } + else + { + System.err.println(">>>> {ReferenceModel} Class [" + className + + "] not found in " + node.getSourceFileName()); + } + } + + //---------------------------------------------------- + + public void cleanOutput() throws IOException + { + FileUtils.deleteDirectory(asRoot); + asRoot.mkdirs(); + } + + public void emit() throws IOException + { + for (Entry<String, ClassReference> set : classes.entrySet()) + { + StringBuilder sb = new StringBuilder(); + + ClassReference reference = set.getValue(); + if (isExcludedClass(reference) != null) + continue; + + if (!reference.isInterface()) + continue; + + emit(reference, sb); + + File sourceFile = reference.getFile(asRoot); + FileUtils.write(sourceFile, sb.toString()); + } + + for (Entry<String, ClassReference> set : classes.entrySet()) + { + ClassReference reference = set.getValue(); + if (isExcludedClass(reference) != null) + continue; + + if (reference.isInterface()) + continue; + + StringBuilder sb = new StringBuilder(); + + emit(reference, sb); + + File sourceFile = reference.getFile(asRoot); + FileUtils.write(sourceFile, sb.toString()); + } + + for (Entry<String, FunctionReference> set : functions.entrySet()) + { + StringBuilder sb = new StringBuilder(); + + FunctionReference reference = set.getValue(); + emit(reference, sb); + + File sourceFile = reference.getFile(asFunctionRoot); + FileUtils.write(sourceFile, sb.toString()); + } + + for (Entry<String, ConstantReference> set : constants.entrySet()) + { + StringBuilder sb = new StringBuilder(); + + ConstantReference reference = set.getValue(); + emit(reference, sb); + + File sourceFile = reference.getFile(asConstantRoot); + FileUtils.write(sourceFile, sb.toString()); + } + + // StringBuilder sb = new StringBuilder(); + // sb.append("package {\n"); + // for (Entry<String, ConstantReference2> set : constants.entrySet()) + // { + // ConstantReference2 reference = set.getValue(); + // emit(reference, sb); + // } + // sb.append("\n}"); + // File sourceFile = new File(asRoot, "constants.as"); + // FileUtils.write(sourceFile, sb.toString()); + } + + public void emit(BaseReference reference, StringBuilder sb) + { + reference.emit(sb); + } + + public String emit(BaseReference reference) + { + StringBuilder sb = new StringBuilder(); + reference.emit(sb); + return sb.toString(); + } + + public void compile() throws IOException + { + JXCompilerOptions options = new JXCompilerOptions(); + //options.setLanguageIn(LanguageMode.ECMASCRIPT6_TYPED); + //options.setLanguageOut(LanguageMode.ECMASCRIPT6_TYPED); + options.setPreserveTypeAnnotations(true); + options.setPrettyPrint(true); + options.setLineLengthThreshold(80); + options.setPreferSingleQuotes(true); + options.setIdeMode(true); + options.setParseJsDocDocumentation(true); + options.setExternExports(false); + + compiler = new com.google.javascript.jscomp.Compiler(); + + options.addCustomPass(CustomPassExecutionTime.BEFORE_OPTIMIZATIONS, + new CollectTypesPass(this, compiler)); + options.addCustomPass(CustomPassExecutionTime.BEFORE_OPTIMIZATIONS, + new AddMemberPass(this, compiler)); + + //compiler.setErrorManager(testErrorManager); + compiler.initOptions(options); + + //Node script = compiler.parse(SourceFile.fromCode("[test]", source)); + + List<SourceFile> sources = new ArrayList<>(); + for (ExternalFile externalFile : externals) + { + String name = externalFile.getName(); + String source = FileUtils.readFileToString(externalFile.getFile()); + sources.add(SourceFile.fromCode("[" + name + "]", source)); + } + + Result compile = compiler.compile(EMPTY_EXTERNS, sources, options); + if (!compile.success) + { + + } + } + + public ExcludedMemeber isExcludedClass(ClassReference classReference) + { + for (ExcludedMemeber memeber : excludesClass) + { + if (memeber.isExcluded(classReference, null)) + return memeber; + } + return null; + } + + public ExcludedMemeber isExcludedMember(ClassReference classReference, + MemberReference memberReference) + { + if (memberReference instanceof FieldReference) + { + for (ExcludedMemeber memeber : excludesField) + { + if (memeber.isExcluded(classReference, memberReference)) + return memeber; + } + } + for (ExcludedMemeber memeber : excludes) + { + if (memeber.isExcluded(classReference, memberReference)) + return memeber; + } + return null; + } + + public static class ExcludedMemeber + { + private String className; + private String name; + private String description; + + public String getClassName() + { + return className; + } + + public String getName() + { + return name; + } + + public String getDescription() + { + return description; + } + + public ExcludedMemeber(String className, String name) + { + this.className = className; + this.name = name; + } + + public ExcludedMemeber(String className, String name, String description) + { + this.className = className; + this.name = name; + this.description = description; + } + + public boolean isExcluded(ClassReference classReference, + MemberReference memberReference) + { + if (memberReference == null) + { + return classReference.getQualifiedName().equals(className); + } + return classReference.getQualifiedName().equals(className) + && memberReference.getQualifiedName().equals(name); + } + + public void print(StringBuilder sb) + { + if (description != null) + sb.append("// " + description + "\n"); + sb.append("//"); + } + } + + public static class ExternalFile + { + private File file; + + public File getFile() + { + return file; + } + + public ExternalFile(File file) + { + this.file = file; + } + + public String getName() + { + return FilenameUtils.getBaseName(getFile().getAbsolutePath()); + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java new file mode 100644 index 0000000..afb3996 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java @@ -0,0 +1,124 @@ +package org.apache.flex.compiler.internal.codegen.externals.utils; + +import org.apache.flex.compiler.internal.codegen.externals.reference.BaseReference; + +import com.google.common.collect.ImmutableList; +import com.google.javascript.rhino.JSDocInfo; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.Node; + +public class FunctionUtils +{ + public static String transformReturnString(BaseReference reference, + JSDocInfo comment) + { + StringBuilder sb = new StringBuilder(); + ImmutableList<String> names = comment.getTemplateTypeNames(); + if (names.size() > 0) + { + sb.append("Object"); + } + else + { + String type = JSTypeUtils.toReturnTypeString(reference); + if (type.indexOf("|") != -1 || type.indexOf('?') != -1) + type = "*"; + + if (type.indexOf("|") != -1) + type = "Object /* TODO " + type + "*/"; + + sb.append(type); + return sb.toString(); + } + + return sb.toString(); + } + + public static String toPrameterString(BaseReference reference, + JSDocInfo comment, Node paramNode) + { + StringBuilder sb = new StringBuilder(); + sb.append("("); + int index = 0; + int len = comment.getParameterCount(); + + if (len == 0) + { + len = paramNode.getChildCount(); + // Missing JSDocInf @param tags + if (len > 0) + { + for (Node param : paramNode.children()) + { + sb.append(param.getString() + ":Object"); + if (index < len - 1) + sb.append(", "); + index++; + } + } + } + else + { + for (String paramName : comment.getParameterNames()) + { + sb.append(toParameter(reference, comment, paramName, + comment.getParameterType(paramName))); + + if (index < len - 1) + sb.append(", "); + index++; + } + } + + sb.append(")"); + + return sb.toString(); + } + + public static String toParameter(BaseReference reference, + JSDocInfo comment, String paramName, JSTypeExpression parameterType) + { + if (parameterType == null) + { + return "Object /* TODO is this correct? */"; + } + + StringBuilder sb = new StringBuilder(); + + //JSTypeExpression parameterType = comment.getParameterType(paramName); + + ImmutableList<String> names = comment.getTemplateTypeNames(); + if (names.size() > 0) + { + sb.append(paramName); + sb.append(":"); + sb.append("Object"); + } + else + { + if (parameterType.isVarArgs()) + { + sb.append("...rest"); + } + else + { + String paramType = JSTypeUtils.toParamTypeString(reference, + paramName); + + sb.append(paramName); + sb.append(":"); + sb.append(paramType); + + if (paramType.indexOf("|") != -1) + paramType = "Object /* TODO " + paramType + "*/"; + + if (parameterType.isOptionalArg()) + { + sb.append(" = null"); + } + } + } + + return sb.toString(); + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/4ca23e3b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/JSTypeUtils.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/JSTypeUtils.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/JSTypeUtils.java new file mode 100644 index 0000000..1add10b --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/externals/utils/JSTypeUtils.java @@ -0,0 +1,198 @@ +package org.apache.flex.compiler.internal.codegen.externals.utils; + +import org.apache.flex.compiler.internal.codegen.externals.reference.BaseReference; +import org.apache.flex.compiler.internal.codegen.externals.reference.ConstantReference; + +import com.google.javascript.jscomp.AbstractCompiler; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.jstype.JSType; +import com.google.javascript.rhino.jstype.UnionType; + +public class JSTypeUtils +{ + public static String toParamTypeString(BaseReference reference, + String paramName) + { + String type = "Object"; + + JSTypeExpression paramType = reference.getComment().getParameterType( + paramName); + if (paramType != null) + { + JSType jsType = JSTypeUtils.toParamJsType( + reference.getModel().getCompiler(), paramType); + //System.err.println(jsType); + + if (jsType != null) + { + type = jsType.toString(); + + if (jsType.isFunctionType()) + { + return "Function /* " + type + " */"; + } + else + { + if (type.indexOf("Array<") == 0) + { + return "Array"; + } + } + + } + else + { + return "Object"; // TemplateType + } + } + + type = TypeUtils.transformParamType(type); + + return type; + } + + private static JSType toParamJsType(AbstractCompiler compiler, + JSTypeExpression typeExpression) + { + JSType jsType = typeExpression.evaluate(null, + compiler.getTypeRegistry()); + + if (jsType.isUnionType()) + { + UnionType ut = (UnionType) jsType; + JSType jsType2 = ut.restrictByNotNullOrUndefined(); + + //System.err.println(jsType2); + + if (!jsType2.isUnionType()) + jsType = jsType2; + } + + return jsType; + } + + public static String toConstantTypeString(ConstantReference reference) + { + JSTypeExpression typeExpression = reference.getComment().getType(); + JSType jsType = typeExpression.evaluate(null, + reference.getModel().getCompiler().getTypeRegistry()); + String type = jsType.toString(); + type = TypeUtils.transformParamType(type); + return type; + } + + public static String toReturnTypeString(BaseReference reference) + { + String type = "void"; + + JSTypeExpression returnType = reference.getComment().getReturnType(); + if (returnType != null) + { + JSType jsType = JSTypeUtils.toReturnJsType( + reference.getModel().getCompiler(), returnType); + //System.err.println(jsType); + + if (jsType != null) + { + type = jsType.toString(); + + if (type.indexOf("Array<") == 0) + { + return "Array"; + } + } + else + { + return "Object"; // TemplateType + } + } + + type = TypeUtils.transformReturnType(type); + + return type; + } + + private static JSType toReturnJsType(AbstractCompiler compiler, + JSTypeExpression typeExpression) + { + JSType jsType = typeExpression.evaluate(null, + compiler.getTypeRegistry()); + + if (jsType.isUnionType()) + { + UnionType ut = (UnionType) jsType; + JSType jsType2 = ut.restrictByNotNullOrUndefined(); + + if (!jsType2.isUnionType()) + jsType = jsType2; + } + + return jsType; + } + + public static String toFieldString(BaseReference reference) + { + String type = "Object"; + + JSTypeExpression ttype = reference.getComment().getType(); + + if (ttype != null) + { + JSType jsType = JSTypeUtils.toTypeJsType( + reference.getModel().getCompiler(), ttype); + //System.err.println(jsType); + + if (jsType != null) + { + if (jsType.isUnionType()) + { + UnionType ut = (UnionType) jsType; + JSType jsType2 = ut.restrictByNotNullOrUndefined(); + + if (!jsType2.isUnionType()) + jsType = jsType2; + } + + type = jsType.toString(); + + if (jsType.isFunctionType()) + { + return "Function /* " + type + " */"; + } + else + { + if (type.indexOf("Array<") == 0) + { + return "Array"; + } + } + } + else + { + return "Object"; // TemplateType + } + } + + type = TypeUtils.transformType(type); + + return type; + } + + public static JSType toTypeJsType(AbstractCompiler compiler, + JSTypeExpression typeExpression) + { + JSType jsType = typeExpression.evaluate(null, + compiler.getTypeRegistry()); + + if (jsType.isUnionType()) + { + UnionType ut = (UnionType) jsType; + JSType jsType2 = ut.restrictByNotNullOrUndefined(); + + if (!jsType2.isUnionType()) + jsType = jsType2; + } + + return jsType; + } +}
