public LocalizedLibraryView GetCoreLibrary(ParserContext parser) { string anyValidCoreLibId = "en:Core"; LibraryMetadata coreLib = this.libraryFinder.GetLibraryMetadataFromAnyPossibleKey(anyValidCoreLibId); string name = coreLib.GetName(parser.CurrentLocale); return(this.GetOrImportLibrary(parser, null, name)); }
public bool IsAllowedImport(LibraryMetadata currentLibrary) { if (this.IsImportRestricted) { // Non-empty list means it must be only accessible from a specific library and not top-level user code. if (currentLibrary == null) { return(false); } // Is the current library on the list? return(this.OnlyImportableFrom.Contains(currentLibrary.ID)); } return(true); }
private LocalizedLibraryView GetOrImportLibraryImpl(ParserContext parser, Token throwToken, string fullImportNameWithDots) { // TODO: allow importing from a user-specified locale Locale fromLocale = parser.CurrentLocale; string name = fullImportNameWithDots.Contains('.') ? fullImportNameWithDots.Split('.')[0] : fullImportNameWithDots; string secondAttemptedKey = name; LibraryMetadata libraryMetadata = this.libraryFinder.GetLibraryMetadataFromAnyPossibleKey(fromLocale.ID + ":" + name); Locale effectiveLocale = fromLocale; if (libraryMetadata == null) { libraryMetadata = this.libraryFinder.GetLibraryMetadataFromAnyPossibleKey(name); if (libraryMetadata != null && libraryMetadata.SupportedLocales.Contains(fromLocale) && libraryMetadata.InternalLocale != fromLocale) { // Coincidental cross-language collision. return(null); } if (libraryMetadata == null) { // Simply no matches at all. return(null); } effectiveLocale = libraryMetadata.InternalLocale; } // Are there any restrictions on importing that library from this location? if (!libraryMetadata.IsAllowedImport(parser.CurrentLibrary)) { throw new ParserException(throwToken, "This library cannot be imported from here."); } // Ensure all secondary lookups for each locale is instantiated to make the upcoming code more readable. if (!this.importedLibrariesByLocalizedName.ContainsKey(effectiveLocale)) { this.importedLibrariesByLocalizedName[effectiveLocale] = new Dictionary <string, LocalizedLibraryView>(); } if (!this.importedLibrariesByLocalizedName.ContainsKey(libraryMetadata.InternalLocale)) { this.importedLibrariesByLocalizedName[libraryMetadata.InternalLocale] = new Dictionary <string, LocalizedLibraryView>(); } // Check to see if this library has been imported before. if (this.importedLibrariesById.ContainsKey(libraryMetadata.ID)) { // Is it imported by the same locale? if (this.importedLibrariesByLocalizedName[effectiveLocale].ContainsKey(name)) { // Then just return the previous instance as-is. return(this.importedLibrariesByLocalizedName[effectiveLocale][name]); } // Wrap the previous instance in the new locale. LocalizedLibraryView output = new LocalizedLibraryView(effectiveLocale, this.importedLibrariesById[libraryMetadata.ID]); this.importedLibrariesByLocalizedName[effectiveLocale][output.Name] = output; return(output); } // If the library exists but hasn't been imported before, instantiate it and // add it to all the lookups. This needs to happen before parsing the embedded // code to prevent infinite recursion. LibraryCompilationScope libraryScope = new LibraryCompilationScope(parser.BuildContext, libraryMetadata); this.librariesAlreadyImportedIndexByKey[libraryMetadata.CanonicalKey] = this.ImportedLibraries.Count; this.ImportedLibraries.Add(libraryScope); this.importedLibrariesById[libraryMetadata.ID] = libraryScope; LocalizedLibraryView localizedView = new LocalizedLibraryView(effectiveLocale, libraryScope); this.importedLibrariesByLocalizedName[effectiveLocale][name] = localizedView; // Parse the library. parser.PushScope(libraryScope); Dictionary <string, string> embeddedCode = libraryMetadata.GetEmbeddedCode(); foreach (string embeddedFile in embeddedCode.Keys.OrderBy(s => s.ToLower())) { string fakeName = "[" + embeddedFile + "]"; string code = embeddedCode[embeddedFile]; parser.ParseInterpretedCode(fakeName, code); } parser.PopScope(); return(localizedView); }
public LibraryCompilationScope(BuildContext buildContext, LibraryMetadata library) : base(buildContext) { this.Library = library; this.scopeKey = library.CanonicalKey; this.Library.LibraryScope = this; }
private static LibraryMetadata[] GetAvailableLibraryPathsByLibraryName( string nullableBuildFileCrayonPath, string nullableProjectDirectory) { string crayonHome = System.Environment.GetEnvironmentVariable("CRAYON_HOME"); #if RELEASE if (crayonHome == null) { throw new System.InvalidOperationException("Please set the CRAYON_HOME environment variable to the location of the directory containing both 'crayon.exe' and the 'lib' directory."); } #endif string placesWhereLibraryDirectoriesCanExist = ""; if (crayonHome != null) { placesWhereLibraryDirectoriesCanExist += ";" + FileUtil.JoinPath(crayonHome, "libs"); } if (nullableBuildFileCrayonPath != null) { placesWhereLibraryDirectoriesCanExist += ";" + nullableBuildFileCrayonPath; } placesWhereLibraryDirectoriesCanExist += ";" + (System.Environment.GetEnvironmentVariable("CRAYON_PATH") ?? ""); #if OSX placesWhereLibraryDirectoriesCanExist = placesWhereLibraryDirectoriesCanExist.Replace(':', ';'); #endif string[] paths = placesWhereLibraryDirectoriesCanExist.Split(new char[] { ';' }, System.StringSplitOptions.RemoveEmptyEntries); List <string> unverifiedLibraryDirectories = new List <string>(); foreach (string path in paths) { // TODO: figure out why this says nullable yet is being used directly. string absolutePath = FileUtil.GetAbsolutePathFromRelativeOrAbsolutePath(nullableProjectDirectory, path); if (FileUtil.DirectoryExists(absolutePath)) { unverifiedLibraryDirectories.AddRange(FileUtil.DirectoryListDirectoryPaths(absolutePath)); } } #if DEBUG // Presumably running from source. Walk up to the root directory and find the Libraries directory. // From there use the list of folders. string currentDirectory = FileUtil.GetCurrentDirectory(); while (!string.IsNullOrEmpty(currentDirectory)) { string path = FileUtil.JoinPath(currentDirectory, "Libraries"); if (FileUtil.DirectoryExists(path) && FileUtil.FileExists(FileUtil.JoinPath(currentDirectory, "Compiler", "CrayonWindows.sln"))) // quick sanity check { unverifiedLibraryDirectories.AddRange(FileUtil.DirectoryListDirectoryPaths(path)); break; } currentDirectory = FileUtil.GetParentDirectory(currentDirectory); } #endif List <string> verifiedLibraryPaths = new List <string>(); foreach (string dir in unverifiedLibraryDirectories) { string manifestPath = FileUtil.JoinPath(dir, "manifest.json"); if (FileUtil.FileExists(manifestPath)) { verifiedLibraryPaths.Add(dir); } } // Library name collisions will override any previous definition. // For example, a custom library referenced by a build file will override a built-in library. // An example use case of this would be to define a custom library called "Gamepad" for mobile that puts // buttons in the corners of the screen, but without having to change any code to be platform-aware. Dictionary <string, LibraryMetadata> uniqueLibraries = new Dictionary <string, LibraryMetadata>(); foreach (string path in verifiedLibraryPaths) { string defaultName = FileUtil.GetFileNameFromPath(path); LibraryMetadata metadata = new LibraryMetadata(path, defaultName); // TODO: don't hardcode EN string uniqueKey = "en:" + metadata.ID; uniqueLibraries[uniqueKey] = metadata; } return(uniqueLibraries.Values .OrderBy(metadata => metadata.ID.ToLower()) .ToArray()); }