diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-02-04 17:30:51 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-04 17:30:51 -0500 |
| commit | 9b80537bc0272a9caf93f146d8964d9bdd4a407e (patch) | |
| tree | 13c2e92adca1b78b632bd8dd6cc1fecb5a12ded9 /source | |
| parent | 0d206996cd68b9f08ae1b4d9da6f16293984302c (diff) | |
Feature/view path (#824)
* Use 'is' over 'as' where appropriate.
* dynamic_cast -> dynamicCast
* Replace 'dynamicCast' with 'as' where has no change in behavior/ambiguity.
* Replace dynamicCast with as where doesn't change behavior/non ambiguous.
* Keep a per view path to the file loaded - such that diagnostic messages always display the path to the requested file.
* Add simplifyPath to ISlangFileSystemExt
Simplify (if possible) paths that are set on SourceFile and SourcView - doing so makes reading paths simpler.
* Fix small typo.
* Improve documentation in source for getFileUniqueIdentity
* Fix override warning.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/ir-serialize.cpp | 2 | ||||
| -rw-r--r-- | source/slang/preprocessor.cpp | 14 | ||||
| -rw-r--r-- | source/slang/preprocessor.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-file-system.cpp | 48 | ||||
| -rw-r--r-- | source/slang/slang-file-system.h | 20 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 11 | ||||
| -rw-r--r-- | source/slang/source-loc.cpp | 39 | ||||
| -rw-r--r-- | source/slang/source-loc.h | 20 |
8 files changed, 134 insertions, 22 deletions
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp index 730f13ca7..a50ed6bd5 100644 --- a/source/slang/ir-serialize.cpp +++ b/source/slang/ir-serialize.cpp @@ -1801,7 +1801,7 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi pathInfo.foundPath = debugStringSlices[UInt(srcSourceInfo.m_pathIndex)]; SourceFile* sourceFile = sourceManager->createSourceFileWithSize(pathInfo, srcSourceInfo.m_endSourceLoc - srcSourceInfo.m_startSourceLoc); - SourceView* sourceView = sourceManager->createSourceView(sourceFile); + SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr); // We need to accumulate all line numbers, for this source file, both adjusted and unadjusted List<IRSerialData::DebugLineInfo> lineInfos; diff --git a/source/slang/preprocessor.cpp b/source/slang/preprocessor.cpp index 4ccb5d50e..91043bcf9 100644 --- a/source/slang/preprocessor.cpp +++ b/source/slang/preprocessor.cpp @@ -842,7 +842,7 @@ top: PathInfo pathInfo = PathInfo::makeTokenPaste(); SourceFile* sourceFile = sourceManager->createSourceFileWithString(pathInfo, sb.ProduceString()); - SourceView* sourceView = sourceManager->createSourceView(sourceFile); + SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr); Lexer lexer; lexer.initialize(sourceView, GetSink(preprocessor), getNamePool(preprocessor), sourceManager->getMemoryArena()); @@ -1627,6 +1627,9 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) return; } + // Simplify the path + filePathInfo.foundPath = includeHandler->simplifyPath(filePathInfo.foundPath); + // Push the new file onto our stack of input streams // TODO(tfoley): check if we have made our include stack too deep auto sourceManager = context->preprocessor->getCompileRequest()->getSourceManager(); @@ -1643,12 +1646,13 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) return; } + sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob); sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile); } // This is a new parse (even if it's a pre-existing source file), so create a new SourceUnit - SourceView* sourceView = sourceManager->createSourceView(sourceFile); + SourceView* sourceView = sourceManager->createSourceView(sourceFile, &filePathInfo); PreprocessorInputStream* inputStream = CreateInputStreamForSource(context->preprocessor, sourceView); inputStream->parent = context->preprocessor->inputStream; @@ -2259,8 +2263,8 @@ static void DefineMacro( SourceFile* keyFile = sourceManager->createSourceFileWithString(pathInfo, key); SourceFile* valueFile = sourceManager->createSourceFileWithString(pathInfo, value); - SourceView* keyView = sourceManager->createSourceView(keyFile); - SourceView* valueView = sourceManager->createSourceView(valueFile); + SourceView* keyView = sourceManager->createSourceView(keyFile, nullptr); + SourceView* valueView = sourceManager->createSourceView(valueFile, nullptr); // Use existing `Lexer` to generate a token stream. Lexer lexer; @@ -2319,7 +2323,7 @@ TokenList preprocessSource( SourceManager* sourceManager = translationUnit->compileRequest->getSourceManager(); - SourceView* sourceView = sourceManager->createSourceView(file); + SourceView* sourceView = sourceManager->createSourceView(file, nullptr); // create an initial input stream based on the provided buffer preprocessor.inputStream = CreateInputStreamForSource(&preprocessor, sourceView); diff --git a/source/slang/preprocessor.h b/source/slang/preprocessor.h index 42a3b25f4..4d02cb50b 100644 --- a/source/slang/preprocessor.h +++ b/source/slang/preprocessor.h @@ -22,6 +22,8 @@ struct IncludeHandler virtual SlangResult readFile(const String& path, ISlangBlob** blobOut) = 0; + + virtual String simplifyPath(const String& path) = 0; }; // Take a string of source code and preprocess it into a list of tokens. diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp index b3ba692bd..d52ea1157 100644 --- a/source/slang/slang-file-system.cpp +++ b/source/slang/slang-file-system.cpp @@ -76,6 +76,13 @@ SlangResult OSFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCan return SLANG_OK; } +SlangResult OSFileSystem::getSimplifiedPath(const char* pathIn, ISlangBlob** outSimplifiedPath) +{ + String simplifiedPath = Path::Simplify(_fixPathDelimiters(pathIn)); + *outSimplifiedPath = StringUtil::createStringBlob(simplifiedPath).detach(); + return SLANG_OK; +} + SlangResult OSFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) { // Don't need to fix delimiters - because combine path handles both path delimiter types @@ -143,9 +150,10 @@ ISlangUnknown* CacheFileSystem::getInterface(const Guid& guid) return _getInterface(this, guid); } -CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode) : +CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle) : m_fileSystem(fileSystem), - m_uniqueIdentityMode(uniqueIdentityMode) + m_uniqueIdentityMode(uniqueIdentityMode), + m_pathStyle(pathStyle) { // Try to get the more sophisticated interface fileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef()); @@ -162,6 +170,17 @@ CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMod default: break; } + if (m_fileSystemExt) + { + // We just defer to the m_fileSystem, so we mark as unknown + m_pathStyle = PathStyle::Unknown; + } + else if (m_pathStyle == PathStyle::Default) + { + // We'll assume it's simplify-able + m_pathStyle = PathStyle::Simplifiable; + } + // It can't be default SLANG_ASSERT(m_uniqueIdentityMode != UniqueIdentityMode::Default); } @@ -286,7 +305,7 @@ CacheFileSystem::PathInfo* CacheFileSystem::_resolveUniqueIdentityCacheInfo(cons // At this point they must have same uniqueIdentity SLANG_ASSERT(pathInfo->getUniqueIdentity() == uniqueIdentity); - // If we have the file contents (because of calcing uniqueIdentity), and there isn't a read fileblob already + // If we have the file contents (because of calc-ing uniqueIdentity), and there isn't a read file blob already // store the data as if read, so doesn't get read again if (fileContents && !pathInfo->m_fileBlob) { @@ -414,6 +433,29 @@ SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* path return toResult(info->m_getPathTypeResult); } +SlangResult CacheFileSystem::getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath) +{ + // If we have a ISlangFileSystemExt we can just pass on the request to it + if (m_fileSystemExt) + { + return m_fileSystemExt->getSimplifiedPath(path, outSimplifiedPath); + } + else + { + // Use the path style to see what we can do with it + switch (m_pathStyle) + { + case PathStyle::Simplifiable: + { + String simplifiedPath = Path::Simplify(_fixPathDelimiters(path)); + *outSimplifiedPath = StringUtil::createStringBlob(simplifiedPath).detach(); + return SLANG_OK; + } + default: return SLANG_E_NOT_IMPLEMENTED; + } + } +} + SlangResult CacheFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) { // If we don't have a backing full file system, we can't produce a canonical path with just ISlangFileSystem::loadFile diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h index e341bf649..a9e92dc1e 100644 --- a/source/slang/slang-file-system.h +++ b/source/slang/slang-file-system.h @@ -40,9 +40,13 @@ public: const char* path, SlangPathType* pathTypeOut) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath( + const char* path, + ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath( const char* path, - ISlangBlob** outCanonicalPath); + ISlangBlob** outCanonicalPath) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL clearCache() {} @@ -71,6 +75,13 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject { public: + enum class PathStyle + { + Default, ///< Pass to say use the default + Unknown, ///< It's an unknown type of path + Simplifiable, ///< It can be simplified by Path::Simplify + }; + enum UniqueIdentityMode { Default, ///< If passed, will default to the others depending on what kind of ISlangFileSystem is passed in @@ -115,6 +126,10 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject const char* path, SlangPathType* outPathType) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath( + const char* path, + ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath( const char* path, ISlangBlob** outCanonicalPath); @@ -122,7 +137,7 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject virtual SLANG_NO_THROW void SLANG_MCALL clearCache(); /// Ctor - CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default); + CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default, PathStyle pathStyle = PathStyle::Default); /// Dtor virtual ~CacheFileSystem(); @@ -178,6 +193,7 @@ protected: Dictionary<String, PathInfo*> m_uniqueIdentityMap; ///< Maps a unique identity for a file to its contents. This OWNs the PathInfo. UniqueIdentityMode m_uniqueIdentityMode; ///< Determines how the 'uniqueIdentity' is produced. Cannot be Default in usage. + PathStyle m_pathStyle; ///< Style of paths ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if nullptr will fall back on the m_fileSystem and emulate all the other methods of ISlangFileSystemExt diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index e332ef588..16dfe8618 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -176,6 +176,17 @@ struct IncludeHandlerImpl : IncludeHandler return SLANG_OK; } + virtual String simplifyPath(const String& path) override + { + ISlangFileSystemExt* fileSystemExt = _getFileSystemExt(); + ComPtr<ISlangBlob> simplifiedPath; + if (SLANG_FAILED(fileSystemExt->getSimplifiedPath(path.Buffer(), simplifiedPath.writeRef()))) + { + return path; + } + return StringUtil::getString(simplifiedPath); + } + }; // diff --git a/source/slang/source-loc.cpp b/source/slang/source-loc.cpp index 6507ea4b7..00b6d3be4 100644 --- a/source/slang/source-loc.cpp +++ b/source/slang/source-loc.cpp @@ -150,16 +150,30 @@ HumaneSourceLoc SourceView::getHumaneLoc(SourceLoc loc, SourceLocType type) pathHandle = entry.m_pathHandle; } - humaneLoc.pathInfo = _getPathInfo(pathHandle); + humaneLoc.pathInfo = _getPathInfoFromHandle(pathHandle); return humaneLoc; } -PathInfo SourceView::_getPathInfo(StringSlicePool::Handle pathHandle) const +PathInfo SourceView::_getPathInfo() const +{ + if (m_viewPath.Length()) + { + PathInfo pathInfo(m_sourceFile->getPathInfo()); + pathInfo.foundPath = m_viewPath; + return pathInfo; + } + else + { + return m_sourceFile->getPathInfo(); + } +} + +PathInfo SourceView::_getPathInfoFromHandle(StringSlicePool::Handle pathHandle) const { // If there is no override path, then just the source files path if (pathHandle == StringSlicePool::Handle(0)) { - return m_sourceFile->getPathInfo(); + return _getPathInfo(); } else { @@ -171,11 +185,11 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) { if (type == SourceLocType::Actual) { - return m_sourceFile->getPathInfo(); + return _getPathInfo(); } const int entryIndex = findEntryIndex(loc); - return _getPathInfo((entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); + return _getPathInfoFromHandle((entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); } /* !!!!!!!!!!!!!!!!!!!!!!! SourceFile !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -418,10 +432,21 @@ SourceFile* SourceManager::createSourceFileWithBlob(const PathInfo& pathInfo, IS return sourceFile; } -SourceView* SourceManager::createSourceView(SourceFile* sourceFile) +SourceView* SourceManager::createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo) { SourceRange range = allocateSourceRange(sourceFile->getContentSize()); - SourceView* sourceView = new SourceView(sourceFile, range); + + SourceView* sourceView = nullptr; + if (pathInfo && + (pathInfo->foundPath.Length() && sourceFile->getPathInfo().foundPath != pathInfo->foundPath)) + { + sourceView = new SourceView(sourceFile, range, &pathInfo->foundPath); + } + else + { + sourceView = new SourceView(sourceFile, range, nullptr); + } + m_sourceViews.Add(sourceView); return sourceView; diff --git a/source/slang/source-loc.h b/source/slang/source-loc.h index aa0623e3d..ad0453d0e 100644 --- a/source/slang/source-loc.h +++ b/source/slang/source-loc.h @@ -194,7 +194,7 @@ public: protected: - SourceManager * m_sourceManager; ///< The source manager this belongs to + SourceManager* m_sourceManager; ///< The source manager this belongs to PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span. ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents UnownedStringSlice m_content; ///< The actual contents of the file. @@ -281,14 +281,24 @@ class SourceView PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); /// Ctor - SourceView(SourceFile* sourceFile, SourceRange range): + SourceView(SourceFile* sourceFile, SourceRange range, const String* viewPath): m_range(range), m_sourceFile(sourceFile) { + if (viewPath) + { + m_viewPath = *viewPath; + } } protected: - PathInfo _getPathInfo(StringSlicePool::Handle pathHandle) const; + /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo + PathInfo _getPathInfoFromHandle(StringSlicePool::Handle pathHandle) const; + /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has been + /// overridden by m_viewPath + PathInfo _getPathInfo() const; + + String m_viewPath; ///< Path to this view. If empty the path is the path to the SourceView SourceRange m_range; ///< The range that this SourceView applies to SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks @@ -315,7 +325,9 @@ struct SourceManager PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); /// Create a new source view from a file - SourceView* createSourceView(SourceFile* sourceFile); + /// @param sourceFile is the source file that contains the source + /// @param pathInfo is path used to read the file from + SourceView* createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo); /// Find a view by a source file location. /// If not found in this manager will look in the parent SourceManager |
