blob: 4eabe129f2d23b348a03586bce4e2e25ea97b541 [file] [log] [blame]
/*
*
* 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.MxmlConfiguration;
import flex2.compiler.common.PathResolver;
import flex2.compiler.common.SinglePathResolver;
import flex2.compiler.io.InMemoryFile;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.swc.SwcScript;
import flex2.compiler.util.LineNumberMap;
import flex2.compiler.util.LocalLogger;
import flex2.compiler.util.MimeMappings;
import flex2.compiler.util.MultiName;
import flex2.compiler.util.QName;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.tools.oem.ApplicationCache;
import macromedia.asc.semantics.TypeValue;
import macromedia.asc.util.Context;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;
/**
* 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.
*/
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;
// 'resolver' doesn't need persistence because it's constructed from pathRoot.
private PathResolver resolver;
private String relativePath, shortName;
private Object owner;
private boolean isInternal;
private boolean isRoot;
private boolean isDebuggable;
private boolean isPreprocessed;
private CompilationUnit unit;
private long fileTime;
private Map<VirtualFile, Long> fileIncludeTimes;
// 1. path resolution
// 2. backing file
// 3. source fragments
private Source delegate;
/**
* This is a per-Source/CompilationUnit logger. The
* ThreadLocalToolkit logger is a per-compile logger. This logger
* is usually wired to the ThreadLocalToolkit logger. During the
* life of a Source, this logger be nulled out, when it's no
* longer needed to save memory. If the Source is reused again, a
* new LocalLogger is created by CompilerAPI.preprocess().
*/
private LocalLogger logger;
private Map<String, Object> fragments;
private Map<String, LineNumberMap> fragmentLineMaps;
private AssetInfo assetInfo;
public int lineCount;
private int reuseCount = 0;
private int totalDependentCount;
public CompilationUnit newCompilationUnit(Object syntaxTree, CompilerContext context)
{
unit = new CompilationUnit(this, syntaxTree, context);
unit.setStandardDefs(ThreadLocalToolkit.getStandardDefs());
return unit;
}
public CompilationUnit getCompilationUnit()
{
return unit;
}
void removeCompilationUnit()
{
// CompilationUnit's created from SwcScript's can't be easily
// recreated, so just remove the type information. The
// alternative is to factor out the CompilationUnit creation
// from CompilerSwcContext.createSource() and modify
// AbcCompiler.parse1() to call it when the CompilationUnit is
// null.
if (isSwcScriptOwner())
{
unit.removeTypeInfo();
}
else
{
unit = null;
}
fileTime = file.getLastModified();
logger = null;
isPreprocessed = false;
fileIncludeTimes.clear();
delegate = null;
resolver = null;
if (fragments != null)
{
fragments.clear();
fragmentLineMaps.clear();
}
}
public void setAssetInfo(AssetInfo assetInfo)
{
this.assetInfo = assetInfo;
}
void setPreprocessed()
{
isPreprocessed = true;
}
boolean isPreprocessed()
{
return isPreprocessed;
}
void setLogger(LocalLogger logger)
{
this.logger = logger;
}
public LocalLogger getLogger()
{
return logger;
}
public void disconnectLogger()
{
if (logger != null && logger.warningCount() == 0 && logger.errorCount() == 0)
{
logger = null;
}
else if (logger != null)
{
// if warning/error exists, keep the logger and just disconnect it from the original logger.
logger.disconnect();
}
}
boolean hasError()
{
return logger != null && logger.errorCount() > 0;
}
public Object getOwner()
{
return owner;
}
// C: do not make this public; only used by ResourceContainer.
void setOwner(Object owner)
{
this.owner = owner;
}
public boolean isSourcePathOwner()
{
return owner != null && owner instanceof SourcePath && !isResourceBundlePathOwner();
}
public boolean isSourceListOwner()
{
return owner != null && owner instanceof SourceList;
}
public boolean isFileSpecOwner()
{
return owner != null && owner instanceof FileSpec;
}
public boolean isCompilerSwcContextOwner()
{
return owner != null && owner instanceof CompilerSwcContext;
}
public boolean isSwcScriptOwner()
{
return owner != null && owner instanceof SwcScript;
}
public boolean isResourceContainerOwner()
{
return owner != null && owner instanceof ResourceContainer;
}
public boolean isResourceBundlePathOwner()
{
return owner != null && owner instanceof ResourceBundlePath;
}
public boolean isInternal()
{
return isInternal;
}
public boolean isEntryPoint()
{
return isFileSpecOwner();
}
public boolean isRoot()
{
return isRoot;
}
public boolean isDebuggable()
{
return isDebuggable;
}
public boolean isCompiled()
{
return unit != null && unit.isBytecodeAvailable();
}
public boolean isUpdated()
{
long lastModified = file.getLastModified();
if (lastModified != fileTime)
{
return true;
}
else
{
for (Entry<VirtualFile, Long> entry : fileIncludeTimes.entrySet())
{
if (entry.getKey().getLastModified() != entry.getValue().longValue())
{
return true;
}
}
return false;
}
}
boolean isUpdated(Source source)
{
boolean result = false;
if (assetInfo != null)
{
if (assetInfo.getArgs().size() != source.assetInfo.getArgs().size())
{
result = true;
}
else
{
for (Iterator i = assetInfo.getArgs().entrySet().iterator(); i.hasNext() && !result;)
{
Entry entry = (Entry) i.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (!value.equals(Transcoder.COLUMN) &&
!value.equals(Transcoder.LINE) &&
!value.equals(source.assetInfo.getArgs().get(key)))
{
result = true;
}
}
}
}
return result;
}
public boolean exists()
{
return file.getLastModified() > 0;
}
public String getName()
{
return file.getName();
}
public String getNameForReporting()
{
return file.getNameForReporting();
}
// C: This is temporary... only use it when you need to set asc Context.setPath
public String getParent()
{
return file.getParent();
}
public long size()
{
return file.size();
}
public InputStream getInputStream() throws IOException
{
return file.getInputStream();
}
public byte[] toByteArray() throws IOException
{
return file.toByteArray();
}
public boolean isTextBased()
{
return file.isTextBased();
}
public String getInputText()
{
return file.toString();
}
public String getMimeType()
{
return file.getMimeType();
}
public long getLastModified()
{
return fileTime;
}
public VirtualFile resolve(String include)
{
return getPathResolver().resolve(include);
}
public PathResolver getPathResolver()
{
if (resolver == null)
{
resolver = new PathResolver();
resolver.addSinglePathResolver(new Resolver(delegate != null ? delegate.getPathResolver() : null, file, pathRoot));
resolver.addSinglePathResolver(ThreadLocalToolkit.getPathResolver());
}
return resolver;
}
static class Resolver implements SinglePathResolver
{
Resolver(PathResolver delegate, VirtualFile file, VirtualFile pathRoot)
{
this.delegate = delegate;
this.file = file;
this.pathRoot = pathRoot;
}
private PathResolver delegate;
private VirtualFile file, pathRoot;
public VirtualFile resolve(String relative)
{
VirtualFile f = null;
if (relative != null)
{
// delegate.resolve() before this.resolve()
if (delegate != null)
{
f = delegate.resolve(relative);
}
else
{
// A leading slash harks back to the Servlet days
// and meant look in the context root, so if we
// see a leading slash, we skip looking relative
// to the file.
if (!relative.startsWith("/"))
{
f = file.resolve(relative);
}
if ((f == null) && (pathRoot != null))
{
// See above note about about a leading slash.
// We used to blindly chop off the leading
// character and many existing apps are now
// dependent on the broken behavior. See the
// performance testsuite for examples.
if (relative.startsWith("/") ||
(ThreadLocalToolkit.getCompatibilityVersion() < MxmlConfiguration.VERSION_4_5))
{
f = pathRoot.resolve(relative.substring(1));
}
}
}
}
return f;
}
}
public void setPathResolver(PathResolver pathResolver)
{
this.resolver = pathResolver;
}
public VirtualFile getBackingFile()
{
return (delegate == null)? file : delegate.getBackingFile();
}
public String getRelativePath()
{
// C: should be /-separated (no backslash)
return relativePath;
}
public String getShortName()
{
return shortName;
}
public VirtualFile getPathRoot()
{
return pathRoot;
}
public void addFileIncludes(Source s)
{
fileIncludeTimes.putAll(s.fileIncludeTimes);
}
public boolean addFileInclude(String path)
{
VirtualFile f = resolve(path);
return addFileInclude(f);
}
public boolean addFileInclude(VirtualFile f)
{
if (f != null)
{
if (!fileIncludeTimes.containsKey(f))
{
fileIncludeTimes.put(f, f.getLastModified());
}
if (delegate != null)
{
delegate.addFileInclude(f);
}
return true;
}
else
{
return false;
}
}
public Iterator<VirtualFile> getFileIncludes()
{
return fileIncludeTimes.keySet().iterator();
}
/**
* Returns a copy.
*/
public Set<VirtualFile> getFileIncludesSet()
{
return new HashSet<VirtualFile>(fileIncludeTimes.keySet());
}
/**
* Returns a copy.
*/
public Map<VirtualFile, Long> getFileIncludeTimes()
{
return new HashMap<VirtualFile, Long>(fileIncludeTimes);
}
public boolean isIncludedFile(String name)
{
for (VirtualFile f : fileIncludeTimes.keySet())
{
if (f.getName().equals(name) || f.getNameForReporting().equals(name))
{
return true;
}
}
return false;
}
public Iterator<VirtualFile> getUpdatedFileIncludes()
{
List<VirtualFile> updated = null;
for (VirtualFile f : fileIncludeTimes.keySet())
{
long ts = fileIncludeTimes.get(f).longValue();
if (f.getLastModified() != ts)
{
if (updated == null)
{
updated = new ArrayList<VirtualFile>(fileIncludeTimes.size());
}
updated.add(f);
}
}
return updated == null ? null : updated.iterator();
}
public int getFileIncludeSize()
{
return fileIncludeTimes.size();
}
long getFileIncludeTime(VirtualFile f)
{
return fileIncludeTimes.get(f).longValue();
}
public long getFileTime()
{
return fileTime;
}
public void setFileTime(long fileTime)
{
this.fileTime = fileTime;
}
public void addSourceFragment(String n, Object f, LineNumberMap m)
{
if (fragments == null)
{
fragments = new HashMap<String, Object>();
fragmentLineMaps = new HashMap<String, LineNumberMap>();
}
fragments.put(n, f);
if (m != null)
{
fragmentLineMaps.put(n, m);
}
}
public Object getSourceFragment(String n)
{
// this.fragment before delegate.fragment
Object obj = (fragments == null) ? null : fragments.get(n);
if (obj == null && delegate != null)
{
return delegate.getSourceFragment(n);
}
else
{
return obj;
}
}
public Collection<LineNumberMap> getSourceFragmentLineMaps()
{
if (fragmentLineMaps != null)
{
return fragmentLineMaps.values();
}
else if (delegate != null)
{
return delegate.getSourceFragmentLineMaps();
}
else
{
return null;
}
}
void clearSourceFragments()
{
fragments = null;
fragmentLineMaps = null;
if (delegate != null)
{
delegate.clearSourceFragments();
}
}
/**
* Used by the web tier for dependency tracking.
*
* returns the last modified time of the source file itself
* without taking last modified time of any dependent files into account
*
* does not return a last modified time for in-memory files
*/
public long getRawLastModified()
{
if (isSwcScriptOwner())
{
return ((SwcScript) owner).getLibrary().getSwcCreationTime();
}
else if (isFileSpecOwner() || isSourceListOwner() || isSourcePathOwner())
{
return fileTime;
}
else // if (isResourceBundlePathOwner() || isResourceContainerOwner())
{
return -1;
}
}
/**
* Used by the web tier for dependency tracking.
*/
public String getRawLocation()
{
if (isSwcScriptOwner())
{
return ((SwcScript) owner).getLibrary().getSwcLocation();
}
else
{
return getName();
}
}
public int compareTo(Source source)
{
return getName().compareTo(source.getName());
}
public int hashCode()
{
return getName().hashCode();
}
public boolean equals(Object object)
{
if (object instanceof Source)
{
Source s = (Source) object;
return s.owner == owner && s.getName().equals(getName()) && s.getRelativePath().equals(getRelativePath());
}
else
{
return false;
}
}
public void close()
{
file.close();
}
/**
* Make a copy of this Source object. Dependencies are multinames in the clone.
*/
public Source copy()
{
if (unit != null && unit.isDone())
{
// copying Source
VirtualFile f = new InMemoryFile(unit.getByteCodes(), getName(), MimeMappings.ABC, fileTime);
Source s = new Source(f, pathRoot, relativePath, shortName, owner, isInternal, isRoot, isDebuggable);
s.fileIncludeTimes.putAll(fileIncludeTimes);
s.logger = logger;
// copying CompilationUnit
CompilationUnit u = s.newCompilationUnit(null, new CompilerContext());
copyCompilationUnit(unit, u, true);
return s;
}
else
{
return null;
}
}
/**
* This method copies all the guts of one CompilationUnit into
* another. It was formerly called copyMetaData(), but it grew to
* include more than just metadata, so it was renamed.
*/
public static void copyCompilationUnit(CompilationUnit fromUnit, CompilationUnit toUnit,
boolean useHistories)
{
toUnit.topLevelDefinitions.addAll(fromUnit.topLevelDefinitions);
if (useHistories)
{
// For non-SwcScript based CompilationUnit's we want to
// copy all the MultiName dependencies from the old
// CompilationUnit's history into the new CompilationUnit,
// so they can be resolved again. This covers the case
// where an ambiguity was introduced between incremental
// compiles.
toUnit.inheritance.addAll(fromUnit.inheritanceHistory.keySet());
toUnit.types.addAll(fromUnit.typeHistory.keySet());
toUnit.namespaces.addAll(fromUnit.namespaceHistory.keySet());
toUnit.expressions.addAll(fromUnit.expressionHistory.keySet());
}
else
{
// CompilationUnit's from SwcScript's get there
// dependencies from the catalog.xml file, so we copy them
// directly to the new CompilationUnit.
toUnit.inheritance.addAll(fromUnit.inheritance);
toUnit.types.addAll(fromUnit.types);
toUnit.namespaces.addAll(fromUnit.namespaces);
toUnit.expressions.addAll(fromUnit.expressions);
}
toUnit.inheritanceHistory = fromUnit.inheritanceHistory;
toUnit.typeHistory = fromUnit.typeHistory;
toUnit.namespaceHistory = fromUnit.namespaceHistory;
toUnit.expressionHistory = fromUnit.expressionHistory;
toUnit.setSignatureChecksum(fromUnit.getSignatureChecksum());
if (fromUnit.hasAssets())
{
toUnit.getAssets().addAll(fromUnit.getAssets());
}
toUnit.auxGenerateInfo = fromUnit.auxGenerateInfo;
// These values are not type info dependent, so always copy them over.
toUnit.icon = fromUnit.icon;
toUnit.iconFile = fromUnit.iconFile;
if (fromUnit.hasTypeInfo)
{
// There is no need to persist these properties because they exists as AS3 metadata in abc[], which
// PersistenceStore always persists.
toUnit.styles = fromUnit.styles;
toUnit.typeInfo = fromUnit.typeInfo;
toUnit.hasTypeInfo = true;
toUnit.classTable.putAll(fromUnit.classTable);
toUnit.swfMetaData = fromUnit.swfMetaData;
toUnit.loaderClass = fromUnit.loaderClass;
toUnit.loaderClassBase = fromUnit.loaderClassBase;
toUnit.extraClasses.addAll(fromUnit.extraClasses);
toUnit.addAccessibilityClasses(fromUnit);
toUnit.licensedClassReqs.putAll(fromUnit.licensedClassReqs);
toUnit.remoteClassAliases.putAll(fromUnit.remoteClassAliases);
toUnit.effectTriggers.putAll(fromUnit.effectTriggers);
toUnit.mixins.addAll(fromUnit.mixins);
toUnit.resourceBundleHistory.addAll(fromUnit.resourceBundleHistory);
toUnit.bytes = fromUnit.bytes;
}
}
/**
* Creates a Source object, given a VirtualFile
*/
static Source newSource(VirtualFile f, long fileTime, VirtualFile pathRoot, String relativePath, String shortName, Object owner,
boolean isInternal, boolean isRoot, boolean isDebuggable, Set<VirtualFile> includes, Map<VirtualFile, Long> includeTimes,
LocalLogger logger)
{
Source s = new Source(f, pathRoot, relativePath, shortName, owner, isInternal, isRoot, isDebuggable);
s.fileTime = fileTime;
s.fileIncludeTimes.putAll(includeTimes);
s.logger = logger;
return s;
}
/**
* Creates a Source object, given an abc[]
*/
static Source newSource(byte[] abc, String name, long fileTime, VirtualFile pathRoot, String relativePath, String shortName, Object owner,
boolean isInternal, boolean isRoot, boolean isDebuggable, Set<VirtualFile> includes, Map<VirtualFile, Long> includeTimes,
LocalLogger logger)
{
VirtualFile f = new InMemoryFile(abc, name, MimeMappings.ABC, fileTime);
return newSource(f, fileTime, pathRoot, relativePath, shortName, owner, isInternal, isRoot, isDebuggable,
includes, includeTimes, logger);
}
/**
* Populates a Source object.
*/
static Source populateSource(Source s, long fileTime, VirtualFile pathRoot, String relativePath, String shortName, Object owner,
boolean isInternal, boolean isRoot, boolean isDebuggable, Set<VirtualFile> includes, Map<VirtualFile, Long> includeTimes,
LocalLogger logger)
{
assert s != null;
s.fileTime = fileTime;
s.pathRoot = pathRoot;
s.relativePath = relativePath;
s.shortName = shortName;
s.owner = owner;
s.isInternal = isInternal;
s.isRoot = isRoot;
s.isDebuggable = isDebuggable;
s.fileIncludeTimes.putAll(includeTimes);
s.logger = logger;
return s;
}
public void reused()
{
reuseCount++;
}
public int getReuseCount()
{
return reuseCount;
}
public int getTotalDependentCount()
{
return totalDependentCount;
}
public void setTotalDependentCount(int totalDependentCount)
{
this.totalDependentCount = totalDependentCount;
}
public String toString()
{
return getName();
}
public static void transferDefinitions(CompilationUnit from, CompilationUnit to)
{
to.topLevelDefinitions.addAll(from.topLevelDefinitions);
}
public static void transferTypeInfo(CompilationUnit from, CompilationUnit to)
{
to.typeInfo = from.typeInfo;
}
public static void clearDependencies(CompilationUnit unit)
{
unit.inheritance.clear();
unit.types.clear();
unit.expressions.clear();
unit.namespaces.clear();
unit.importPackageStatements.clear();
unit.importDefinitionStatements.clear();
}
public static void transferInheritance(CompilationUnit from, CompilationUnit to)
{
to.inheritance.clear();
to.inheritance.addAll(from.inheritance);
to.inheritanceHistory.putAll(from.inheritanceHistory);
}
public static void transferDependencies(CompilationUnit from, CompilationUnit to)
{
clearDependencies(to);
to.inheritance.addAll(from.inheritance);
to.types.addAll(from.types);
to.expressions.addAll(from.expressions);
to.namespaces.addAll(from.namespaces);
to.importPackageStatements.addAll(from.importPackageStatements);
to.importDefinitionStatements.addAll(from.importDefinitionStatements);
to.inheritanceHistory.putAll(from.inheritanceHistory);
to.typeHistory.putAll(from.typeHistory);
to.expressionHistory.putAll(from.expressionHistory);
to.namespaceHistory.putAll(from.namespaceHistory);
}
public static void transferNamespaces(CompilationUnit from, CompilationUnit to)
{
to.namespaces.clear();
to.namespaces.addAll(from.namespaces);
to.namespaceHistory.putAll(from.namespaceHistory);
}
public static void transferExpressions(CompilationUnit from, CompilationUnit to)
{
to.expressions.clear();
to.expressions.addAll(from.expressions);
to.expressionHistory.putAll(from.expressionHistory);
}
public static void transferAssets(CompilationUnit from, CompilationUnit to)
{
if (from.hasAssets())
{
to.getAssets().addAll(from.getAssets());
}
}
public static void transferMetaData(CompilationUnit from, CompilationUnit to)
{
to.metadata.addAll(from.metadata);
to.swfMetaData = from.swfMetaData;
to.icon = from.icon;
to.iconFile = from.iconFile;
to.loaderClass = from.loaderClass;
to.extraClasses.addAll( from.extraClasses );
to.addAccessibilityClasses(from);
to.licensedClassReqs.putAll( from.licensedClassReqs );
to.remoteClassAliases.putAll(from.remoteClassAliases);
to.effectTriggers.putAll(from.effectTriggers);
to.mixins.addAll(from.mixins);
to.resourceBundles.addAll(from.resourceBundles);
to.resourceBundleHistory.addAll(from.resourceBundleHistory);
to.setSignatureChecksum(from.getSignatureChecksum());
}
public static void transferGeneratedSources(CompilationUnit from, CompilationUnit to)
{
to.addGeneratedSources(from.getGeneratedSources());
from.clearGeneratedSources();
}
public static void transferClassTable(CompilationUnit from, CompilationUnit to)
{
to.classTable.putAll(from.classTable);
}
public static void transferLoaderClassBase(CompilationUnit from, CompilationUnit to)
{
to.loaderClassBase = from.loaderClassBase;
}
public static void transferBytecodes(CompilationUnit from, CompilationUnit to)
{
to.bytes.clear();
to.bytes.set(from.bytes.toByteArray(false), from.bytes.size());
to.getSource().lineCount = from.getSource().lineCount;
}
public static void transferStyles(CompilationUnit from, CompilationUnit to)
{
to.styles = from.styles;
}
}