/// <summary> /// Resolves reference from libraries to classes and other libraries. /// </summary> /// <param name="libraryTable">The table of known libraries.</param> /// <param name="resolvedLibraryList">The list of libraries that have been resolved so far.</param> /// <param name="importChanged">Indicates that the import specifier has changed.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if the method succeeded.</returns> public virtual bool Resolve(ISealableDictionary <string, ISealableDictionary <string, ILibrary> > libraryTable, IList <ILibrary> resolvedLibraryList, ref bool importChanged, IErrorList errorList) { List <IImport> ToRemove = new List <IImport>(); bool Success = true; foreach (IImport ImportItem in ImportList) { // Check the import and obtain the matching library. if (!ImportItem.CheckImportConsistency(libraryTable, out ILibrary MatchingLibrary, errorList)) { Success = false; continue; } // You can't import the same library twice. if (ImportedLibraryList.Contains(MatchingLibrary)) { Success = false; errorList.AddError(new ErrorDuplicateImport((IIdentifier)ImportItem.LibraryIdentifier, MatchingLibrary.ValidLibraryName, MatchingLibrary.ValidSourceName)); continue; } // If the imported library hasn't been resolved yet, ignore it for now. if (!resolvedLibraryList.Contains(MatchingLibrary)) { continue; } // The imported library was resolved, merge this import with it. if (!MergeImports(ImportedClassTable, ImportItem, MatchingLibrary, errorList)) { Success = false; continue; } ImportedLibraryList.Add(MatchingLibrary); ToRemove.Add(ImportItem); importChanged = true; } foreach (IImport ImportItem in ToRemove) { ImportList.Remove(ImportItem); } Debug.Assert(Success || !errorList.IsEmpty); return(Success); }
/// <summary> /// Validates a class import clauses. /// </summary> /// <param name="libraryTable">Imported libraries.</param> /// <param name="classTable">Imported classes.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if imports are valid.</returns> public virtual bool CheckClassConsistency(ISealableDictionary <string, ISealableDictionary <string, ILibrary> > libraryTable, ISealableDictionary <string, ISealableDictionary <string, IClass> > classTable, IErrorList errorList) { bool Success = true; // Process all import clauses separately. foreach (IImport ImportItem in ImportList) { if (!ImportItem.CheckImportConsistency(libraryTable, out ILibrary MatchingLibrary, errorList)) { Success = false; continue; } if (ImportedLibraryList.Contains(MatchingLibrary)) { Success = false; errorList.AddError(new ErrorDuplicateImport((IIdentifier)ImportItem.LibraryIdentifier, MatchingLibrary.ValidLibraryName, MatchingLibrary.ValidSourceName)); continue; } if (!Library.MergeImports(ImportedClassTable, ImportItem, MatchingLibrary, errorList)) { Success = false; continue; } ImportedLibraryList.Add(MatchingLibrary); } // Check import specifications. foreach (KeyValuePair <string, IImportedClass> Entry in ImportedClassTable) { IImportedClass Imported = Entry.Value; if (Imported.Item == this) { string NewName = Entry.Key; if (NewName != ValidClassName) { Success = false; errorList.AddError(new ErrorNameChanged(Imported.ImportLocation, ValidClassName, NewName)); } if (Imported.IsTypeAssigned && Imported.ImportType != BaseNode.ImportType.Latest) { Success = false; errorList.AddError(new ErrorImportTypeConflict(Imported.ImportLocation, ValidClassName)); } break; } } // If not referenced by an imported library, a class should be able to reference itself. if (!ImportedClassTable.ContainsKey(ValidClassName)) { IImportedClass SelfImport = new ImportedClass(this, BaseNode.ImportType.Latest); ImportedClassTable.Add(ValidClassName, SelfImport); #if COVERAGE string ImportString = SelfImport.ToString(); #endif } foreach (KeyValuePair <string, IImportedClass> Entry in ImportedClassTable) { IImportedClass Imported = Entry.Value; Imported.SetParentSource(this); } ImportedClassTable.Seal(); Debug.Assert(Success || !errorList.IsEmpty); return(Success); }