diff --git a/src/Core/Build/Tasks/ScriptCompilerTask.cs b/src/Core/Build/Tasks/ScriptCompilerTask.cs index ae7634a09..208044eba 100644 --- a/src/Core/Build/Tasks/ScriptCompilerTask.cs +++ b/src/Core/Build/Tasks/ScriptCompilerTask.cs @@ -244,8 +244,13 @@ private CompilerOptions CreateOptions(IEnumerable sourceItems, IEnume options.IncludeResolver = this; string scriptFilePath = GetScriptFilePath(locale, minimize, includeTests); + string symbolFilePath = GetSymbolFilePath(); + outputScriptItem = new TaskItem(scriptFilePath); + TaskItem outputSymbolItem = new TaskItem(symbolFilePath); + options.ScriptFile = new TaskItemOutputStreamSource(outputScriptItem); + options.SymbolFile = new TaskItemOutputStreamSource(outputSymbolItem); return options; } @@ -307,6 +312,7 @@ private void GenerateDeploymentFile() { try { string assemblyFile = Path.GetFileName(_assembly.ItemSpec); string scriptsFilePath = Path.Combine(OutputPath, Path.ChangeExtension(assemblyFile, "scripts")); + string symbolFilePath = Path.Combine(OutputPath, Path.ChangeExtension(assemblyFile, "symbol")); Uri scriptsUri = new Uri(Path.GetFullPath(scriptsFilePath), UriKind.Absolute); IEnumerable scripts = @@ -407,6 +413,16 @@ private string GetScriptFilePath(string locale, bool minimize, bool includeTests return Path.GetFullPath(Path.Combine(OutputPath, Path.ChangeExtension(scriptName, extension))); } + private string GetSymbolFilePath() { + + string scriptName = Path.GetFileName(_assembly.ItemSpec); + if (Directory.Exists(OutputPath) == false) { + Directory.CreateDirectory(OutputPath); + } + string extension = "symbol"; + return Path.GetFullPath(Path.Combine(OutputPath, Path.ChangeExtension(scriptName, extension))); + } + private ICollection GetSources(IEnumerable sourceItems) { if (sourceItems == null) { return new TaskItemInputStreamSource[0]; @@ -428,13 +444,37 @@ private ICollection GetSources(IEnumerable sourceItems return sources; } + public enum FileTypeEnum { + Normal, + Minimized, + Symbol + } + + public string GetExtension(FileTypeEnum fileType) { + switch (fileType) { + case FileTypeEnum.Minimized: + return ".min.js"; + + case FileTypeEnum.Symbol: + return ".symbol"; + + case FileTypeEnum.Normal: + default: + return ".js"; + } + } + + private void OnScriptFileGenerated(ITaskItem scriptItem, CompilerOptions options, bool copyReferences) { - Func getScriptFile = delegate(string reference, bool minimized) { - string scriptFile = Path.ChangeExtension(reference, minimized ? ".min.js" : ".js"); + + Func getScriptFile = delegate(string reference, FileTypeEnum fileType) + { + var extension = GetExtension(fileType); + string scriptFile = Path.ChangeExtension(reference, extension); string fileName = Path.GetFileNameWithoutExtension(scriptFile); if (fileName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)) { - fileName = (minimized ? "ss.min" : "ss") + Path.GetExtension(scriptFile); + fileName = (fileType == FileTypeEnum.Minimized ? "ss.min" : "ss") + Path.GetExtension(scriptFile); scriptFile = Path.Combine(Path.GetDirectoryName(scriptFile), fileName); } @@ -491,17 +531,23 @@ private void OnScriptFileGenerated(ITaskItem scriptItem, CompilerOptions options if (copyReferences) { foreach (string reference in options.References) { - string scriptFile = getScriptFile(reference, /* minimized */ false); + string scriptFile = getScriptFile(reference, FileTypeEnum.Normal); if (scriptFile != null) { string path = Path.Combine(scriptFolder, CopyReferencesPath, Path.GetFileName(scriptFile)); safeCopyFile(scriptFile, path); } - string minScriptFile = getScriptFile(reference, /* minimized */ true); + string minScriptFile = getScriptFile(reference, FileTypeEnum.Minimized); if (minScriptFile != null) { string path = Path.Combine(scriptFolder, CopyReferencesPath, Path.GetFileName(minScriptFile)); safeCopyFile(minScriptFile, path); } + + string symbolFile = getScriptFile(reference, FileTypeEnum.Symbol); + if (symbolFile != null) { + string path = Path.Combine(scriptFolder, CopyReferencesPath, Path.GetFileName(symbolFile)); + safeCopyFile(symbolFile, path); + } } } @@ -570,5 +616,7 @@ public TaskItemOutputStreamSource(ITaskItem taskItem, string name) : base(taskItem.ItemSpec, name) { } } + + } } diff --git a/src/Core/Compiler/Compiler.csproj b/src/Core/Compiler/Compiler.csproj index 70475588b..617ecee78 100644 --- a/src/Core/Compiler/Compiler.csproj +++ b/src/Core/Compiler/Compiler.csproj @@ -50,6 +50,9 @@ ResXParser.cs + + + @@ -178,6 +181,7 @@ + diff --git a/src/Core/Compiler/Compiler/MetadataBuilder.cs b/src/Core/Compiler/Compiler/MetadataBuilder.cs index d846598f0..fe7d627db 100644 --- a/src/Core/Compiler/Compiler/MetadataBuilder.cs +++ b/src/Core/Compiler/Compiler/MetadataBuilder.cs @@ -829,6 +829,7 @@ private void BuildType(TypeSymbol typeSymbol, UserTypeNode typeNode) { if (AttributeNode.FindAttribute(attributes, "ScriptImport") != null) { ScriptReference dependency = null; + typeSymbol.SetScriptImported(); AttributeNode dependencyAttribute = AttributeNode.FindAttribute(attributes, "ScriptDependency"); if (dependencyAttribute != null) { diff --git a/src/Core/Compiler/CompilerOptions.cs b/src/Core/Compiler/CompilerOptions.cs index 382301d7c..447cdbbff 100644 --- a/src/Core/Compiler/CompilerOptions.cs +++ b/src/Core/Compiler/CompilerOptions.cs @@ -21,6 +21,7 @@ public sealed class CompilerOptions { private ICollection _sources; private ICollection _resources; private IStreamSource _scriptFile; + private IStreamSource _symbolFile; private IStreamSource _docCommentFile; private IStreamSourceResolver _includeResolver; private bool _includeTests; @@ -148,6 +149,15 @@ public IStreamSource ScriptFile { } } + public IStreamSource SymbolFile { + get { + return _symbolFile; + } + set { + _symbolFile = value; + } + } + public ICollection Sources { get { return _sources; diff --git a/src/Core/Compiler/Generator/ExpressionGenerator.cs b/src/Core/Compiler/Generator/ExpressionGenerator.cs index 796d4e430..8bb906043 100644 --- a/src/Core/Compiler/Generator/ExpressionGenerator.cs +++ b/src/Core/Compiler/Generator/ExpressionGenerator.cs @@ -266,9 +266,11 @@ private static void GenerateDelegateExpression(ScriptGenerator generator, Member } } else { - writer.Write("ss.bind('"); + writer.Write("ss.bind("); + ExpressionGenerator.GenerateExpression(generator, symbol, expression.ObjectReference); + writer.Write("."); writer.Write(expression.Method.GeneratedName); - writer.Write("', "); + writer.Write(", "); ExpressionGenerator.GenerateExpression(generator, symbol, expression.ObjectReference); writer.Write(")"); } diff --git a/src/Core/Compiler/ScriptCompiler.cs b/src/Core/Compiler/ScriptCompiler.cs index 50045e229..bb9189e04 100644 --- a/src/Core/Compiler/ScriptCompiler.cs +++ b/src/Core/Compiler/ScriptCompiler.cs @@ -17,6 +17,7 @@ using ScriptSharp.ResourceModel; using ScriptSharp.ScriptModel; using ScriptSharp.Validator; +using ScriptSharp.SymbolFile; namespace ScriptSharp { @@ -223,9 +224,47 @@ public bool Compile(CompilerOptions options) { return false; } + GenerateSymbol(); + if (_hasErrors) { + return false; + } + return true; } + private void GenerateSymbol() { + + Stream outputStream = null; + TextWriter outputWriter = null; + + try { + outputStream = _options.SymbolFile.GetStream(); + if (outputStream == null) { + ((IErrorHandler)this).ReportError("Unable to write to file " + _options.SymbolFile.FullName, + _options.SymbolFile.FullName); + return; + } + + outputWriter = new StreamWriter(outputStream); + + var sfg = new SymbolFileGenerator(outputWriter); + sfg.Generate(_symbols); + + } catch (Exception e) { + Debug.Fail(e.ToString()); + } finally { + if (outputWriter != null) { + outputWriter.Flush(); + } + if (outputStream != null) { + _options.SymbolFile.CloseStream(outputStream); + } + } + + + + } + private void GenerateScript() { Stream outputStream = null; TextWriter outputWriter = null; @@ -243,9 +282,11 @@ private void GenerateScript() { #if DEBUG if (_options.InternalTestMode) { if (_testOutput != null) { + outputWriter.WriteLine("/**"); outputWriter.Write(_testOutput); outputWriter.WriteLine("Script"); outputWriter.WriteLine("================================================================"); + outputWriter.Write("**/"); outputWriter.WriteLine(); outputWriter.WriteLine(); } diff --git a/src/Core/Compiler/ScriptModel/Symbols/TypeSymbol.cs b/src/Core/Compiler/ScriptModel/Symbols/TypeSymbol.cs index 5a42280cf..899d731f0 100644 --- a/src/Core/Compiler/ScriptModel/Symbols/TypeSymbol.cs +++ b/src/Core/Compiler/ScriptModel/Symbols/TypeSymbol.cs @@ -33,6 +33,7 @@ internal abstract class TypeSymbol : Symbol, ISymbolTable { private bool _ignoreNamespace; private string _scriptNamespace; private bool _testType; + private bool _scriptImported; protected TypeSymbol(SymbolType type, string name, NamespaceSymbol parent) : base(type, name, parent) { @@ -195,6 +196,12 @@ public string ScriptNamespace { } } + public bool IsScriptImported { + get { + return _scriptImported; + } + } + public virtual void AddMember(MemberSymbol memberSymbol) { Debug.Assert(memberSymbol != null); Debug.Assert(String.IsNullOrEmpty(memberSymbol.Name) == false); @@ -294,6 +301,10 @@ public void SetTestType() { _testType = true; } + internal void SetScriptImported() { + _scriptImported = true; + } + #region ISymbolTable Members ICollection ISymbolTable.Symbols { get { @@ -337,5 +348,6 @@ Symbol ISymbolTable.FindSymbol(string name, Symbol context, SymbolFilter filter) return symbol; } #endregion + } } diff --git a/src/Core/Compiler/SymbolFile/AjaxMinRenameFileGenerator.cs b/src/Core/Compiler/SymbolFile/AjaxMinRenameFileGenerator.cs new file mode 100644 index 000000000..4ed2aac55 --- /dev/null +++ b/src/Core/Compiler/SymbolFile/AjaxMinRenameFileGenerator.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using System.IO; + +namespace ScriptSharp.SymbolFile { + public class AjaxMinRenameFileGenerator { + + internal const string RootElement = "root"; + internal const string RenameElement = "rename"; + internal const string NorenameElement = "norename"; + internal const string IdAttribute = "id"; + internal const string FromAttribute = "from"; + internal const string ToAttribute = "to"; + + /// + /// Generate an AjaxMin rename file, based on Exported Symbols + /// + /// Merged symbol file + /// AjaxMin rename file + public void Generate(string symbol, string rename) { + + string renames = @"//Symbol[@GeneratedName][ancestor::Symbol[@HasApplicationTypes='True']]"; + string norenames = @"//Symbol[@GeneratedName][ancestor::Symbol[@HasApplicationTypes='False']] + | //Symbol[@GeneratedName][ancestor::Symbol[@IsScriptImported='True']] + | //Symbol[@GeneratedName][@IsScriptImported='True'] + "; + + var xmsf = new XmlDocument(); + xmsf.Load(symbol); + + var renameNodes = xmsf.SelectNodes(renames); + var norenameNodes = xmsf.SelectNodes(norenames); + + HashSet norenameHash = new HashSet(); + foreach (XmlNode node in norenameNodes) { + string name = GetAttribute(node, SymbolFile.GeneratedNameAttribute); + norenameHash.Add(name); + + // $.bbq.getstate get expanded as getstate + // otherwise ajaxmin will it + var names = name.Split(new[] { '.' }); + string trailing = names[names.Length - 1]; + norenameHash.Add(trailing); + } + + HashSet renameHash = new HashSet(); + foreach (XmlNode node in renameNodes) { + string name = GetAttribute(node, SymbolFile.GeneratedNameAttribute); + if (norenameHash.Contains(name)) { + continue; + } + renameHash.Add(name); + } + + GenerateFile(rename, norenameHash, renameHash); + + } + + private void GenerateFile(string rename, HashSet norenameHash, HashSet renameHash) { + + using (XmlTextWriter writer = new XmlTextWriter(rename, Encoding.UTF8)) { + + writer.WriteStartDocument(); + writer.WriteStartElement(RootElement); + + var seq = Generate(renameHash.Count); + var random = RandomPermutation(seq).ToArray(); + + int i = 0; + foreach (string ren in renameHash) { + writer.WriteStartElement(RenameElement); + writer.WriteAttributeString(FromAttribute, ren); + writer.WriteAttributeString(ToAttribute, random[i++]); + writer.WriteEndElement(); + } + + foreach (string ren in norenameHash) { + writer.WriteStartElement(NorenameElement); + writer.WriteAttributeString(IdAttribute, ren); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + writer.WriteEndDocument(); + + writer.Flush(); + writer.Close(); + + } + + } + + public static IEnumerable Generate(int length) { + for (int i = 0; i < length; i++) { + yield return "x" + i; + } + } + + static Random random = new Random(); + public static IEnumerable RandomPermutation(IEnumerable sequence) { + T[] retArray = sequence.ToArray(); + + + for (int i = 0; i < retArray.Length - 1; i += 1) { + int swapIndex = random.Next(i + 1, retArray.Length); + T temp = retArray[i]; + retArray[i] = retArray[swapIndex]; + retArray[swapIndex] = temp; + } + + return retArray; + } + + string GetAttribute(XmlNode node, string attributeName) { + if (node == null) { + return null; + } + if (node.Attributes[attributeName] == null) { + return null; + } + return node.Attributes[attributeName].Value; + } + } +} diff --git a/src/Core/Compiler/SymbolFile/SymbolFile.cs b/src/Core/Compiler/SymbolFile/SymbolFile.cs new file mode 100644 index 000000000..92c3a84b9 --- /dev/null +++ b/src/Core/Compiler/SymbolFile/SymbolFile.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ScriptSharp.SymbolFile { + internal class SymbolFile { + + internal const string RootElement = "Symbols"; + internal const string SymbolElement = "Symbol"; + internal const string GeneratedNameAttribute = "GeneratedName"; + internal const string NameAttribute = "Name"; + internal const string TypeAttribute = "Type"; + internal const string HasApplicationTypesAttribute = "HasApplicationTypes"; + internal const string IsExtenderClassAttribute = "IsExtenderClass"; + internal const string BaseClassAttribute = "BaseClass"; + internal const string FlagAttribute = "Flag"; + internal const string ReadOnlyAttribute = "ReadOnly"; + internal const string AssociatedTypeAttribute = "AssociatedType"; + internal const string VisibilityAttribute = "Visibility"; + internal const string ConditionsAttribute = "Conditions"; + internal const string ValueTypeAttribute = "ValueType"; + internal const string ModeAttribute = "Mode"; + internal const string IsPublicAttribute = "IsPublic"; + internal const string AbstractAttribute = "Abstract"; + internal const string InterfaceMemberAttribute = "InterfaceMember"; + internal const string SetterTypeName = "Setter"; + internal const string GetterTypeName = "Getter"; + internal const string AliasedAttribute = "IsAliased"; + internal const string IsScriptImportedAttribute = "IsScriptImported"; + + + } +} diff --git a/src/Core/Compiler/SymbolFile/SymbolFileGenerator.cs b/src/Core/Compiler/SymbolFile/SymbolFileGenerator.cs new file mode 100644 index 000000000..dd8eaa133 --- /dev/null +++ b/src/Core/Compiler/SymbolFile/SymbolFileGenerator.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.CodeDom.Compiler; +using ScriptSharp.ScriptModel; +using System.IO; +using System.Diagnostics; +using System.Collections; +using System.Xml; + +namespace ScriptSharp.SymbolFile { + + /// + /// Generates symbol files from extracted symbol informations. + /// + internal class SymbolFileGenerator { + + + private readonly XmlTextWriter _writer; + + + internal SymbolFileGenerator(TextWriter writer) { + Debug.Assert(writer != null); + + _writer = new XmlTextWriter(writer); + + } + + internal void Generate(SymbolSet symbols) { + + _writer.WriteStartDocument(); + _writer.WriteStartElement(SymbolFile.RootElement); + + DumpSymbols(symbols); + + _writer.WriteEndElement(); + _writer.WriteEndDocument(); + + } + #region Dump + + + private void DumpSymbols(SymbolSet symbols) { + ArrayList namespaces = new ArrayList(symbols.Namespaces.Count); + foreach (NamespaceSymbol ns in symbols.Namespaces) { + namespaces.Add(ns); + } + namespaces.Sort(new SymbolComparer()); + + foreach (NamespaceSymbol ns in namespaces) { + DumpSymbol(ns); + + } + } + + + private void WriteElement(Symbol s) { + + _writer.WriteEndElement(); + + } + + #endregion + private void DumpClass(ClassSymbol classSymbol) { + + if (classSymbol.BaseClass != null) { + _writer.WriteAttributeString(SymbolFile.BaseClassAttribute, classSymbol.BaseClass.Name); + } + if (classSymbol.Interfaces != null) { + foreach (InterfaceSymbol interfaceSymbol in classSymbol.Interfaces) { + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, interfaceSymbol.Type.ToString()); + _writer.WriteAttributeString(SymbolFile.NameAttribute, interfaceSymbol.Name); + _writer.WriteEndElement(); + } + } + if (classSymbol.Constructor != null) { + DumpSymbol(classSymbol.Constructor); + } + if (classSymbol.StaticConstructor != null) { + DumpSymbol(classSymbol.StaticConstructor); + } + if (classSymbol.Indexer != null) { + DumpSymbol(classSymbol.Indexer); + } + } + + private void DumpConstructor(ConstructorSymbol ctorSymbol) { + if (ctorSymbol.Parameters != null) { + + foreach (ParameterSymbol paramSymbol in ctorSymbol.Parameters) { + DumpSymbol(paramSymbol); + } + } + } + + private void DumpDelegate(DelegateSymbol delegateSymbol) { + } + + private void DumpEnumeration(EnumerationSymbol enumSymbol) { + _writer.WriteAttributeString(SymbolFile.FlagAttribute, enumSymbol.Flags.ToString()); + } + + private void DumpEnumerationField(EnumerationFieldSymbol enumFieldSymbol) { + } + + private void DumpEvent(EventSymbol eventSymbol) { + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.GetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, eventSymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "add_" + eventSymbol.GeneratedName); + _writer.WriteEndElement(); + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.SetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, eventSymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "remove_" + eventSymbol.GeneratedName); + _writer.WriteEndElement(); + } + + private void DumpField(FieldSymbol fieldSymbol) { + _writer.WriteAttributeString(SymbolFile.AliasedAttribute, fieldSymbol.IsGlobalField.ToString()); + } + + private void DumpIndexer(IndexerSymbol indexerSymbol) { + _writer.WriteAttributeString(SymbolFile.ReadOnlyAttribute, indexerSymbol.IsReadOnly.ToString()); + _writer.WriteAttributeString(SymbolFile.AbstractAttribute, indexerSymbol.IsAbstract.ToString()); + + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.GetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, indexerSymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "get_" + indexerSymbol.GeneratedName); + _writer.WriteEndElement(); + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.SetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, indexerSymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "set_" + indexerSymbol.GeneratedName); + _writer.WriteEndElement(); + + } + + private void DumpInterface(InterfaceSymbol interfaceSymbol) { + } + + private void DumpMember(MemberSymbol memberSymbol) { + + _writer.WriteAttributeString(SymbolFile.AssociatedTypeAttribute, memberSymbol.AssociatedType.Name.ToString()); + _writer.WriteAttributeString(SymbolFile.VisibilityAttribute, memberSymbol.Visibility.ToString()); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, memberSymbol.GeneratedName); + + if (memberSymbol.InterfaceMember != null) { + _writer.WriteAttributeString(SymbolFile.InterfaceMemberAttribute, string.Format( + "{0}.{1}", memberSymbol.InterfaceMember.Parent.Name, memberSymbol.InterfaceMember.Name)); + } + + switch (memberSymbol.Type) { + case SymbolType.Field: + DumpField((FieldSymbol)memberSymbol); + break; + case SymbolType.EnumerationField: + DumpEnumerationField((EnumerationFieldSymbol)memberSymbol); + break; + case SymbolType.Constructor: + DumpConstructor((ConstructorSymbol)memberSymbol); + break; + case SymbolType.Property: + DumpProperty((PropertySymbol)memberSymbol); + break; + case SymbolType.Indexer: + DumpIndexer((IndexerSymbol)memberSymbol); + break; + case SymbolType.Event: + DumpEvent((EventSymbol)memberSymbol); + break; + case SymbolType.Method: + DumpMethod((MethodSymbol)memberSymbol); + break; + } + + } + + private void DumpMethod(MethodSymbol methodSymbol) { + + + _writer.WriteAttributeString(SymbolFile.AbstractAttribute, methodSymbol.IsAbstract.ToString()); + _writer.WriteAttributeString(SymbolFile.AliasedAttribute, methodSymbol.IsAliased.ToString()); + + if (methodSymbol.Conditions != null) { + + StringBuilder sb = new StringBuilder(); + foreach (string condition in methodSymbol.Conditions) { + sb.Append(condition); + sb.Append(","); + } + _writer.WriteAttributeString(SymbolFile.ConditionsAttribute, sb.ToString()); + } + + if (methodSymbol.Parameters != null) { + + foreach (ParameterSymbol paramSymbol in methodSymbol.Parameters) { + DumpSymbol(paramSymbol); + } + + } + } + + private void DumpNamespace(NamespaceSymbol namespaceSymbol) { + + _writer.WriteAttributeString(SymbolFile.HasApplicationTypesAttribute, namespaceSymbol.HasApplicationTypes.ToString()); + + ArrayList types = new ArrayList(namespaceSymbol.Types.Count); + foreach (TypeSymbol type in namespaceSymbol.Types) { + types.Add(type); + } + types.Sort(new SymbolComparer()); + + foreach (TypeSymbol type in types) { + DumpSymbol(type); + } + } + + private void DumpParameter(ParameterSymbol parameterSymbol) { + _writer.WriteAttributeString(SymbolFile.ValueTypeAttribute, parameterSymbol.ValueType.Name); + _writer.WriteAttributeString(SymbolFile.ModeAttribute, parameterSymbol.Mode.ToString()); + } + + private void DumpProperty(PropertySymbol propertySymbol) { + _writer.WriteAttributeString(SymbolFile.ReadOnlyAttribute, propertySymbol.IsReadOnly.ToString()); + _writer.WriteAttributeString(SymbolFile.AbstractAttribute, propertySymbol.IsAbstract.ToString()); + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.GetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, propertySymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "get_" + propertySymbol.GeneratedName); + _writer.WriteEndElement(); + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, SymbolFile.SetterTypeName); + _writer.WriteAttributeString(SymbolFile.NameAttribute, propertySymbol.Name); + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, "set_" + propertySymbol.GeneratedName); + _writer.WriteEndElement(); + + } + + private void DumpSymbol(Symbol symbol) { + + _writer.WriteStartElement(SymbolFile.SymbolElement); + _writer.WriteAttributeString(SymbolFile.TypeAttribute, symbol.Type.ToString()); + _writer.WriteAttributeString(SymbolFile.NameAttribute, symbol.Name); + + switch (symbol.Type) { + case SymbolType.Namespace: + DumpNamespace((NamespaceSymbol)symbol); + break; + case SymbolType.Class: + case SymbolType.Interface: + case SymbolType.Enumeration: + case SymbolType.Delegate: + case SymbolType.Record: + DumpType((TypeSymbol)symbol); + break; + case SymbolType.Field: + case SymbolType.EnumerationField: + case SymbolType.Constructor: + case SymbolType.Property: + case SymbolType.Indexer: + case SymbolType.Event: + case SymbolType.Method: + DumpMember((MemberSymbol)symbol); + break; + case SymbolType.Parameter: + DumpParameter((ParameterSymbol)symbol); + break; + } + + _writer.WriteEndElement(); + + } + + private void DumpType(TypeSymbol typeSymbol) { + + _writer.WriteAttributeString(SymbolFile.IsExtenderClassAttribute, typeSymbol.IsApplicationType.ToString()); + _writer.WriteAttributeString(SymbolFile.IsPublicAttribute, typeSymbol.IsPublic.ToString()); + _writer.WriteAttributeString(SymbolFile.IsScriptImportedAttribute, typeSymbol.IsScriptImported.ToString()); + + _writer.WriteAttributeString(SymbolFile.GeneratedNameAttribute, typeSymbol.GeneratedName); + + switch (typeSymbol.Type) { + case SymbolType.Class: + case SymbolType.Record: + DumpClass((ClassSymbol)typeSymbol); + break; + case SymbolType.Interface: + DumpInterface((InterfaceSymbol)typeSymbol); + break; + case SymbolType.Enumeration: + DumpEnumeration((EnumerationSymbol)typeSymbol); + break; + case SymbolType.Delegate: + DumpDelegate((DelegateSymbol)typeSymbol); + break; + } + + foreach (MemberSymbol member in typeSymbol.Members) { + DumpSymbol(member); + } + + } + private sealed class SymbolComparer : IComparer { + + public int Compare(object x, object y) { + return String.Compare(((Symbol)x).Name, ((Symbol)y).Name); + } + } + + + + } +} diff --git a/src/Core/Compiler/SymbolFile/SymbolFileMerger.cs b/src/Core/Compiler/SymbolFile/SymbolFileMerger.cs new file mode 100644 index 000000000..c35c32df6 --- /dev/null +++ b/src/Core/Compiler/SymbolFile/SymbolFileMerger.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using System.IO; + +namespace ScriptSharp.SymbolFile { + + /// + /// Merges multiple symbol files into a single one + /// + public class SymbolFileMerger { + + public bool Merge(string[] symbols, string mergefile, out string error) { + + bool success = false; + try { + TryMerge(symbols, mergefile); + success = true; + error = null; + } catch (Exception e) { + error = e.ToString(); + } + return success; + } + + private void TryMerge(string[] symbols, string mergefile) { + + var merged = new XmlDocument(); + XmlElement root = merged.CreateElement(SymbolFile.RootElement); + merged.AppendChild(root); + + foreach (var symbol in symbols) { + var xml = new XmlDocument(); + xml.Load(symbol); + + string namespaces = string.Format("/{0}/{1}[@{2}='Namespace']", SymbolFile.RootElement, SymbolFile.SymbolElement, SymbolFile.TypeAttribute); + foreach (XmlNode node in xml.SelectNodes(namespaces)) { + MergeNamespace(merged, root, node); + } + } + + merged.Save(mergefile); + } + + private void MergeNamespace(XmlDocument merged, XmlElement root, XmlNode node) { + + string name = node.Attributes["Name"] == null ? null : node.Attributes["Name"].Value; + string ns = string.Format("/{0}/{1}[@{2}='Namespace'][@{3}='{4}']", SymbolFile.RootElement, SymbolFile.SymbolElement, SymbolFile.TypeAttribute, SymbolFile.NameAttribute, name); + + var exists = merged.SelectSingleNode(ns); + bool existsHasApplicationType = HasApplicationAttribue(exists); + bool nodeHasApplicationType = HasApplicationAttribue(node); + + if (exists == null) { + var imported = merged.ImportNode(node, true); + root.AppendChild(imported); + } else if (exists != null + && !existsHasApplicationType + && nodeHasApplicationType) { + root.RemoveChild(exists); + var imported = merged.ImportNode(node, true); + root.AppendChild(imported); + } + } + + private bool HasApplicationAttribue(XmlNode node) { + if (node == null) { + return false; + } + if (node.Attributes[SymbolFile.HasApplicationTypesAttribute] == null) { + return false; + } + bool value = false; + bool.TryParse(node.Attributes[SymbolFile.HasApplicationTypesAttribute].Value, out value); + return value; + } + } +} diff --git a/src/ScriptSharp.sln b/src/ScriptSharp.sln index fef45edef..055b248d4 100644 --- a/src/ScriptSharp.sln +++ b/src/ScriptSharp.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "jQuery.Core", "Libraries\jQuery\jQuery.Core\jQuery.Core.csproj", "{4A9F7CE0-5A45-4B28-AD01-05528709B6E4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "Libraries\Web\Web.csproj", "{3681A9A8-FC40-4125-B842-7775713C8DCE}" diff --git a/src/Tools/Deployment/Deployment.csproj b/src/Tools/Deployment/Deployment.csproj index 6d7a332df..3dd0e1a1d 100644 --- a/src/Tools/Deployment/Deployment.csproj +++ b/src/Tools/Deployment/Deployment.csproj @@ -33,6 +33,11 @@ 4 + + False + ..\..\..\tools\ext\AjaxMin.dll + False + @@ -40,6 +45,8 @@ + + Properties\ScriptSharp.cs @@ -49,8 +56,16 @@ PreserveNewest + Designer + + + {9F14036F-673F-418E-B817-7E2289D7F3F6} + Compiler + False + +