public ICollection<SymbolImplementation> BuildCode(SymbolSet symbols) { _implementations = new List<SymbolImplementation>(); foreach (NamespaceSymbol namespaceSymbol in symbols.Namespaces) { if (namespaceSymbol.HasApplicationTypes == false) { continue; } foreach (TypeSymbol type in namespaceSymbol.Types) { if (type.IsApplicationType == false) { continue; } if (type.IsTestType && !_options.IncludeTests) { // Ignore test types, if tests are not to be compiled continue; } switch (type.Type) { case SymbolType.Class: BuildCode((ClassSymbol)type); break; case SymbolType.Record: if (((RecordSymbol)type).Constructor != null) { BuildCode(((RecordSymbol)type).Constructor); } break; } } } return _implementations; }
public void GenerateScript(SymbolSet symbolSet) { Debug.Assert(symbolSet != null); Dictionary<string, bool> generatedNamespaces = new Dictionary<string, bool>(); foreach (NamespaceSymbol namespaceSymbol in symbolSet.Namespaces) { if (namespaceSymbol.HasApplicationTypes) { NamespaceGenerator.GenerateScript(this, namespaceSymbol, generatedNamespaces); } } List<ClassSymbol> generatedClasses = new List<ClassSymbol>(_classes.Count); foreach (ClassSymbol generatedClass in _classes) { if (generatedClass.HasGlobalMethods == false) { GenerateClassRegistration(generatedClass, generatedClasses); } } // TODO: Couple of line-breaks would be nice here // but only if there are any classes with static // ctors or members foreach (ClassSymbol generatedClass in _classes) { TypeGenerator.GenerateClassConstructorScript(this, generatedClass); } if (Options.IncludeTests) { foreach (ClassSymbol generatedClass in _classes) { if (generatedClass.IsTestClass) { TestGenerator.GenerateScript(this, generatedClass); } } } }
public NamespaceSymbol(string name, SymbolSet symbolSet) : base(SymbolType.Namespace, name, null) { _symbolSet = symbolSet; _types = new List<TypeSymbol>(); _typeMap = new Dictionary<string, TypeSymbol>(); }
public StatementBuilder(ILocalSymbolTable symbolTable, CodeMemberSymbol memberContext, IErrorHandler errorHandler, CompilerOptions options) { _symbolTable = symbolTable; _memberContext = memberContext; _symbolSet = memberContext.SymbolSet; _errorHandler = errorHandler; _expressionBuilder = new ExpressionBuilder(symbolTable, memberContext, errorHandler, options); }
public ExpressionBuilder(ILocalSymbolTable symbolTable, FieldSymbol fieldContext, IErrorHandler errorHandler, CompilerOptions options) { _symbolTable = symbolTable; _symbolContext = fieldContext; _classContext = ((ClassSymbol)fieldContext.Parent).PrimaryPartialClass; _symbolSet = fieldContext.SymbolSet; _errorHandler = errorHandler; _options = options; }
public 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); _writer.WriteLine(); } }
public bool Compile(CompilerOptions options) { if (options == null) { throw new ArgumentNullException("options"); } _options = options; _hasErrors = false; _symbols = new SymbolSet(); ImportMetadata(); if (_hasErrors) { return false; } BuildCodeModel(); if (_hasErrors) { return false; } BuildMetadata(); if (_hasErrors) { return false; } BuildImplementation(); if (_hasErrors) { return false; } GenerateScript(); if (_hasErrors) { return false; } return true; }
public ICollection<TypeSymbol> BuildMetadata(ParseNodeList compilationUnits, SymbolSet symbols, CompilerOptions options) { Debug.Assert(compilationUnits != null); Debug.Assert(symbols != null); _symbols = symbols; _symbolTable = symbols; _options = options; string scriptName = GetAssemblyScriptName(compilationUnits); if (String.IsNullOrEmpty(scriptName)) { _errorHandler.ReportError("You must declare a ScriptAssembly attribute.", String.Empty); } else if (Utility.IsValidScriptName(scriptName) == false) { string errorMessage = "The ScriptAssembly attribute referenced an invalid name '{0}'. Script names must only contain letters, numbers, dots or underscores."; _errorHandler.ReportError(String.Format(errorMessage, scriptName), String.Empty); } symbols.ScriptName = scriptName; string scriptPrefix = GetAssemblyScriptPrefix(compilationUnits); if (String.IsNullOrEmpty(scriptPrefix) == false) { if (Utility.IsValidIdentifier(scriptPrefix) == false) { string errorMessage = "The ScriptQualifier attribute referenced an invalid prefix '{0}'. Script prefix must be valid identifiers."; _errorHandler.ReportError(String.Format(errorMessage, scriptPrefix), String.Empty); } } else { scriptPrefix = scriptName.Replace(".", String.Empty); } symbols.ScriptPrefix = scriptPrefix; string assemblyScriptNamespace = GetAssemblyScriptNamespace(compilationUnits); List<TypeSymbol> types = new List<TypeSymbol>(); // Build all the types first. // Types need to be loaded upfront so that they can be used in resolving types associated // with members. foreach (CompilationUnitNode compilationUnit in compilationUnits) { foreach (NamespaceNode namespaceNode in compilationUnit.Members) { string namespaceName = namespaceNode.Name; NamespaceSymbol namespaceSymbol = symbols.GetNamespace(namespaceName); List<string> imports = null; Dictionary<string, string> aliases = null; ParseNodeList usingClauses = namespaceNode.UsingClauses; if ((usingClauses != null) && (usingClauses.Count != 0)) { foreach (ParseNode usingNode in namespaceNode.UsingClauses) { if (usingNode is UsingNamespaceNode) { if (imports == null) { imports = new List<string>(usingClauses.Count); } string referencedNamespace = ((UsingNamespaceNode)usingNode).ReferencedNamespace; if (imports.Contains(referencedNamespace) == false) { imports.Add(referencedNamespace); } } else { Debug.Assert(usingNode is UsingAliasNode); if (aliases == null) { aliases = new Dictionary<string, string>(); } UsingAliasNode aliasNode = (UsingAliasNode)usingNode; aliases[aliasNode.Alias] = aliasNode.TypeName; } } } // Add parent namespaces as imports in reverse order since they // are searched in that fashion. string[] namespaceParts = namespaceName.Split('.'); for (int i = namespaceParts.Length - 2; i >= 0; i--) { string partialNamespace; if (i == 0) { partialNamespace = namespaceParts[0]; } else { partialNamespace = String.Join(".", namespaceParts, 0, i + 1); } if (imports == null) { imports = new List<string>(); } if (imports.Contains(partialNamespace) == false) { imports.Add(partialNamespace); } } // Build type symbols for all user-defined types foreach (TypeNode typeNode in namespaceNode.Members) { UserTypeNode userTypeNode = typeNode as UserTypeNode; if (userTypeNode == null) { continue; } // Check if we have overriding script namespace for this type. string typeScriptNamespace = GetScriptNamespace(userTypeNode.Attributes); if (String.IsNullOrEmpty(typeScriptNamespace)) { typeScriptNamespace = assemblyScriptNamespace; } ClassSymbol partialTypeSymbol = null; bool isPartial = false; if ((userTypeNode.Modifiers & Modifiers.Partial) != 0) { partialTypeSymbol = (ClassSymbol)((ISymbolTable)namespaceSymbol).FindSymbol(userTypeNode.Name, /* context */ null, SymbolFilter.Types); if ((partialTypeSymbol != null) && partialTypeSymbol.IsApplicationType) { // This class will be considered as a partial class isPartial = true; // Merge code model information for the partial class onto the code model node // for the primary partial class. Interesting bits of information include things // such as base class etc. that is yet to be processed. CustomTypeNode partialTypeNode = (CustomTypeNode)partialTypeSymbol.ParseContext; partialTypeNode.MergePartialType((CustomTypeNode)userTypeNode); // Merge interesting bits of information onto the primary type symbol as well // representing this partial class BuildType(partialTypeSymbol, userTypeNode); if (String.IsNullOrEmpty(typeScriptNamespace) == false) { partialTypeSymbol.ScriptNamespace = typeScriptNamespace; } } } TypeSymbol typeSymbol = BuildType(userTypeNode, namespaceSymbol); if (typeSymbol != null) { typeSymbol.SetParseContext(userTypeNode); typeSymbol.SetParentSymbolTable(symbols); if (imports != null) { typeSymbol.SetImports(imports); } if (aliases != null) { typeSymbol.SetAliases(aliases); } if (String.IsNullOrEmpty(typeScriptNamespace) == false) { typeSymbol.ScriptNamespace = typeScriptNamespace; } if (isPartial == false) { namespaceSymbol.AddType(typeSymbol); } else { // Partial types don't get added to the namespace, so we don't have // duplicated named items. However, they still do get instantiated // and processed as usual. // // The members within partial classes refer to the partial type as their parent, // and hence derive context such as the list of imports scoped to the // particular type. // However, the members will get added to the primary partial type's list of // members so they can be found. // Effectively the partial class here gets created just to hold // context of type-symbol level bits of information such as the list of // imports, that are consumed when generating code for the members defined // within a specific partial class. ((ClassSymbol)typeSymbol).SetPrimaryPartialClass(partialTypeSymbol); } types.Add(typeSymbol); } } } } // Build inheritance chains foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Class) { BuildTypeInheritance((ClassSymbol)typeSymbol); } } // Import members foreach (TypeSymbol typeSymbol in types) { BuildMembers(typeSymbol); } // Associate interface members with interface member symbols foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Class) { BuildInterfaceAssociations((ClassSymbol)typeSymbol); } } // Load resource values if (_symbols.HasResources) { foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Resources) { BuildResources((ResourcesSymbol)typeSymbol); } } } // Load documentation if (_options.EnableDocComments) { Stream docCommentsStream = options.DocCommentFile.GetStream(); if (docCommentsStream != null) { try { XmlDocument docComments = new XmlDocument(); docComments.Load(docCommentsStream); symbols.SetComments(docComments); } finally { options.DocCommentFile.CloseStream(docCommentsStream); } } } return types; }
public ResourcesBuilder(SymbolSet symbols) { _symbols = symbols; }
public SignatureParser(SymbolSet symbols, ICompilerErrorHandler errorHandler) { _symbols = symbols; _errorHandler = errorHandler; }
public ICollection<TypeSymbol> ImportMetadata(ICollection<string> references, SymbolSet symbols) { Debug.Assert(references != null); Debug.Assert(symbols != null); _symbols = symbols; MetadataSource mdSource = new MetadataSource(); bool hasLoadErrors = mdSource.LoadReferences(references, _errorHandler); ICollection<TypeSymbol> importedTypes = null; if (hasLoadErrors == false) { importedTypes = ImportAssemblies(mdSource); } if (_resolveError) { return null; } #if STATIC_ARRAY_EXTENSIONS // Update instance members that need to be generated as static methods ConvertInstanceMembersToStaticMembers(); #endif // STATIC_ARRAY_EXTENSIONS return importedTypes; }