http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/CompilerAPI.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/CompilerAPI.java b/flex-compiler-oem/src/flex2/compiler/CompilerAPI.java new file mode 100644 index 0000000..00d8376 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/CompilerAPI.java @@ -0,0 +1,98 @@ +/* + * + * 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 flex2.compiler; + +import java.io.File; +import java.io.IOException; + +import flex2.compiler.io.LocalFile; +import flex2.compiler.io.VirtualFile; +import flex2.compiler.config.ConfigurationException; +import flex2.compiler.util.ThreadLocalToolkit; +import flex2.compiler.common.PathResolver; + +/** + * This class orchestrates delegation to the subcompilers using + * batch1() when -conservative is true or batch2(), the default. It + * also handles common tasks like validating CompilationUnit's before + * an incremental compilation, resolving dependences, loading a cache + * from a previous compilation, and storing a compilation cache. + * + * @see flex2.compiler.SubCompiler + * @see flex2.compiler.PersistentStore + * @see flex2.compiler.abc.AbcCompiler + * @see flex2.compiler.as3.As3Compiler + * @see flex2.compiler.css.CssCompiler + * @see flex2.compiler.fxg.FXGCompiler + * @see flex2.compiler.i18n.I18nCompiler + * @see flex2.compiler.mxml.MxmlCompiler + * @author Clement Wong + */ +public final class CompilerAPI +{ + private final static int INHERITANCE = 1; + private final static int NAMESPACES = 2; + private final static int TYPES = 3; + private final static int EXPRESSIONS = 4; + + static String constructClassName(String namespaceURI, String localPart) + { + return (namespaceURI.length() == 0) ? localPart : new StringBuilder(namespaceURI.length() + localPart.length() + 1).append(namespaceURI).append(":").append(localPart).toString(); + } + public static VirtualFile getVirtualFile(String path) throws ConfigurationException + { + return getVirtualFile(path, true); + } + + /** + * Create virtual file for given file and throw configuration exception if not possible + */ + public static VirtualFile getVirtualFile(String path, boolean reportError) throws ConfigurationException + { + VirtualFile result = null; + File file = new File(path); + + if (file != null && file.exists()) + { + try + { + result = new LocalFile(file.getCanonicalFile()); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else + { + PathResolver resolver = ThreadLocalToolkit.getPathResolver(); + result = resolver.resolve(path); + + if (result == null && reportError) + { + throw new ConfigurationException.IOError(path); + } + } + + return result; + } + +}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/CompilerException.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/CompilerException.java b/flex-compiler-oem/src/flex2/compiler/CompilerException.java new file mode 100644 index 0000000..ec25424 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/CompilerException.java @@ -0,0 +1,53 @@ +/* + * + * 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 flex2.compiler; + +/** + * This class provides a common base class for all exceptions thrown + * by the compiler. It can be used in catch statements, but it + * shouldn't be constructed directly. A subclass of CompilerMessage + * should be used when reporting an error or warning. + * + * @author Clement Wong + * @see flex2.compiler.util.CompilerMessage + */ +public class CompilerException extends Exception +{ + private static final long serialVersionUID = 1587688606009074835L; + + public CompilerException() + { + } + + public CompilerException(String message) + { + super(message); + } + + public CompilerException(String message, Throwable cause) + { + super(message, cause); + } + + public CompilerException(Throwable cause) + { + super(cause); + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/ILocalizableMessage.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/ILocalizableMessage.java b/flex-compiler-oem/src/flex2/compiler/ILocalizableMessage.java new file mode 100644 index 0000000..d107d94 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/ILocalizableMessage.java @@ -0,0 +1,35 @@ +/* + * + * 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 flex2.compiler; + +/** + * This is a marker interface for all localizable messages. All + * localized errors and exceptions should implement this. + * + * @author Roger Gonzalez + */ +public interface ILocalizableMessage extends flex2.tools.oem.Message +{ + void setPath(String path); + void setLine(int line); + void setColumn(int column); + Exception getExceptionDetail(); + boolean isPathAvailable(); +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/Logger.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/Logger.java b/flex-compiler-oem/src/flex2/compiler/Logger.java new file mode 100644 index 0000000..2b5e90f --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/Logger.java @@ -0,0 +1,94 @@ +/* + * + * 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 flex2.compiler; + +//import flash.localization.LocalizationManager; + +/** + * The base interface of all loggers in the compiler. + * + * @author Clement Wong + */ +public interface Logger +{ + int errorCount(); + + int warningCount(); + + void logInfo(String info); + + void logDebug(String debug); + + void logWarning(String warning); + + void logError(String error); + + void logInfo(String path, String info); + + void logDebug(String path, String debug); + + void logWarning(String path, String warning); + + void logWarning(String path, String warning, int errorCode); + + void logError(String path, String error); + + void logError(String path, String error, int errorCode); + + void logInfo(String path, int line, String info); + + void logDebug(String path, int line, String debug); + + void logWarning(String path, int line, String warning); + + void logWarning(String path, int line, String warning, int errorCode); + + void logError(String path, int line, String error); + + void logError(String path, int line, String error, int errorCode); + + void logInfo(String path, int line, int col, String info); + + void logDebug(String path, int line, int col, String debug); + + void logWarning(String path, int line, int col, String warning); + + void logError(String path, int line, int col, String error); + + void logWarning(String path, int line, int col, String warning, String source); + + void logWarning(String path, int line, int col, String warning, String source, int errorCode); + + void logError(String path, int line, int col, String error, String source); + + void logError(String path, int line, int col, String error, String source, int errorCode); + + void log(ILocalizableMessage m); + + void log(ILocalizableMessage m, String source); + + void needsCompilation(String path, String reason); + + void includedFileUpdated(String path); + + void includedFileAffected(String path); + +// void setLocalizationManager( LocalizationManager mgr ); +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/Source.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/Source.java b/flex-compiler-oem/src/flex2/compiler/Source.java new file mode 100644 index 0000000..a610047 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/Source.java @@ -0,0 +1,127 @@ +/* + * + * 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 flex2.compiler; + +import flex2.compiler.io.VirtualFile; +import java.util.*; + +/** + * This class represents the information associated with a single file + * while it's being compiled. This information includes the + * <code>pathRoot</code>, the <code>relativePath</code>, the + * <code>shortName</code>, which is often the class name, the owner, + * which specifies where the Source came from, and whether the + * <code>Source</code> is internal, root, and debuggable. + * + * @author Clement Wong + */ +public final class Source implements Comparable<Source> +{ + // used by flex2.compiler.i18n.I18nCompiler, InterfaceCompiler and ImplementationCompiler + public Source(VirtualFile file, Source original) + { + this(file, original.pathRoot, original.relativePath, original.shortName, original.owner, original.isInternal, original.isRoot, original.isDebuggable); + this.delegate = original; + } + + // used by InterfaceCompiler.createInlineComponentUnit(). Note the owner will be set + // later by the ResourceContainer when this is passed into addResource() by + // CompilerAPI.addGeneratedSources(). + public Source(VirtualFile file, Source original, String shortName, boolean isInternal, boolean isRoot) + { + this(file, original.pathRoot, original.relativePath, shortName, null, isInternal, isRoot, true); + this.delegate = original; + } + + // used by FileSpec + public Source(VirtualFile file, String relativePath, String shortName, Object owner, boolean isInternal, boolean isRoot) + { + this(file, null, relativePath, shortName, owner, isInternal, isRoot, true); + } + + // used by SourceList and SourcePath + public Source(VirtualFile file, VirtualFile pathRoot, String relativePath, String shortName, Object owner, boolean isInternal, boolean isRoot) + { + this(file, pathRoot, relativePath, shortName, owner, isInternal, isRoot, true); + } + + // used by StylesContainer, CompilerSwcContext, EmbedEvaluator, DataBindingExtension and PreLink + public Source(VirtualFile file, String relativePath, String shortName, Object owner, boolean isInternal, boolean isRoot, boolean isDebuggable) + { + this(file, null, relativePath, shortName, owner, isInternal, isRoot, isDebuggable); + } + + Source(VirtualFile file, VirtualFile pathRoot, String relativePath, String shortName, Object owner, boolean isInternal, boolean isRoot, boolean isDebuggable) + { + this.file = file; + this.pathRoot = pathRoot; + this.relativePath = relativePath; + this.shortName = shortName; + this.owner = owner; + this.isInternal = isInternal; + this.isRoot = isRoot; + this.isDebuggable = isDebuggable; + + if (file != null) + { + fileTime = file.getLastModified(); + } + + fileIncludeTimes = new HashMap<VirtualFile, Long>(4); + } + + private VirtualFile file; + private VirtualFile pathRoot; + private String relativePath, shortName; + private Object owner; + private boolean isInternal; + private boolean isRoot; + private boolean isDebuggable; + private boolean isPreprocessed; + + private long fileTime; + private Map<VirtualFile, Long> fileIncludeTimes; + + // 1. path resolution + // 2. backing file + // 3. source fragments + private Source delegate; + + public int compareTo(Source source) + { + return getName().compareTo(source.getName()); + } + + public String getName() + { + return file.getName(); + } + + public String getNameForReporting() + { + return file.getNameForReporting(); + } + + public boolean exists() + { + return file.getLastModified() > 0; + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/SourceList.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/SourceList.java b/flex-compiler-oem/src/flex2/compiler/SourceList.java new file mode 100644 index 0000000..1e2e3e0 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/SourceList.java @@ -0,0 +1,370 @@ +/* + * + * 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 flex2.compiler; + +import flex2.compiler.io.FileUtil; +import flex2.compiler.io.LocalFile; +import flex2.compiler.io.VirtualFile; +import flex2.compiler.util.CompilerMessage; +import flex2.compiler.util.NameFormatter; +import flex2.compiler.util.QName; +import flex2.compiler.util.ThreadLocalToolkit; +import flex2.tools.oem.ApplicationCache; + +import java.io.File; +import java.util.*; + +/** + * A SourceList represents a list of files, following the single + * public definition rule, and an associated path where dependencies + * can be found. When compiling via mxmlc, the files specified on the + * command line are put into the <code>SourceList</code>. When + * compiling via Flash Builder, the root or application is included in + * the <code>SourceList</code>. + * + * @author Clement Wong + */ +public final class SourceList +{ + public SourceList(List<VirtualFile> files, VirtualFile[] classPath, VirtualFile appPath, String[] mimeTypes) + throws CompilerException + { + this(files, classPath, appPath, mimeTypes, true); + } + + public SourceList(List<VirtualFile> files, VirtualFile[] classPath, VirtualFile appPath, String[] mimeTypes, boolean lastIsRoot) + throws CompilerException + { + VirtualFile[] vfiles = new VirtualFile[files.size()]; + files.toArray(vfiles); + init(vfiles, classPath, appPath, mimeTypes, lastIsRoot); + } + + private void init(VirtualFile[] files, VirtualFile[] classPath, VirtualFile appPath, String[] mimeTypes, boolean lastIsRoot) + throws CompilerException + { + this.mimeTypes = mimeTypes; + sources = new LinkedHashMap<String, Source>(files.length); + directories = new ArrayList<File>(classPath == null ? 0 : classPath.length); + + SourcePath.addApplicationParentToSourcePath(appPath, classPath, directories); + SourcePath.addPathElements(classPath, directories, true, null); + + for (int i = 0, length = files.length; i < length; i++) + { + // No need to check to see if the appPath is supported again. + if ((appPath != null && files[i].getName().equals(appPath.getName())) || isSupported(files[i])) + { + String name = files[i].getName(); + VirtualFile pathRoot = calculatePathRoot(files[i]); + if (pathRoot != null) + { + String relativePath = calculateRelativePath(name); + String namespaceURI = relativePath.replace('/', '.'); + String localPart = calculateLocalPart(name); + Source source = new Source(files[i], pathRoot, relativePath, localPart, this, false, (i == length - 1) && lastIsRoot); + String className = CompilerAPI.constructClassName(namespaceURI, localPart); + sources.put(className, source); + } + else + { + // Files in SourceList must be in --source-path. + // output an error here... + FileNotInSourcePath ex = new FileNotInSourcePath(name); + ThreadLocalToolkit.log(ex); + throw ex; + } + } + else + { + UnsupportedFileType ex = new UnsupportedFileType(files[i].getName()); + ThreadLocalToolkit.log(ex); + throw ex; + } + } + } + + private VirtualFile calculatePathRoot(VirtualFile f) + { + return calculatePathRoot(f, directories); + } + + static VirtualFile calculatePathRoot(VirtualFile f, List<File> directories) + { + String name = f.getName(); + for (int i = 0, size = directories == null ? 0 : directories.size(); i < size; i++) + { + String dir = directories.get(i).getAbsolutePath(); + if (name.startsWith(dir)) + { + return new LocalFile(FileUtil.openFile(dir)); + } + } + // return new LocalFile(FileUtil.openFile(f.getParent())); + return null; + } + + private String calculateRelativePath(String name) + { + // C: name is canonical. + for (int i = 0, size = directories == null ? 0 : directories.size(); i < size; i++) + { + // Tack on the separatorChar to handle directories, which + // are the same as other, just longer. Like "a" and "a1". + // See SDK-24084. + String dir = directories.get(i).getAbsolutePath() + File.separatorChar; + + if (name.startsWith(dir)) + { + name = name.substring(dir.length()); + int index = name.lastIndexOf(File.separatorChar); + if (index != -1) + { + return name.substring(0, index).replace(File.separatorChar, '/'); + } + else + { + return ""; + } + } + } + + return ""; + } + + private String calculateLocalPart(String name) + { + String leafName = name.substring(name.lastIndexOf(File.separatorChar) + 1); + String localPart = leafName.substring(0, leafName.lastIndexOf('.')); + return localPart; + } + + private Map<String, Source> sources; + private List<File> directories; + private String[] mimeTypes; + + public List<Source> retrieveSources() + { + List<Source> sources = new ArrayList<Source>(this.sources.size()); + + for (Iterator<String> i = this.sources.keySet().iterator(); i.hasNext();) + { + String name = i.next(); + Source s = this.sources.get(name); +// CompilationUnit u = (s != null) ? s.getCompilationUnit() : null; + + if (s != null && !s.exists()) + { + // C: This is a SourceList. If the source doesn't exist, the compiler should get a warning... + s = null; + } + // else if ((u != null && !u.isDone()) || (s != null && s.isUpdated())) + // { + // s.removeCompilationUnit(); + // } + // else if (u != null) + // { + // s = s.copy(); + // assert s != null; + // } + + if (s != null) + { + sources.add(s); + } + } + + return sources; + } + + /* + public Source findSource(String namespaceURI, String localPart) + { + if (sources.size() == 0) + { + return null; + } + + assert localPart.indexOf('.') == -1 && localPart.indexOf('/') == -1 && localPart.indexOf(':') == -1 + : "findSource(" + namespaceURI + "," + localPart + ") has bad localPart"; + + // classname format is a.b:c + String className = CompilerAPI.constructClassName(namespaceURI, localPart); + Source s = sources.get(className); + CompilationUnit u = (s != null) ? s.getCompilationUnit() : null; + + if (s != null && !s.exists()) + { + s = null; + } + + // If the compilation unit does exist and the top level definition name doesn't match + // the specified class name, we don't count it as a match. + if (s != null && u != null && u.topLevelDefinitions.size() == 1) + { + if (!u.topLevelDefinitions.contains(namespaceURI, localPart)) + { + String realName = u.topLevelDefinitions.first().toString(); + sources.put(realName, s); + s = null; + u = null; + } + } + + if (s != null && ((u != null && !u.isDone()) || s.isUpdated())) + { + // s.removeCompilationUnit(); + } + else if (s != null && u != null) + { + s = s.copy(); + assert s != null; + } + + return s; + } + + String[] checkClassNameFileName(Source s) + { + String defName = null, pathName = null; + + if (s.getOwner() == this) + { + QName def = s.getCompilationUnit().topLevelDefinitions.last(); + + defName = def.getLocalPart(); + pathName = s.getShortName(); + + if (defName.equals(pathName)) + { + return null; + } + } + + return new String[] { pathName, defName }; + } + + String[] checkPackageNameDirectoryName(Source s) + { + String defPackage = null, pathPackage = null; + + if (s.getOwner() == this) + { + QName def = s.getCompilationUnit().topLevelDefinitions.last(); + + defPackage = NameFormatter.normalizePackageName(def.getNamespace()); + pathPackage = NameFormatter.toDot(s.getRelativePath(), '/'); + + if (defPackage.equals(pathPackage)) + { + return null; + } + } + + return new String[] { pathPackage, defPackage }; + } + */ + private boolean isSupported(VirtualFile file) + { + for (int i = 0, length = mimeTypes.length; i < length; i++) + { + if (mimeTypes[i].equals(file.getMimeType())) + { + return true; + } + } + + return false; + } + + public List<File> getPaths() + { + return directories; + } + + String[] getMimeTypes() + { + return mimeTypes; + } + + /** + * Checks if there is a cached Source for each local Source and if + * found, copies it's CompilationUnit into it. + public void applyApplicationCache(ApplicationCache applicationCache) + { + for (Map.Entry<String, Source> entry : sources.entrySet()) + { + String className = entry.getKey(); + Source source = entry.getValue(); + Source cachedSource = applicationCache.getSource(className); + + if ((cachedSource != null) && !cachedSource.isUpdated()) + { + CompilationUnit cachedCompilationUnit = cachedSource.getCompilationUnit(); + + if (cachedSource.getPathRoot().equals(source.getPathRoot()) && + (cachedCompilationUnit != null) && cachedCompilationUnit.hasTypeInfo) + { + CompilationUnit compilationUnit = + source.newCompilationUnit(cachedCompilationUnit.getSyntaxTree(), + new CompilerContext()); + + Source.copyCompilationUnit(cachedCompilationUnit, compilationUnit, true); + source.setFileTime(cachedSource.getFileTime()); + cachedSource.reused(); + } + } + } + } + */ + + public Map<String, Source> sources() + { + return sources; + } + + // error messages + + public static class FileNotInSourcePath extends CompilerMessage.CompilerError + { + private static final long serialVersionUID = -1516975612657669682L; + + public FileNotInSourcePath(String name) + { + super(); + this.name = name; + } + + public final String name; + } + + public static class UnsupportedFileType extends CompilerMessage.CompilerError + { + private static final long serialVersionUID = 5300063184460255877L; + + public UnsupportedFileType(String name) + { + super(); + this.name = name; + } + + public final String name; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/SourcePath.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/SourcePath.java b/flex-compiler-oem/src/flex2/compiler/SourcePath.java new file mode 100644 index 0000000..4e356a0 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/SourcePath.java @@ -0,0 +1,647 @@ +/* + * + * 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 flex2.compiler; + +import flex2.compiler.common.SinglePathResolver; +import flex2.compiler.io.FileUtil; +import flex2.compiler.io.LocalFile; +import flex2.compiler.io.VirtualFile; +import flex2.compiler.util.CompilerMessage; +import flex2.compiler.util.MimeMappings; +import flex2.compiler.util.NameFormatter; +import flex2.compiler.util.QName; +import flex2.compiler.util.ThreadLocalToolkit; +import flex2.tools.oem.ApplicationCache; + +import java.io.File; +import java.util.*; + +/** + * A list of paths specified by the -source-path option, where + * dependencies, following the single public definition rule, can be + * resolved. + * + * @author Clement Wong + */ +public class SourcePath extends SourcePathBase + implements SinglePathResolver +{ + protected final List<File> directories; + private ApplicationCache applicationCache; + + public SourcePath(VirtualFile[] classPath, VirtualFile appPath, String[] mimeTypes, boolean allowSourcePathOverlap) + { + this(mimeTypes, allowSourcePathOverlap); + + addApplicationParentToSourcePath(appPath, classPath, this.directories); + addPathElements(classPath, this.directories, allowSourcePathOverlap, warnings); + } + + public SourcePath(String[] mimeTypes, boolean allowSourcePathOverlap) + { + super(mimeTypes, allowSourcePathOverlap); + directories = new LinkedList<File>(); + } + + public void addPathElements(VirtualFile[] classPath) + { + addPathElements(classPath, directories, allowSourcePathOverlap, warnings); + } + + /* + private Source newSource(File file, File pathRoot, String namespaceURI, String localPart) + { + Source source = new Source(new LocalFile(file), new LocalFile(pathRoot), + namespaceURI.replace('.', '/'), localPart, this, false, false); + + if (applicationCache != null) + { + String className = CompilerAPI.constructClassName(namespaceURI, localPart); + Source cachedSource = applicationCache.getSource(className); + + if ((cachedSource != null) && !cachedSource.isUpdated()) + { + CompilationUnit cachedCompilationUnit = cachedSource.getCompilationUnit(); + + if (cachedSource.getPathRoot().equals(source.getPathRoot()) && + (cachedCompilationUnit != null) && cachedCompilationUnit.hasTypeInfo) + { + CompilationUnit compilationUnit = + source.newCompilationUnit(cachedCompilationUnit.getSyntaxTree(), + new CompilerContext()); + + Source.copyCompilationUnit(cachedCompilationUnit, compilationUnit, true); + source.setFileTime(cachedSource.getFileTime()); + cachedSource.reused(); + + // We somehow need to validate that other reused + // sources, which depend on this source, reference + // the same slots. Or maybe it's good enough just + // to validate that the slots referenced by this + // source are the same as the slots referenced by + // the dependencies. Something to ponder. + } + } + } + + return source; + } + + // see if the Source object continues to be the first choice given a QName. + boolean checkPreference(Source s) + { + assert s.getOwner() == this; + + String relativePath = constructRelativePath(s), pathRoot = s.getPathRoot().getName(); + if (relativePath == null) + { + // not possible, but don't disrupt the flow... + return true; + } + + boolean thisPath = false; + + for (int i = 0, size = directories.size(); i < size; i++) + { + File d = directories.get(i), f = null; + if (pathRoot.equals(FileUtil.getCanonicalPath(d))) + { + thisPath = true; + } + + try + { + f = findFile(d, relativePath, mimeTypes); + } + catch (CompilerException ex) + { + removeSource(s); + return false; + } + + if (f != null && !thisPath) + { + removeSource(s); + return false; + } + } + + return true; + } + + protected Source findFile(String className, String namespaceURI, String localPart) throws CompilerException + { + String p = className.replace(':', '.').replace('.', File.separatorChar); + Source s = null; + + for (int i = 0, size = directories.size(); i < size; i++) + { + File f, d = directories.get(i); + + if ((f = findFile(d, p, mimeTypes)) != null) + { + sources.put(className, s = newSource(f, d, namespaceURI, localPart)); + return s; + } + } + + return null; + } + + public boolean hasPackage(String packageName) + { + for (int i = 0, size = directories.size(); i < size; i++) + { + File d = directories.get(i); + if (hasDirectory(d, packageName)) + { + return true; + } + } + + return false; + } + + public boolean hasDefinition(QName qName) + { + String className = CompilerAPI.constructClassName(qName.getNamespace(), qName.getLocalPart()); + + if (misses.contains(className)) + { + return false; + } + + if (hits.contains(className)) + { + return true; + } + + String p = className.replace(':', '.').replace('.', File.separatorChar); + + for (int i = 0, size = directories.size(); i < size; i++) + { + File f, d = directories.get(i); + + try + { + if ((f = findFile(d, p, mimeTypes)) != null) + { + hits.add(className); + return true; + } + } + catch (CompilerException ex) + { + } + } + + misses.add(className); + return false; + } + + private boolean hasDirectory(File dir, String packageName) + { + if (packageName.length() == 0) + { + return true; + } + + String relativePath = packageName.replace('.', File.separatorChar); + String fullPath = dir.getPath() + File.separator + relativePath; + + if (dirs.get(fullPath) == NO_DIR) + { + return false; + } + + boolean result = new File(dir, relativePath).isDirectory(); + dirs.put(fullPath, result ? fullPath : NO_DIR); + + return result; + } + + public List<File> getPaths() + { + return directories; + } + */ + /** + * Resolves paths with a leading slash and relative to a Source + * Path directory. + */ + public VirtualFile resolve(String path) + { + if (path.charAt(0) == '/') + { + String relativePath = path.substring(1); + + for (File directory : directories) + { + File file = FileUtil.openFile(directory, relativePath); + + if ((file != null) && file.exists()) + { + return new LocalFile(file); + } + } + } + + return null; + } + + /* + public void setApplicationCache(ApplicationCache applicationCache) + { + this.applicationCache = applicationCache; + } + */ +} + +/** + * @author Clement Wong + */ +abstract class SourcePathBase +{ + protected final static String NO_DIR = ""; + + static void addApplicationParentToSourcePath(VirtualFile appPath, VirtualFile[] classPath, List<File> directories) + { + if (appPath != null) + { + File f = FileUtil.openFile(appPath.getParent()); + // if (f != null && f.isDirectory()) + if (f != null && f.isDirectory() && (FileUtil.isSubdirectoryOf(appPath.getParent(), classPath) == -1)) + { + directories.add(f); + } + } + } + + static void addPathElements(VirtualFile[] classPath, List<File> directories, boolean allowSourcePathOverlap, List<ClasspathOverlap> warnings) + { + boolean badPaths = false; + + for (int i = 0, length = (classPath == null) ? 0 : classPath.length; i < length; i++) + { + String path = classPath[i].getName(); + File f = FileUtil.openFile(path); + if (f != null && f.isDirectory()) + { + if (!allowSourcePathOverlap && !badPaths) + { + int index = FileUtil.isSubdirectoryOf(f, directories); + if (index != -1) + { + String dirPath = directories.get(index).getAbsolutePath(); + if (checkValidPackageName(path, dirPath)) + { + // C: don't want to use ThreadLocalToolkit here... + + // preilly: don't use logError below, because we don't stop + // compiling and if the error count is non-zero downstream mayhem + // occurs. For example, no SWC's get loaded, which makes it + // alittle tough to compile. + + warnings.add(new ClasspathOverlap(path, dirPath)); + badPaths = true; + } + } + } + directories.add(f); + } + } + } + + private static boolean checkValidPackageName(String path1, String path2) + { + if (path1.equals(path2)) return true; + String packagePath = path1.length() > path2.length() ? path1.substring(path2.length()) : path2.substring(path1.length()); + + for (StringTokenizer t = new StringTokenizer(packagePath, File.separator); t.hasMoreTokens(); ) + { + String s = t.nextToken(); + if (!flex2.compiler.mxml.lang.TextParser.isValidIdentifier(s)) + { + return false; + } + } + + return true; + } + + public SourcePathBase(String[] mimeTypes, boolean allowSourcePathOverlap) + { + this.mimeTypes = mimeTypes; + this.allowSourcePathOverlap = allowSourcePathOverlap; + sources = new HashMap<String, Source>(); + + hits = new HashSet<String>(); + misses = new HashSet<String>(1024); + dirs = new HashMap<String, String>(); + warnings = new ArrayList<ClasspathOverlap>(5); + } + + protected final String[] mimeTypes; + protected final Map<String, Source> sources; + protected boolean allowSourcePathOverlap; + + protected final Set<String> hits, misses; + protected final HashMap<String, String> dirs; + protected final List<ClasspathOverlap> warnings; + + /* + public Source findSource(String namespaceURI, String localPart) throws CompilerException + { + assert localPart.indexOf('.') == -1 && localPart.indexOf('/') == -1 && localPart.indexOf(':') == -1 + : "findSource(" + namespaceURI + "," + localPart + ") has bad localPart"; + + // classname format is a.b:c + String className = CompilerAPI.constructClassName(namespaceURI, localPart); + + return findSource(className, namespaceURI, localPart); + } + + protected Source findSource(String className, String namespaceURI, String localPart) throws CompilerException + { + if (misses.contains(className)) + { + return null; + } + + Source s = sources.get(className); + + if (s == null) + { + if ((s = findFile(className, namespaceURI, localPart)) != null) + { + return s; + } + } + + CompilationUnit u = (s != null) ? s.getCompilationUnit() : null; + + if (s != null && !s.exists()) + { + sources.remove(className); + s = null; + } + + if (adjustDefinitionName(namespaceURI, localPart, s, u)) + { + u = null; + s = null; + } + + if (s != null && ((u != null && !u.isDone()) || s.isUpdated())) + { + // s.removeCompilationUnit(); + } + else if (s != null && u != null) + { + s = s.copy(); + assert s != null; + } + + if (s == null) + { + misses.add(className); + } + + return s; + } + + protected boolean adjustDefinitionName(String namespaceURI, String localPart, Source s, CompilationUnit u) + { + // If the compilation unit does exist and the top level definition name doesn't match + // the specified class name, we don't count it as a match. + if (s != null && u != null && u.topLevelDefinitions.size() == 1) + { + if (!u.topLevelDefinitions.contains(namespaceURI, localPart)) + { + String realName = (u.topLevelDefinitions.first()).toString(); + sources.put(realName, s); + misses.remove(realName); + return true; + } + } + + return false; + } + + abstract boolean checkPreference(Source s); + + protected abstract Source findFile(String className, String namespaceURI, String localPart) throws CompilerException; + + protected File findFile(File directory, String relativePath, String[] mimeTypes) throws CompilerException + { + File found = null; + + for (int k = 0, length = mimeTypes.length; k < length; k++) + { + File f = findFile(directory, relativePath, mimeTypes[k]); + + if (f != null && found == null) + { + found = f; + // break; + } + else if (f != null) + { + throw new MoreThanOneComponentOfTheSameName(found.getAbsolutePath(), f.getAbsolutePath()); + } + } + + return found; + } + + protected File findFile(File directory, String relativePath, String mimeType) + { + String fullPath = directory.getPath() + File.separator + relativePath; + int lastSlash = fullPath.lastIndexOf(File.separator); + String dir = null; + if (lastSlash != -1) + { + dir = fullPath.substring(0, lastSlash); + if (dirs.get(dir) == NO_DIR) + { + return null; + } + } + + String path = relativePath + MimeMappings.getExtension(mimeType); + File f = FileUtil.openFile(directory, path); + + if ((f != null) && f.isFile() && FileUtil.getCanonicalPath(f).endsWith(path)) + { + return f; + } + else if (f != null && dir != null && !dirs.containsKey(dir)) + { + File p = f.getParentFile(); + dirs.put(dir, p != null && p.isDirectory() ? dir : NO_DIR); + } + + return null; + } + + String[] checkClassNameFileName(Source s) + { + String defName = null, pathName = null; + + if (s.getOwner() == this) + { + QName def = s.getCompilationUnit().topLevelDefinitions.last(); + + defName = def.getLocalPart(); + pathName = s.getShortName(); + + if (defName.equals(pathName)) + { + return null; + } + } + + return new String[] { pathName, defName }; + } + + String[] checkPackageNameDirectoryName(Source s) + { + String defPackage = null, pathPackage = null; + + if (s.getOwner() == this) + { + QName def = s.getCompilationUnit().topLevelDefinitions.last(); + + defPackage = NameFormatter.normalizePackageName(def.getNamespace()); + pathPackage = NameFormatter.toDot(s.getRelativePath(), '/'); + + if (defPackage.equals(pathPackage)) + { + return null; + } + } + + return new String[] { pathPackage, defPackage }; + } + + protected String constructRelativePath(Source s) + { + // + 1 removes the leading / + String relativePath = s.getName().substring(s.getPathRoot().getName().length() + 1); + for (int k = 0, length = mimeTypes.length; k < length; k++) + { + String ext = MimeMappings.getExtension(mimeTypes[k]); + if (relativePath.endsWith(ext)) + { + relativePath = relativePath.substring(0, relativePath.length() - ext.length()); + return relativePath; + } + } + + assert false; + return null; + } + + // used by CompilerAPI.validateCompilationUnits()... not efficient, but we rarely call it... + public void removeSource(Source s) + { + for (Iterator i = sources.entrySet().iterator(); i.hasNext(); ) + { + Map.Entry e = (Map.Entry) i.next(); + if (e.getValue() == s) + { + i.remove(); + return; + } + } + + assert false : "couldn't find " + s; + } + + public void clearCache() + { + hits.clear(); + misses.clear(); + dirs.clear(); + } + + String[] getMimeTypes() + { + return mimeTypes; + } + + public Map<String, Source> sources() + { + return sources; + } + + public String toString() + { + StringBuilder buffer = new StringBuilder("SourcePath: \n"); + Iterator<Source> iterator = sources.values().iterator(); + + while (iterator.hasNext()) + { + Source source = iterator.next(); + buffer.append("\tsource = " + source + ", cu = " + source.getCompilationUnit() + "\n"); + } + + return buffer.toString(); + } + + public void displayWarnings() + { + for (int i = 0, size = warnings.size(); i < size; i++) + { + ThreadLocalToolkit.log(warnings.get(i)); + } + } + */ + + // error messages + + public static class ClasspathOverlap extends CompilerMessage.CompilerWarning + { + private static final long serialVersionUID = -6314431057641028497L; + + public ClasspathOverlap(String path, String directory) + { + super(); + this.cpath = path; + this.directory = directory; + } + + public final String cpath, directory; + } + + public static class MoreThanOneComponentOfTheSameName extends CompilerMessage.CompilerInfo + { + private static final long serialVersionUID = 5943423934006966281L; + + public MoreThanOneComponentOfTheSameName(String file1, String file2) + { + super(); + this.file1 = file1; + this.file2 = file2; + } + + public final String file1, file2; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/SymbolTable.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/SymbolTable.java b/flex-compiler-oem/src/flex2/compiler/SymbolTable.java new file mode 100644 index 0000000..a0f330e --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/SymbolTable.java @@ -0,0 +1,60 @@ +/* + * + * 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 flex2.compiler; + +/** + * This class supports looking up information for a class or a style + * and looking up a <code>Source</code> by QName or by resource bundle + * name. + * + * @author Clement Wong + */ +public final class SymbolTable +{ + // These may look funny, but they line up with the values that ASC uses. + public static final String internalNamespace = "internal"; + public static final String privateNamespace = "private"; + public static final String protectedNamespace = "protected"; + public static final String publicNamespace = ""; + public static final String unnamedPackage = ""; + public static final String[] VISIBILITY_NAMESPACES = new String[] {SymbolTable.publicNamespace, + SymbolTable.protectedNamespace, + SymbolTable.internalNamespace, + SymbolTable.privateNamespace}; + + public static final String NOTYPE = "*"; + public static final String STRING = "String"; + public static final String BOOLEAN = "Boolean"; + public static final String NUMBER = "Number"; + public static final String INT = "int"; + public static final String UINT = "uint"; + public static final String NAMESPACE = "Namespace"; + public static final String FUNCTION = "Function"; + public static final String CLASS = "Class"; + public static final String ARRAY = "Array"; + public static final String OBJECT = "Object"; + public static final String XML = "XML"; + public static final String XML_LIST = "XMLList"; + public static final String REPARENT = "Reparent"; + public static final String REGEXP = "RegExp"; + public static final String EVENT = "flash.events:Event"; + public static final String VECTOR = "__AS3__.vec:Vector"; + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dff3a518/flex-compiler-oem/src/flex2/compiler/as3/As3Configuration.java ---------------------------------------------------------------------- diff --git a/flex-compiler-oem/src/flex2/compiler/as3/As3Configuration.java b/flex-compiler-oem/src/flex2/compiler/as3/As3Configuration.java new file mode 100644 index 0000000..eddad63 --- /dev/null +++ b/flex-compiler-oem/src/flex2/compiler/as3/As3Configuration.java @@ -0,0 +1,166 @@ +/* + * + * 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 flex2.compiler.as3; + +import macromedia.asc.embedding.ConfigVar; +import macromedia.asc.util.ObjectList; + +/** + * This interface is used to restrict consumers of + * CompilerConfiguration to as3 compiler specific options. + * + * @author Clement Wong + * @see flex2.compiler.common.CompilerConfiguration + */ +public interface As3Configuration +{ + /** + * Omit method arg names. + */ + boolean optimize(); + + /** + * Emit system paths with debug info. + */ + boolean verboseStacktraces(); + + /** + * Generate SWFs for debugging + */ + boolean debug(); + + int dialect(); + boolean adjustOpDebugLine(); + + /** + * Run the AS3 compiler in strict mode + */ + boolean strict(); + + /** + * Enable asc -warnings + */ + boolean warnings(); + + /** + * Generate asdoc + */ + boolean doc(); + + /** + * user-defined AS3 file encoding + */ + String getEncoding(); + + /** + * Configuration settings (ConfigVars) from <code>--compiler.define</code> + * are retrieved using this getter. + * + * @return ObjectList<macromedia.asc.embedding.ConfigVar> + */ + ObjectList<ConfigVar> getDefine(); + + boolean getGenerateAbstractSyntaxTree(); + + /** + * Whether to export metadata into ABCs + */ + public boolean metadataExport(); + + public boolean showDeprecationWarnings(); + + // coach warnings + + public boolean warn_array_tostring_changes(); + + public boolean warn_assignment_within_conditional(); + + public boolean warn_bad_array_cast(); + + public boolean warn_bad_bool_assignment(); + + public boolean warn_bad_date_cast(); + + public boolean warn_bad_es3_type_method(); + + public boolean warn_bad_es3_type_prop(); + + public boolean warn_bad_nan_comparison(); + + public boolean warn_bad_null_assignment(); + + public boolean warn_bad_null_comparison(); + + public boolean warn_bad_undefined_comparison(); + + public boolean warn_boolean_constructor_with_no_args(); + + public boolean warn_changes_in_resolve(); + + public boolean warn_class_is_sealed(); + + public boolean warn_const_not_initialized(); + + public boolean warn_constructor_returns_value(); + + public boolean warn_deprecated_event_handler_error(); + + public boolean warn_deprecated_function_error(); + + public boolean warn_deprecated_property_error(); + + public boolean warn_duplicate_argument_names(); + + public boolean warn_duplicate_variable_def(); + + public boolean warn_for_var_in_changes(); + + public boolean warn_import_hides_class(); + + public boolean warn_instance_of_changes(); + + public boolean warn_internal_error(); + + public boolean warn_level_not_supported(); + + public boolean warn_missing_namespace_decl(); + + public boolean warn_negative_uint_literal(); + + public boolean warn_no_constructor(); + + public boolean warn_no_explicit_super_call_in_constructor(); + + public boolean warn_no_type_decl(); + + public boolean warn_number_from_string_changes(); + + public boolean warn_scoping_change_in_this(); + + public boolean warn_slow_text_field_addition(); + + public boolean warn_unlikely_function_value(); + + public boolean warn_xml_class_has_changed(); + + public boolean keepEmbedMetadata(); + + public boolean getAdvancedTelemetry(); +}