diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-10-16 18:49:11 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-16 18:49:11 -0400 |
| commit | 3e74d39f24fdfaa547ce900be177863e2bfe2dea (patch) | |
| tree | 9a5143e6de4caa27b23fc870003011e96129905f /source/slang/slang.cpp | |
| parent | 204fb3c75b520a2cbb1c25f995a8c424ec2753f3 (diff) | |
Feature/include refactor (#675)
* Refactor of path handling.
* Added PathInfo
* Changed ISlangFileSystem - such that has separate concepts of reading a file, getting a relative path and getting a canonical path
* Added support for getting a canonical path for windows/linux
* Made maps/testing around canonicalPaths
* User output remains around 'foundPath' - which is the same as before
* Small improvements around PathInfo
* Added a type and make constructors to make clear the different 'path' uses
* Fixed bug in findViewRecursively
* Checking and reporting for ignored #pragma once.
* Removed SLANG_PATH_TYPE_NONE as doesn't serve any useful purpose.
* Improve comments in slang.h aroung ISlangFileSystem
* Remove the need for <windows.h> in slang-io.cpp
* Ran premake5.
* Improvements and fixes around PathInfo.
* Fix typo on linix GetCanonical
* Make the ISlangFileSystem the same as before, and ISlangFileSystem contain the new methods.
Internally it always uses the ISlangFileSystemExt, and will wrap a ISlangFileSystem with WrapFileSystem, if it is determined (via queryInterface) that it doesn't implement the full interface.
Diffstat (limited to 'source/slang/slang.cpp')
| -rw-r--r-- | source/slang/slang.cpp | 196 |
1 files changed, 148 insertions, 48 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index c04aaa044..908bee283 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -9,6 +9,8 @@ #include "syntax-visitors.h" #include "../slang/type-layout.h" +#include "include-file-system.h" + #include "ir-serialize.h" // Used to print exception type names in internal-compiler-error messages @@ -75,39 +77,106 @@ Session::Session() addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode()); } +static String getString(ISlangBlob* blob) +{ + if (blob) + { + size_t size = blob->getBufferSize(); + if (size > 0) + { + const char* contents = (const char*)blob->getBufferPointer(); + // Check it has terminating 0, if not we must construct as if it does + if (contents[size - 1] == 0) + { + size --; + } + return String(contents, contents + size); + } + } + return String(); +} + struct IncludeHandlerImpl : IncludeHandler { CompileRequest* request; - virtual IncludeResult TryToFindIncludeFile( + ISlangFileSystemExt* _getFileSystemExt() + { + return request->fileSystemExt; + } + + SlangResult _findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& pathInfoOut) + { + ISlangFileSystemExt* fileSystemExt = _getFileSystemExt(); + + // Get relative path + ComPtr<ISlangBlob> relPathBlob; + SLANG_RETURN_ON_FAIL(fileSystemExt->calcRelativePath(fromPathType, fromPath.begin(), path.begin(), relPathBlob.writeRef())); + String relPath(getString(relPathBlob)); + if (relPath.Length() <= 0) + { + return SLANG_FAIL; + } + + // Get the canonical path + ComPtr<ISlangBlob> canonicalPathBlob; + SLANG_RETURN_ON_FAIL(fileSystemExt->getCanoncialPath(relPath.begin(), canonicalPathBlob.writeRef())); + + // If the rel path exists -> the canonical path MUST exists too + String canonicalPath(getString(canonicalPathBlob)); + if (canonicalPath.Length() <= 0) + { + // Canonical path can't be empty + return SLANG_FAIL; + } + + pathInfoOut.type = PathInfo::Type::Normal; + pathInfoOut.foundPath = relPath; + pathInfoOut.canonicalPath = canonicalPath; + return SLANG_OK; + } + + virtual SlangResult findFile( String const& pathToInclude, String const& pathIncludedFrom, - String* outFoundPath, - ISlangBlob** outFoundSourceBlob) override + PathInfo& pathInfoOut) override { - String path = Path::Combine(Path::GetDirectoryName(pathIncludedFrom), pathToInclude); + pathInfoOut.type = PathInfo::Type::Unknown; - if(SLANG_SUCCEEDED(request->loadFile(path, outFoundSourceBlob))) + // Try just relative to current path { - *outFoundPath = path; - request->mDependencyFilePaths.Add(path); - return IncludeResult::Found; + SlangResult res = _findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, pathInfoOut); + // It either succeeded or wasn't found, anything else is a failure passed back + if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) + { + return res; + } } + // Search all the searchDirectories for (auto & dir : request->searchDirectories) { - path = Path::Combine(dir.path, pathToInclude); - - if(SLANG_SUCCEEDED(request->loadFile(path, outFoundSourceBlob))) + SlangResult res = _findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, pathInfoOut); + if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) { - *outFoundPath = path; - request->mDependencyFilePaths.Add(path); - return IncludeResult::Found; + return res; } } - return IncludeResult::NotFound; + return SLANG_E_NOT_FOUND; + } + + virtual SlangResult readFile(const String& path, + ISlangBlob** blobOut) override + { + ISlangFileSystem* fileSystemExt = _getFileSystemExt(); + SLANG_RETURN_ON_FAIL(fileSystemExt->loadFile(path.begin(), blobOut)); + + request->mDependencyFilePaths.Add(path); + + return SLANG_OK; } + }; // @@ -244,6 +313,10 @@ CompileRequest::CompileRequest(Session* session) setSourceManager(&sourceManagerStorage); sourceManager->initialize(session->getBuiltinSourceManager()); + + // Set up the default file system + SLANG_ASSERT(fileSystem == nullptr); + fileSystemExt = IncludeFileSystem::getDefault(); } CompileRequest::~CompileRequest() @@ -376,7 +449,7 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio SourceManager localSourceManager; localSourceManager.initialize(sourceManager); - Slang::RefPtr<Slang::SourceFile> srcFile(localSourceManager.createSourceFile(String("type string"), typeStr)); + Slang::RefPtr<Slang::SourceFile> srcFile(localSourceManager.createSourceFile(PathInfo::makeTypeParse(), typeStr)); // We'll use a temporary diagnostic sink DiagnosticSink sink; @@ -706,7 +779,8 @@ void CompileRequest::addTranslationUnitSourceBlob( String const& path, ISlangBlob* sourceBlob) { - RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(path, sourceBlob); + PathInfo pathInfo = PathInfo::makePath(path); + RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(pathInfo, sourceBlob); addTranslationUnitSourceFile(translationUnitIndex, sourceFile); } @@ -716,7 +790,8 @@ void CompileRequest::addTranslationUnitSourceString( String const& path, String const& source) { - RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(path, source); + PathInfo pathInfo = PathInfo::makePath(path); + RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(pathInfo, source); addTranslationUnitSourceFile(translationUnitIndex, sourceFile); } @@ -789,13 +864,18 @@ UInt CompileRequest::addTarget( void CompileRequest::loadParsedModule( RefPtr<TranslationUnitRequest> const& translationUnit, Name* name, - String const& path) + const PathInfo& pathInfo) { // Note: we add the loaded module to our name->module listing // before doing semantic checking, so that if it tries to // recursively `import` itself, we can detect it. RefPtr<LoadedModule> loadedModule = new LoadedModule(); - mapPathToLoadedModule.Add(path, loadedModule); + + // Get a path + String mostUniquePath = pathInfo.getMostUniquePath(); + SLANG_ASSERT(mostUniquePath.Length() > 0); + + mapPathToLoadedModule.Add(mostUniquePath, loadedModule); mapNameToLoadedModules.Add(name, loadedModule); int errorCountBefore = mSink.GetErrorCount(); @@ -821,8 +901,8 @@ void CompileRequest::loadParsedModule( RefPtr<ModuleDecl> CompileRequest::loadModule( Name* name, - String const& path, - ISlangBlob* sourceBlob, + const PathInfo& filePathInfo, + ISlangBlob* sourceBlob, SourceLoc const& srcLoc) { RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(); @@ -835,11 +915,11 @@ RefPtr<ModuleDecl> CompileRequest::loadModule( // TODO: decide which options, if any, should be inherited. translationUnit->compileFlags = 0; - RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(path, sourceBlob); + // Create with the 'friendly' name + RefPtr<SourceFile> sourceFile = getSourceManager()->createSourceFile(filePathInfo, sourceBlob); translationUnit->sourceFiles.Add(sourceFile); - int errorCountBefore = mSink.GetErrorCount(); parseTranslationUnit(translationUnit.Ptr()); int errorCountAfter = mSink.GetErrorCount(); @@ -854,7 +934,7 @@ RefPtr<ModuleDecl> CompileRequest::loadModule( loadParsedModule( translationUnit, name, - path); + filePathInfo); errorCountAfter = mSink.GetErrorCount(); @@ -891,7 +971,7 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule( } // Derive a file name for the module, by taking the given - // identifier, replacing all occurences of `_` with `-`, + // identifier, replacing all occurrences of `_` with `-`, // and then appending `.slang`. // // For example, `foo_bar` becomes `foo-bar.slang`. @@ -914,39 +994,37 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule( IncludeHandlerImpl includeHandler; includeHandler.request = this; - // Get the original path - String pathIncludedFrom= getSourceManager()->getPath(loc, SourceLocType::Actual); - - String foundPath; - ComPtr<ISlangBlob> foundSourceBlob; - IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, foundSourceBlob.writeRef()); - switch( includeResult ) - { - case IncludeResult::NotFound: - case IncludeResult::Error: - { - this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); - - mapNameToLoadedModules[name] = nullptr; - return nullptr; - } - break; + // Get the original path info + PathInfo pathIncludedFromInfo = getSourceManager()->getPathInfo(loc, SourceLocType::Actual); + PathInfo filePathInfo; - default: - break; + // There is an argument to passing in the 'canonicalPath' instead of the foundPath, but either should work here + if (SLANG_FAILED(includeHandler.findFile(fileName, pathIncludedFromInfo.foundPath, filePathInfo))) + { + this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); + mapNameToLoadedModules[name] = nullptr; + return nullptr; } // Maybe this was loaded previously at a different relative name? - if (mapPathToLoadedModule.TryGetValue(foundPath, loadedModule)) + if (mapPathToLoadedModule.TryGetValue(filePathInfo.canonicalPath, loadedModule)) return loadedModule->moduleDecl; + // Try to load it + ComPtr<ISlangBlob> fileContents; + if (SLANG_FAILED(includeHandler.readFile(filePathInfo.canonicalPath, fileContents.writeRef()))) + { + this->mSink.diagnose(loc, Diagnostics::cannotOpenFile, fileName); + mapNameToLoadedModules[name] = nullptr; + return nullptr; + } // We've found a file that we can load for the given module, so // go ahead and perform the module-load action return loadModule( name, - foundPath, - foundSourceBlob, + filePathInfo, + fileContents, loc); } @@ -1121,13 +1199,35 @@ SLANG_API void spDestroyCompileRequest( delete req; } +static const Slang::Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt; + SLANG_API void spSetFileSystem( SlangCompileRequest* request, ISlangFileSystem* fileSystem) { if(!request) return; auto req = REQ(request); + + // Set the fileSystem req->fileSystem = fileSystem; + + // Set up fileSystemExt appropriately + if (fileSystem == nullptr) + { + req->fileSystemExt = Slang::IncludeFileSystem::getDefault(); + } + else + { + // See if we have the interface + fileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)req->fileSystemExt.writeRef()); + + // If not wrap with WrapFileSytem that keeps the old behavior + if (!req->fileSystemExt) + { + // Construct a wrapper to emulate the extended interface behavior + req->fileSystemExt = new Slang::WrapFileSystem(fileSystem); + } + } } |
