summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/compiler.cpp21
-rw-r--r--source/slang/compiler.h4
-rw-r--r--source/slang/diagnostic-defs.h2
-rw-r--r--source/slang/diagnostics.cpp60
-rw-r--r--source/slang/diagnostics.h15
-rw-r--r--source/slang/ir-serialize.cpp2
-rw-r--r--source/slang/options.cpp4
-rw-r--r--source/slang/preprocessor.cpp37
-rw-r--r--source/slang/slang-file-system.cpp185
-rw-r--r--source/slang/slang-file-system.h79
-rw-r--r--source/slang/slang.cpp89
-rw-r--r--source/slang/source-loc.cpp59
-rw-r--r--source/slang/source-loc.h55
13 files changed, 386 insertions, 226 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index a003cf33d..29f7a95d9 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -473,6 +473,18 @@ namespace Slang
sink->diagnoseRaw(SLANG_FAILED(res) ? Severity::Error : Severity::Warning, builder.getUnownedSlice());
}
+ static String _getDisplayPath(const DiagnosticSink& sink, SourceFile* sourceFile)
+ {
+ if (sink.flags & DiagnosticSink::Flag::VerbosePath)
+ {
+ return sourceFile->calcVerbosePath();
+ }
+ else
+ {
+ return sourceFile->getPathInfo().foundPath;
+ }
+ }
+
String calcTranslationUnitSourcePath(TranslationUnitRequest* translationUnitRequest)
{
CompileRequest* compileRequest = translationUnitRequest->compileRequest;
@@ -481,6 +493,8 @@ namespace Slang
return "slang-generated";
}
+ auto& sink = translationUnitRequest->compileRequest->mSink;
+
const auto& sourceFiles = translationUnitRequest->sourceFiles;
const int numSourceFiles = int(sourceFiles.Count());
@@ -488,16 +502,15 @@ namespace Slang
switch (numSourceFiles)
{
case 0: return "unknown";
- case 1: return sourceFiles[0]->getPathInfo().foundPath;
+ case 1: return _getDisplayPath(sink, sourceFiles[0]);
default:
{
StringBuilder builder;
- builder << sourceFiles[0]->getPathInfo().foundPath;
+ builder << _getDisplayPath(sink, sourceFiles[0]);
for (int i = 1; i < numSourceFiles; ++i)
{
- builder << ";" << sourceFiles[i]->getPathInfo().foundPath;
+ builder << ";" << _getDisplayPath(sink, sourceFiles[i]);
}
-
return builder;
}
}
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index 41ba027c6..ca82950be 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -399,7 +399,7 @@ namespace Slang
// This is a list of unique modules loaded, in the order they were encountered.
List<RefPtr<LoadedModule> > loadedModulesList;
- // Map from the path of a module file to its definition
+ // Map from the path (or uniqueIdentity if available) of a module file to its definition
Dictionary<String, RefPtr<LoadedModule>> mapPathToLoadedModule;
// Map from the logical name of a module to its definition
@@ -509,6 +509,8 @@ namespace Slang
mSink.sourceManager = sm;
}
+ void setFileSystem(ISlangFileSystem* fileSystem);
+
/// During propagation of an exception for an internal
/// error, note that this source location was involved
void noteInternalErrorLoc(SourceLoc const& loc);
diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h
index a7c89321d..ceb4706fd 100644
--- a/source/slang/diagnostic-defs.h
+++ b/source/slang/diagnostic-defs.h
@@ -149,7 +149,7 @@ DIAGNOSTIC(-1, Note, seeOpeningToken, "see opening '$0'")
DIAGNOSTIC(15300, Error, includeFailed, "failed to find include file '$0'")
DIAGNOSTIC(15301, Error, importFailed, "failed to find imported file '$0'")
DIAGNOSTIC(-1, Error, noIncludeHandlerSpecified, "no `#include` handler was specified")
-DIAGNOSTIC(15302, Error, noCanonicalPath, "`#include` handler didn't generate a canonical path for '$0'")
+DIAGNOSTIC(15302, Error, noUniqueIdentity, "`#include` handler didn't generate a unique identity for file '$0'")
// 154xx - macro definition
diff --git a/source/slang/diagnostics.cpp b/source/slang/diagnostics.cpp
index 9a88c041d..00205fed3 100644
--- a/source/slang/diagnostics.cpp
+++ b/source/slang/diagnostics.cpp
@@ -199,30 +199,54 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a
}
}
+static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& diagnostic, StringBuilder& outBuilder)
+{
+ outBuilder << humaneLoc.pathInfo.foundPath;
+ outBuilder << "(";
+ outBuilder << Int32(humaneLoc.line);
+ outBuilder << "): ";
+
+ outBuilder << getSeverityName(diagnostic.severity);
+
+ if (diagnostic.ErrorID >= 0)
+ {
+ outBuilder << " ";
+ outBuilder << diagnostic.ErrorID;
+ }
+
+ outBuilder << ": ";
+ outBuilder << diagnostic.Message;
+ outBuilder << "\n";
+}
+
static void formatDiagnostic(
DiagnosticSink* sink,
- StringBuilder& sb,
- Diagnostic const& diagnostic)
+ Diagnostic const& diagnostic,
+ StringBuilder& sb)
{
auto sourceManager = sink->sourceManager;
- auto humaneLoc = sourceManager->getHumaneLoc(diagnostic.loc);
-
- sb << humaneLoc.pathInfo.foundPath;
- sb << "(";
- sb << Int32(humaneLoc.line);
- sb << "): ";
- sb << getSeverityName(diagnostic.severity);
-
- if( diagnostic.ErrorID >= 0 )
+ SourceView* sourceView = nullptr;
+ HumaneSourceLoc humaneLoc;
+ const auto sourceLoc = diagnostic.loc;
{
- sb << " ";
- sb << diagnostic.ErrorID;
+ sourceView = sourceManager->findSourceViewRecursively(sourceLoc);
+ if (sourceView)
+ {
+ humaneLoc = sourceView->getHumaneLoc(sourceLoc);
+ }
+ formatDiagnostic(humaneLoc, diagnostic, sb);
}
+
+ if (sourceView && (sink->flags & DiagnosticSink::Flag::VerbosePath))
+ {
+ auto actualLoc = sourceView->getHumaneLoc(diagnostic.loc, SourceLocType::Actual);
+ // Look up the full path
+ SourceFile* sourceFile = sourceView->getSourceFile();
+ actualLoc.pathInfo.foundPath = sourceFile->calcVerbosePath();
- sb << ": ";
- sb << diagnostic.Message;
- sb << "\n";
+ formatDiagnostic(actualLoc, diagnostic, sb);
+ }
}
void DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& info, int argCount, DiagnosticArg const* const* args)
@@ -246,7 +270,7 @@ void DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& in
{
// If so, pass the error string along to them
StringBuilder messageBuilder;
- formatDiagnostic(this, messageBuilder, diagnostic);
+ formatDiagnostic(this, diagnostic, messageBuilder);
writer->write(messageBuilder.Buffer(), messageBuilder.Length());
}
@@ -254,7 +278,7 @@ void DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& in
{
// If the user doesn't have a callback, then just
// collect our diagnostic messages into a buffer
- formatDiagnostic(this, outputBuffer, diagnostic);
+ formatDiagnostic(this, diagnostic, outputBuffer);
}
if (diagnostic.severity >= Severity::Fatal)
diff --git a/source/slang/diagnostics.h b/source/slang/diagnostics.h
index 8e5bbcb64..fed492bc7 100644
--- a/source/slang/diagnostics.h
+++ b/source/slang/diagnostics.h
@@ -141,12 +141,23 @@ namespace Slang
// The source manager to use when mapping source locations to file+line info
SourceManager* sourceManager;
+ struct Flag
+ {
+ enum Enum: uint32_t
+ {
+ VerbosePath = 0x1, ///< Will try and display a
+ };
+ };
+ typedef uint32_t Flags;
+
StringBuilder outputBuffer;
// List<Diagnostic> diagnostics;
int errorCount = 0;
- ISlangWriter* writer = nullptr;
+ ISlangWriter* writer = nullptr;
+ Flags flags = 0;
+
/*
void Error(int id, const String & msg, const SourceLoc & pos)
{
@@ -163,7 +174,7 @@ namespace Slang
void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info)
{
- diagnoseImpl(pos, info, 0, NULL);
+ diagnoseImpl(pos, info, 0, nullptr);
}
void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info, DiagnosticArg const& arg0)
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index 61b21f1ef..4ff7cd733 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -2005,7 +2005,7 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
RefPtr<IRModule> irReadModule;
SourceManager workSourceManager;
- workSourceManager.initialize(sourceManager);
+ workSourceManager.initialize(sourceManager, nullptr);
{
IRSerialReader reader;
diff --git a/source/slang/options.cpp b/source/slang/options.cpp
index b87e19e46..8a4cf35b7 100644
--- a/source/slang/options.cpp
+++ b/source/slang/options.cpp
@@ -456,6 +456,10 @@ struct OptionsParser
{
requestImpl->useSerialIRBottleneck = true;
}
+ else if (argStr == "-verbose-paths")
+ {
+ requestImpl->mSink.flags |= DiagnosticSink::Flag::VerbosePath;
+ }
else if (argStr == "-verify-debug-serial-ir")
{
requestImpl->verifyDebugSerialization = true;
diff --git a/source/slang/preprocessor.cpp b/source/slang/preprocessor.cpp
index c038737b7..4ccb5d50e 100644
--- a/source/slang/preprocessor.cpp
+++ b/source/slang/preprocessor.cpp
@@ -197,10 +197,9 @@ struct Preprocessor
// The translation unit that is being parsed
TranslationUnitRequest* translationUnit;
- // Any paths that have issued `#pragma once` directives to
+ // The unique identities of any paths that have issued `#pragma once` directives to
// stop them from being included again.
- HashSet<String> pragmaOncePaths;
-
+ HashSet<String> pragmaOnceUniqueIdentities;
TranslationUnitRequest* getTranslationUnit()
{
@@ -1610,10 +1609,10 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
return;
}
- // We must have a canonical path to be compare
- if (!filePathInfo.hasCanonicalPath())
+ // We must have a uniqueIdentity to be compare
+ if (!filePathInfo.hasUniqueIdentity())
{
- GetSink(context)->diagnose(pathToken.loc, Diagnostics::noCanonicalPath, path);
+ GetSink(context)->diagnose(pathToken.loc, Diagnostics::noUniqueIdentity, path);
return;
}
@@ -1623,7 +1622,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
expectEndOfDirective(context);
// Check whether we've previously included this file and seen a `#pragma once` directive
- if(context->preprocessor->pragmaOncePaths.Contains(filePathInfo.canonicalPath))
+ if(context->preprocessor->pragmaOnceUniqueIdentities.Contains(filePathInfo.uniqueIdentity))
{
return;
}
@@ -1633,7 +1632,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
auto sourceManager = context->preprocessor->getCompileRequest()->getSourceManager();
// See if this an already loaded source file
- SourceFile* sourceFile = sourceManager->findSourceFileRecursively(filePathInfo.canonicalPath);
+ SourceFile* sourceFile = sourceManager->findSourceFileRecursively(filePathInfo.uniqueIdentity);
// If not create a new one, and add to the list of known source files
if (!sourceFile)
{
@@ -1645,7 +1644,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
}
sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob);
- sourceManager->addSourceFile(filePathInfo.canonicalPath, sourceFile);
+ sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile);
}
// This is a new parse (even if it's a pre-existing source file), so create a new SourceUnit
@@ -1873,29 +1872,19 @@ SLANG_PRAGMA_DIRECTIVE_CALLBACK(handlePragmaOnceDirective)
// We need to identify the path of the file we are preprocessing,
// so that we can avoid including it again.
//
- // Note: for now we are doing a very simplistic check where
- // we use the raw file path as the key for our duplicate checking.
- //
- // TODO: a more refined implementation should probably apply Unicode
- // normalization and case-folding to the path, and then use that
- // plus a hash of the file contents to determine whether things
- // represent the "same" file.
- //
- // TODO: even for our simplistic implementation, we need to add
- // logic to deal with `../` segments in path names to detect
- // trivial cases of the "same" path.
- //
+ // We are using the 'uniqueIdentity' as determined by the ISlangFileSystemEx interface to determine file identities.
+
auto directiveLoc = GetDirectiveLoc(context);
auto issuedFromPathInfo = context->preprocessor->translationUnit->compileRequest->getSourceManager()->getPathInfo(directiveLoc, SourceLocType::Actual);
- // Must have a canonical path for a #pragma once to work
- if (!issuedFromPathInfo.hasCanonicalPath())
+ // Must have uniqueIdentity for a #pragma once to work
+ if (!issuedFromPathInfo.hasUniqueIdentity())
{
GetSink(context)->diagnose(subDirectiveToken, Diagnostics::pragmaOnceIgnored);
return;
}
- context->preprocessor->pragmaOncePaths.Add(issuedFromPathInfo.canonicalPath);
+ context->preprocessor->pragmaOnceUniqueIdentities.Add(issuedFromPathInfo.uniqueIdentity);
}
// Information about a specific `#pragma` directive
diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp
index 96dcc7558..b3ba692bd 100644
--- a/source/slang/slang-file-system.cpp
+++ b/source/slang/slang-file-system.cpp
@@ -62,12 +62,17 @@ static String _fixPathDelimiters(const char* pathIn)
#endif
}
-SlangResult OSFileSystem::getCanoncialPath(const char* pathIn, ISlangBlob** canonicalPathOut)
+SlangResult OSFileSystem::getFileUniqueIdentity(const char* pathIn, ISlangBlob** outUniqueIdentity)
+{
+ // By default we use the canonical path to uniquely identify a file
+ return getCanonicalPath(pathIn, outUniqueIdentity);
+}
+
+SlangResult OSFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath)
{
String canonicalPath;
- SLANG_RETURN_ON_FAIL(Path::GetCanonical(_fixPathDelimiters(pathIn), canonicalPath));
-
- *canonicalPathOut = StringUtil::createStringBlob(canonicalPath).detach();
+ SLANG_RETURN_ON_FAIL(Path::GetCanonical(_fixPathDelimiters(path), canonicalPath));
+ *outCanonicalPath = StringUtil::createStringBlob(canonicalPath).detach();
return SLANG_OK;
}
@@ -138,44 +143,61 @@ ISlangUnknown* CacheFileSystem::getInterface(const Guid& guid)
return _getInterface(this, guid);
}
-CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, CanonicalMode canonicalMode) :
+CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode) :
m_fileSystem(fileSystem),
- m_canonicalMode(canonicalMode)
+ m_uniqueIdentityMode(uniqueIdentityMode)
{
// Try to get the more sophisticated interface
fileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef());
- switch (canonicalMode)
+ switch (uniqueIdentityMode)
{
- case CanonicalMode::Default:
- case CanonicalMode::FileSystemExt:
+ case UniqueIdentityMode::Default:
+ case UniqueIdentityMode::FileSystemExt:
{
- m_canonicalMode = m_fileSystemExt ? CanonicalMode::FileSystemExt : CanonicalMode::SimplifyPathAndHash;
+ // If it's not a complete file system, we will default to SimplifyAndHash style by default
+ m_uniqueIdentityMode = m_fileSystemExt ? UniqueIdentityMode::FileSystemExt : UniqueIdentityMode::SimplifyPathAndHash;
break;
}
default: break;
}
// It can't be default
- SLANG_ASSERT(m_canonicalMode != CanonicalMode::Default);
+ SLANG_ASSERT(m_uniqueIdentityMode != UniqueIdentityMode::Default);
}
CacheFileSystem::~CacheFileSystem()
{
- for (const auto& pair : m_canonicalMap)
+ for (const auto& pair : m_uniqueIdentityMap)
{
delete pair.Value;
}
}
+void CacheFileSystem::clearCache()
+{
+ for (const auto& pair : m_uniqueIdentityMap)
+ {
+ delete pair.Value;
+ }
+
+ m_uniqueIdentityMap.Clear();
+ m_pathMap.Clear();
+
+ if (m_fileSystemExt)
+ {
+ m_fileSystemExt->clearCache();
+ }
+}
+
// Determines if we can simplify a path for a given mode
-static bool _canSimplifyPath(CacheFileSystem::CanonicalMode mode)
+static bool _canSimplifyPath(CacheFileSystem::UniqueIdentityMode mode)
{
- typedef CacheFileSystem::CanonicalMode CanonicalMode;
+ typedef CacheFileSystem::UniqueIdentityMode UniqueIdentityMode;
switch (mode)
{
- case CanonicalMode::SimplifyPath:
- case CanonicalMode::SimplifyPathAndHash:
+ case UniqueIdentityMode::SimplifyPath:
+ case UniqueIdentityMode::SimplifyPathAndHash:
{
return true;
}
@@ -186,33 +208,32 @@ static bool _canSimplifyPath(CacheFileSystem::CanonicalMode mode)
}
}
-SlangResult CacheFileSystem::_calcCanonicalPath(const String& path, String& outCanonicalPath, ComPtr<ISlangBlob>& outFileContents)
+SlangResult CacheFileSystem::_calcUniqueIdentity(const String& path, String& outUniqueIdentity, ComPtr<ISlangBlob>& outFileContents)
{
- switch (m_canonicalMode)
+ switch (m_uniqueIdentityMode)
{
- case CanonicalMode::FileSystemExt:
+ case UniqueIdentityMode::FileSystemExt:
{
- // Try getting the canonical path
- // Okay request from the underlying file system the canonical path
- ComPtr<ISlangBlob> canonicalBlob;
- SLANG_RETURN_ON_FAIL(m_fileSystemExt->getCanoncialPath(path.Buffer(), canonicalBlob.writeRef()));
+ // Try getting the uniqueIdentity by asking underlying file system
+ ComPtr<ISlangBlob> uniqueIdentity;
+ SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(path.Buffer(), uniqueIdentity.writeRef()));
// Get the path as a string
- outCanonicalPath = StringUtil::getString(canonicalBlob);
+ outUniqueIdentity = StringUtil::getString(uniqueIdentity);
return SLANG_OK;
}
- case CanonicalMode::Path:
+ case UniqueIdentityMode::Path:
{
- outCanonicalPath = path;
+ outUniqueIdentity = path;
return SLANG_OK;
}
- case CanonicalMode::SimplifyPath:
+ case UniqueIdentityMode::SimplifyPath:
{
- outCanonicalPath = Path::Simplify(path);
+ outUniqueIdentity = Path::Simplify(path);
// If it still has relative elements can't uniquely identify, so give up
- return Path::IsRelative(outCanonicalPath) ? SLANG_FAIL : SLANG_OK;
+ return Path::IsRelative(outUniqueIdentity) ? SLANG_FAIL : SLANG_OK;
}
- case CanonicalMode::SimplifyPathAndHash:
- case CanonicalMode::Hash:
+ case UniqueIdentityMode::SimplifyPathAndHash:
+ case UniqueIdentityMode::Hash:
{
// I can only see if this is the same file as already loaded by loading the file and doing a hash
Result res = m_fileSystem->loadFile(path.Buffer(), outFileContents.writeRef());
@@ -229,10 +250,10 @@ SlangResult CacheFileSystem::_calcCanonicalPath(const String& path, String& outC
hashString.append(':');
- // The canonical name is.. combination of name and hash
+ // The uniqueIdentity is a combination of name and hash
hashString.append(hash, 16);
- outCanonicalPath = hashString;
+ outUniqueIdentity = hashString;
return SLANG_OK;
}
}
@@ -240,32 +261,32 @@ SlangResult CacheFileSystem::_calcCanonicalPath(const String& path, String& outC
return SLANG_FAIL;
}
-CacheFileSystem::PathInfo* CacheFileSystem::_getOrCreateCanonicalCacheInfo(const String& path)
+CacheFileSystem::PathInfo* CacheFileSystem::_resolveUniqueIdentityCacheInfo(const String& path)
{
- // Use the path to produce canonicalPath information
+ // Use the path to produce uniqueIdentity information
ComPtr<ISlangBlob> fileContents;
- String canonicalPath;
+ String uniqueIdentity;
- SlangResult res = _calcCanonicalPath(path, canonicalPath, fileContents);
+ SlangResult res = _calcUniqueIdentity(path, uniqueIdentity, fileContents);
if (SLANG_FAILED(res))
{
- // Was not able to create a canonical path.. so mark in path map the problem
+ // Was not able to create a uniqueIdentity - return failure as nullptr
return nullptr;
}
- // Now try looking up by canonical path. If not found, add a new result
+ // Now try looking up by uniqueIdentity path. If not found, add a new result
PathInfo* pathInfo = nullptr;
- if (!m_canonicalMap.TryGetValue(canonicalPath, pathInfo))
+ if (!m_uniqueIdentityMap.TryGetValue(uniqueIdentity, pathInfo))
{
- // Create with found canonicalPath
- pathInfo = new PathInfo(canonicalPath);
- m_canonicalMap.Add(canonicalPath, pathInfo);
+ // Create with found uniqueIdentity
+ pathInfo = new PathInfo(uniqueIdentity);
+ m_uniqueIdentityMap.Add(uniqueIdentity, pathInfo);
}
- // At this point they must have same canonicalPath
- SLANG_ASSERT(pathInfo->getCanonicalPath() == canonicalPath);
+ // At this point they must have same uniqueIdentity
+ SLANG_ASSERT(pathInfo->getUniqueIdentity() == uniqueIdentity);
- // If we have the file contents (because of calcing canonical), and there isn't a read fileblob already
+ // If we have the file contents (because of calcing uniqueIdentity), and there isn't a read fileblob already
// store the data as if read, so doesn't get read again
if (fileContents && !pathInfo->m_fileBlob)
{
@@ -276,24 +297,24 @@ CacheFileSystem::PathInfo* CacheFileSystem::_getOrCreateCanonicalCacheInfo(const
return pathInfo;
}
-CacheFileSystem::PathInfo* CacheFileSystem::_getOrCreateSimplifiedPathCacheInfo(const String& path)
+CacheFileSystem::PathInfo* CacheFileSystem::_resolveSimplifiedPathCacheInfo(const String& path)
{
// If we can simplify the path, try looking up in path cache with simplified path (as long as it's different!)
- if (_canSimplifyPath(m_canonicalMode))
+ if (_canSimplifyPath(m_uniqueIdentityMode))
{
const String simplifiedPath = Path::Simplify(path);
// Only lookup if the path is different - because otherwise will recurse forever...
if (simplifiedPath != path)
{
// This is a recursive call - and will ensure the simplified path is added to the cache
- return _getOrCreatePathCacheInfo(simplifiedPath);
+ return _resolvePathCacheInfo(simplifiedPath);
}
}
- return _getOrCreateCanonicalCacheInfo(path);
+ return _resolveUniqueIdentityCacheInfo(path);
}
-CacheFileSystem::PathInfo* CacheFileSystem::_getOrCreatePathCacheInfo(const String& path)
+CacheFileSystem::PathInfo* CacheFileSystem::_resolvePathCacheInfo(const String& path)
{
// Lookup in path cache
PathInfo* pathInfo;
@@ -304,7 +325,7 @@ CacheFileSystem::PathInfo* CacheFileSystem::_getOrCreatePathCacheInfo(const Stri
}
// Try getting or creating taking into account possible path simplification
- pathInfo = _getOrCreateSimplifiedPathCacheInfo(path);
+ pathInfo = _resolveSimplifiedPathCacheInfo(path);
// Always add the result to the path cache (even if null)
m_pathMap.Add(path, pathInfo);
return pathInfo;
@@ -314,7 +335,7 @@ SlangResult CacheFileSystem::loadFile(char const* pathIn, ISlangBlob** blobOut)
{
*blobOut = nullptr;
String path(pathIn);
- PathInfo* info = _getOrCreatePathCacheInfo(path);
+ PathInfo* info = _resolvePathCacheInfo(path);
if (!info)
{
return SLANG_FAIL;
@@ -333,15 +354,15 @@ SlangResult CacheFileSystem::loadFile(char const* pathIn, ISlangBlob** blobOut)
return toResult(info->m_loadFileResult);
}
-SlangResult CacheFileSystem::getCanoncialPath(const char* path, ISlangBlob** canonicalPathOut)
+SlangResult CacheFileSystem::getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity)
{
- PathInfo* info = _getOrCreatePathCacheInfo(path);
+ PathInfo* info = _resolvePathCacheInfo(path);
if (!info)
{
return SLANG_E_NOT_FOUND;
}
- info->m_canonicalPath->addRef();
- *canonicalPathOut = info->m_canonicalPath;
+ info->m_uniqueIdentity->addRef();
+ *outUniqueIdentity = info->m_uniqueIdentity;
return SLANG_OK;
}
@@ -362,7 +383,7 @@ SlangResult CacheFileSystem::calcCombinedPath(SlangPathType fromPathType, const
SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* pathTypeOut)
{
String path(pathIn);
- PathInfo* info = _getOrCreatePathCacheInfo(path);
+ PathInfo* info = _resolvePathCacheInfo(path);
if (!info)
{
return SLANG_E_NOT_FOUND;
@@ -393,4 +414,52 @@ SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* path
return toResult(info->m_getPathTypeResult);
}
+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
+ if (!m_fileSystemExt)
+ {
+ return SLANG_E_NOT_IMPLEMENTED;
+ }
+
+ // A file must exist to get a canonical path...
+ PathInfo* info = _resolvePathCacheInfo(path);
+ if (!info)
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+
+ // We don't have this -> so read it ...
+ if (info->m_getCanonicalPathResult == CompressedResult::Uninitialized)
+ {
+ // Try getting the canonicalPath by asking underlying file system
+ ComPtr<ISlangBlob> canonicalPathBlob;
+ SlangResult res = m_fileSystemExt->getCanonicalPath(path, canonicalPathBlob.writeRef());
+
+ if (SLANG_SUCCEEDED(res))
+ {
+ // Get the path as a string
+ String canonicalPath = StringUtil::getString(canonicalPathBlob);
+ if (canonicalPath.Length() > 0)
+ {
+ info->m_canonicalPath = new StringBlob(canonicalPath);
+ }
+ else
+ {
+ res = SLANG_FAIL;
+ }
+ }
+
+ // Save the result
+ info->m_getCanonicalPathResult = toCompressedResult(res);
+ }
+
+ if (info->m_canonicalPath)
+ {
+ info->m_canonicalPath->addRef();
+ }
+ *outCanonicalPath = info->m_canonicalPath;
+ return SLANG_OK;
+}
+
}
diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h
index 94d89b58b..e341bf649 100644
--- a/source/slang/slang-file-system.h
+++ b/source/slang/slang-file-system.h
@@ -26,9 +26,9 @@ public:
ISlangBlob** outBlob) SLANG_OVERRIDE;
// ISlangFileSystemExt
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanoncialPath(
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(
const char* path,
- ISlangBlob** canonicalPathOut) SLANG_OVERRIDE;
+ ISlangBlob** uniqueIdentityOut) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
SlangPathType fromPathType,
@@ -40,6 +40,12 @@ public:
const char* path,
SlangPathType* pathTypeOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(
+ const char* path,
+ ISlangBlob** outCanonicalPath);
+
+ virtual SLANG_NO_THROW void SLANG_MCALL clearCache() {}
+
/// Get a default instance
static ISlangFileSystemExt* getSingleton() { return &s_singleton; }
@@ -59,16 +65,13 @@ of the interface on the constructor.
NOTE! That this behavior is the same as previously in that....
1) calcRelativePath, just returns the path as processed by the Path:: methods
-2) getCanonicalPath, just returns the input path as the 'canonical' path. This will be wrong with a file multiply referenced through paths with .. and or . but
-doing it this way means it works as before and requires no new functions.
-
-You can use a more sophisticated canonical style if you pass true to useSimplifyForCanonicalPath. This will simplify relative path to create a canonical path.
+2) getUniqueIdentity behavior depends on the UniqueIdentityMode.
*/
class CacheFileSystem: public ISlangFileSystemExt, public RefObject
{
public:
- enum CanonicalMode
+ enum UniqueIdentityMode
{
Default, ///< If passed, will default to the others depending on what kind of ISlangFileSystem is passed in
Path, ///< Just use the path as is (old style slang behavior)
@@ -98,9 +101,9 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject
ISlangBlob** outBlob) SLANG_OVERRIDE;
// ISlangFileSystemExt
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanoncialPath(
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(
const char* path,
- ISlangBlob** canonicalPathOut) SLANG_OVERRIDE;
+ ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
SlangPathType fromPathType,
@@ -110,10 +113,16 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(
const char* path,
- SlangPathType* pathTypeOut) SLANG_OVERRIDE;
+ SlangPathType* outPathType) SLANG_OVERRIDE;
+
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(
+ const char* path,
+ ISlangBlob** outCanonicalPath);
+
+ virtual SLANG_NO_THROW void SLANG_MCALL clearCache();
/// Ctor
- CacheFileSystem(ISlangFileSystem* fileSystem, CanonicalMode canonicalMode = CanonicalMode::Default);
+ CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default);
/// Dtor
virtual ~CacheFileSystem();
@@ -126,52 +135,52 @@ protected:
struct PathInfo
{
- PathInfo(const String& canonicalPath)
+ PathInfo(const String& uniqueIdentity)
{
- m_canonicalPath = new StringBlob(canonicalPath);
- m_canonicalPath->addRef();
+ m_uniqueIdentity = new StringBlob(uniqueIdentity);
+ m_uniqueIdentity->addRef();
m_loadFileResult = CompressedResult::Uninitialized;
m_getPathTypeResult = CompressedResult::Uninitialized;
+ m_getCanonicalPathResult = CompressedResult::Uninitialized;
m_pathType = SLANG_PATH_TYPE_FILE;
}
- ~PathInfo()
- {
- m_canonicalPath->release();
- }
- /// Get the canonical path as a string
- const String& getCanonicalPath() const { SLANG_ASSERT(m_canonicalPath); return m_canonicalPath->getString(); }
+
+ /// Get the unique identity path as a string
+ const String& getUniqueIdentity() const { SLANG_ASSERT(m_uniqueIdentity); return m_uniqueIdentity->getString(); }
- StringBlob* m_canonicalPath; ///< The canonical path
+ RefPtr<StringBlob> m_uniqueIdentity;
CompressedResult m_loadFileResult;
- CompressedResult m_getPathTypeResult;
+ CompressedResult m_getPathTypeResult;
+ CompressedResult m_getCanonicalPathResult;
+
SlangPathType m_pathType;
ComPtr<ISlangBlob> m_fileBlob;
+ RefPtr<StringBlob> m_canonicalPath;
};
- /// Given a path works out a canonical path, based on the canonicalMode. outFileContents will be set if file had to be read to produce the canonicalPath (ie with Hash)
- SlangResult _calcCanonicalPath(const String& path, String& outCanonicalPath, ComPtr<ISlangBlob>& outFileContents);
-
+ /// Given a path, works out a uniqueIdentity, based on the uniqueIdentityMode. outFileContents will be set if file had to be read to produce the uniqueIdentity (ie with Hash)
+ SlangResult _calcUniqueIdentity(const String& path, String& outUniqueIdentity, ComPtr<ISlangBlob>& outFileContents);
/// For a given path gets a PathInfo. Can return nullptr, if it is not possible to create the PathInfo for some reason
- PathInfo* _getOrCreatePathCacheInfo(const String& path);
- /// Turns the path into a canonical path, and then tries to look up in the canonicalPathMap.
- PathInfo* _getOrCreateCanonicalCacheInfo(const String& path);
- /// Will simplify the path (if possible) to lookup on the pathCache else will create on canonicalCache
- PathInfo* _getOrCreateSimplifiedPathCacheInfo(const String& path);
+ PathInfo* _resolvePathCacheInfo(const String& path);
+ /// Turns the path into a uniqueIdentity, and then tries to look up in the uniqueIdentityMap.
+ PathInfo* _resolveUniqueIdentityCacheInfo(const String& path);
+ /// Will simplify the path (if possible) to lookup on the pathCache else will create on uniqueIdentityMap
+ PathInfo* _resolveSimplifiedPathCacheInfo(const String& path);
/* TODO: This may be improved by mapping to a ISlangBlob. This makes output fast and easy, and if constructed
as a StringBlob, we can just static_cast to get as a string to use internally, instead of constantly converting.
It is probably the case we cannot do dynamic_cast on ISlangBlob if we don't know where constructed -> if outside of slang codebase
doing such a cast can cause an exception. So we *never* want to do dynamic cast from blobs which could be created by external code. */
- Dictionary<String, PathInfo*> m_pathMap; ///< Maps a path to a canonical path
- Dictionary<String, PathInfo*> m_canonicalMap; ///< Maps a canonical path to a files contents. This OWNs the PathInfo.
+ Dictionary<String, PathInfo*> m_pathMap; ///< Maps a path to a PathInfo (and unique identity)
+ Dictionary<String, PathInfo*> m_uniqueIdentityMap; ///< Maps a unique identity for a file to its contents. This OWNs the PathInfo.
- CanonicalMode m_canonicalMode; ///< Determines how 'canonicalPath' is produced. Cannot be Default in usage.
+ UniqueIdentityMode m_uniqueIdentityMode; ///< Determines how the 'uniqueIdentity' is produced. Cannot be Default in usage.
- ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set
- ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if not will fall back on the m_fileSystem
+ 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 247098434..359848d65 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -58,7 +58,7 @@ Session::Session()
#include "object-meta-end.h"
// Make sure our source manager is initialized
- builtinSourceManager.initialize(nullptr);
+ builtinSourceManager.initialize(nullptr, nullptr);
// Initialize representations of some very basic types:
initializeTypes();
@@ -117,21 +117,21 @@ struct IncludeHandlerImpl : IncludeHandler
return SLANG_E_NOT_FOUND;
}
- // Get the canonical path
- ComPtr<ISlangBlob> canonicalPathBlob;
- SLANG_RETURN_ON_FAIL(fileSystemExt->getCanoncialPath(combinedPath.begin(), canonicalPathBlob.writeRef()));
+ // Get the uniqueIdentity
+ ComPtr<ISlangBlob> uniqueIdentityBlob;
+ SLANG_RETURN_ON_FAIL(fileSystemExt->getFileUniqueIdentity(combinedPath.begin(), uniqueIdentityBlob.writeRef()));
- // If the rel path exists -> the canonical path MUST exists too
- String canonicalPath(StringUtil::getString(canonicalPathBlob));
- if (canonicalPath.Length() <= 0)
+ // If the rel path exists -> a uniqueIdentity MUST exists too
+ String uniqueIdentity(StringUtil::getString(uniqueIdentityBlob));
+ if (uniqueIdentity.Length() <= 0)
{
- // Canonical path can't be empty
+ // Unique identity can't be empty
return SLANG_FAIL;
}
pathInfoOut.type = PathInfo::Type::Normal;
pathInfoOut.foundPath = combinedPath;
- pathInfoOut.canonicalPath = canonicalPath;
+ pathInfoOut.uniqueIdentity = uniqueIdentity;
return SLANG_OK;
}
@@ -306,7 +306,7 @@ CompileRequest::CompileRequest(Session* session)
setSourceManager(&sourceManagerStorage);
- sourceManager->initialize(session->getBuiltinSourceManager());
+ sourceManager->initialize(session->getBuiltinSourceManager(), nullptr);
// Set all the default writers
for (int i = 0; i < int(WriterChannel::CountOf); ++i)
@@ -314,9 +314,7 @@ CompileRequest::CompileRequest(Session* session)
setWriter(WriterChannel(i), nullptr);
}
- // Set up the default file system
- SLANG_ASSERT(fileSystem == nullptr);
- fileSystemExt = new CacheFileSystem(OSFileSystem::getSingleton());
+ setFileSystem(nullptr);
}
// Allocate static const storage for the various interface IDs that the Slang API needs to expose
@@ -419,7 +417,7 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio
{
// Create a SourceManager on the stack, so any allocations for 'SourceFile'/'SourceView' etc will be cleaned up
SourceManager localSourceManager;
- localSourceManager.initialize(sourceManager);
+ localSourceManager.initialize(sourceManager, nullptr);
Slang::SourceFile* srcFile = localSourceManager.createSourceFileWithString(PathInfo::makeTypeParse(), typeStr);
@@ -859,10 +857,10 @@ void CompileRequest::loadParsedModule(
RefPtr<LoadedModule> loadedModule = new LoadedModule();
// Get a path
- String mostUniquePath = pathInfo.getMostUniquePath();
- SLANG_ASSERT(mostUniquePath.Length() > 0);
+ String mostUniqueIdentity = pathInfo.getMostUniqueIdentity();
+ SLANG_ASSERT(mostUniqueIdentity.Length() > 0);
- mapPathToLoadedModule.Add(mostUniquePath, loadedModule);
+ mapPathToLoadedModule.Add(mostUniqueIdentity, loadedModule);
mapNameToLoadedModules.Add(name, loadedModule);
int errorCountBefore = mSink.GetErrorCount();
@@ -985,7 +983,7 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
PathInfo pathIncludedFromInfo = getSourceManager()->getPathInfo(loc, SourceLocType::Actual);
PathInfo filePathInfo;
- // We are going to allow canonicalPath to be able to hold strings other than paths (like hashes), therefore we have to load via the found path
+ // We have to load via the found path - as that is how file was originally loaded
if (SLANG_FAILED(includeHandler.findFile(fileName, pathIncludedFromInfo.foundPath, filePathInfo)))
{
this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName);
@@ -994,7 +992,7 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
}
// Maybe this was loaded previously at a different relative name?
- if (mapPathToLoadedModule.TryGetValue(filePathInfo.getMostUniquePath(), loadedModule))
+ if (mapPathToLoadedModule.TryGetValue(filePathInfo.getMostUniqueIdentity(), loadedModule))
return loadedModule->moduleDecl;
// Try to load it
@@ -1047,6 +1045,34 @@ void CompileRequest::noteInternalErrorLoc(SourceLoc const& loc)
internalErrorLocsNoted++;
}
+static const Slang::Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt;
+
+void CompileRequest::setFileSystem(ISlangFileSystem* inFileSystem)
+{
+ // Set the fileSystem
+ fileSystem = inFileSystem;
+
+ // Set up fileSystemExt appropriately
+ if (inFileSystem == nullptr)
+ {
+ fileSystemExt = new Slang::CacheFileSystem(Slang::OSFileSystem::getSingleton());
+ }
+ else
+ {
+ // See if we have the interface
+ inFileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)fileSystemExt.writeRef());
+
+ // If not wrap with WrapFileSytem that keeps the old behavior
+ if (!fileSystemExt)
+ {
+ // Construct a wrapper to emulate the extended interface behavior
+ fileSystemExt = new Slang::CacheFileSystem(fileSystem);
+ }
+ }
+
+ // Set the file system used on the source manager
+ sourceManager->setFileSystemExt(fileSystemExt);
+}
RefPtr<ModuleDecl> findOrImportModule(
CompileRequest* request,
@@ -1236,35 +1262,12 @@ 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 = new Slang::CacheFileSystem(Slang::OSFileSystem::getSingleton());
- }
- 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::CacheFileSystem(fileSystem);
- }
- }
+ REQ(request)->setFileSystem(fileSystem);
}
SLANG_API void spSetCompileFlags(
diff --git a/source/slang/source-loc.cpp b/source/slang/source-loc.cpp
index 78477bb78..6507ea4b7 100644
--- a/source/slang/source-loc.cpp
+++ b/source/slang/source-loc.cpp
@@ -9,11 +9,11 @@ namespace Slang {
/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceView !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-const String PathInfo::getMostUniquePath() const
+const String PathInfo::getMostUniqueIdentity() const
{
switch (type)
{
- case Type::Normal: return canonicalPath;
+ case Type::Normal: return uniqueIdentity;
case Type::FoundPath: return foundPath;
default: return "";
}
@@ -89,7 +89,7 @@ void SourceView::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handl
void SourceView::addLineDirective(SourceLoc directiveLoc, const String& path, int line)
{
- StringSlicePool::Handle pathHandle = m_sourceManager->getStringSlicePool().add(path.getUnownedSlice());
+ StringSlicePool::Handle pathHandle = getSourceManager()->getStringSlicePool().add(path.getUnownedSlice());
return addLineDirective(directiveLoc, pathHandle, line);
}
@@ -163,8 +163,7 @@ PathInfo SourceView::_getPathInfo(StringSlicePool::Handle pathHandle) const
}
else
{
- // We don't have a full normal path (including 'canonical') so just go with FoundPath
- return PathInfo::makePath(m_sourceManager->getStringSlicePool().getSlice(pathHandle));
+ return PathInfo::makePath(getSourceManager()->getStringSlicePool().getSlice(pathHandle));
}
}
@@ -295,7 +294,8 @@ void SourceFile::setContents(const String& content)
setContents(contentBlob);
}
-SourceFile::SourceFile(const PathInfo& pathInfo, size_t contentSize) :
+SourceFile::SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize) :
+ m_sourceManager(sourceManager),
m_pathInfo(pathInfo),
m_contentSize(contentSize)
{
@@ -303,14 +303,37 @@ SourceFile::SourceFile(const PathInfo& pathInfo, size_t contentSize) :
SourceFile::~SourceFile()
{
+}
+
+String SourceFile::calcVerbosePath() const
+{
+ ISlangFileSystemExt* fileSystemExt = getSourceManager()->getFileSystemExt();
+ if (fileSystemExt)
+ {
+ String canonicalPath;
+ ComPtr<ISlangBlob> canonicalPathBlob;
+ if (SLANG_SUCCEEDED(fileSystemExt->getCanonicalPath(m_pathInfo.foundPath.Buffer(), canonicalPathBlob.writeRef())))
+ {
+ canonicalPath = StringUtil::getString(canonicalPathBlob);
+ }
+ if (canonicalPath.Length() > 0)
+ {
+ return canonicalPath;
+ }
+ }
+
+ return m_pathInfo.foundPath;
}
/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
void SourceManager::initialize(
- SourceManager* p)
+ SourceManager* p,
+ ISlangFileSystemExt* fileSystemExt)
{
+ m_fileSystemExt = fileSystemExt;
+
m_parent = p;
if( p )
@@ -374,14 +397,14 @@ SourceRange SourceManager::allocateSourceRange(UInt size)
SourceFile* SourceManager::createSourceFileWithSize(const PathInfo& pathInfo, size_t contentSize)
{
- SourceFile* sourceFile = new SourceFile(pathInfo, contentSize);
+ SourceFile* sourceFile = new SourceFile(this, pathInfo, contentSize);
m_sourceFiles.Add(sourceFile);
return sourceFile;
}
SourceFile* SourceManager::createSourceFileWithString(const PathInfo& pathInfo, const String& contents)
{
- SourceFile* sourceFile = new SourceFile(pathInfo, contents.Length());
+ SourceFile* sourceFile = new SourceFile(this, pathInfo, contents.Length());
m_sourceFiles.Add(sourceFile);
sourceFile->setContents(contents);
return sourceFile;
@@ -389,7 +412,7 @@ SourceFile* SourceManager::createSourceFileWithString(const PathInfo& pathInfo,
SourceFile* SourceManager::createSourceFileWithBlob(const PathInfo& pathInfo, ISlangBlob* blob)
{
- SourceFile* sourceFile = new SourceFile(pathInfo, blob->getBufferSize());
+ SourceFile* sourceFile = new SourceFile(this, pathInfo, blob->getBufferSize());
m_sourceFiles.Add(sourceFile);
sourceFile->setContents(blob);
return sourceFile;
@@ -398,7 +421,7 @@ SourceFile* SourceManager::createSourceFileWithBlob(const PathInfo& pathInfo, IS
SourceView* SourceManager::createSourceView(SourceFile* sourceFile)
{
SourceRange range = allocateSourceRange(sourceFile->getContentSize());
- SourceView* sourceView = new SourceView(this, sourceFile, range);
+ SourceView* sourceView = new SourceView(sourceFile, range);
m_sourceViews.Add(sourceView);
return sourceView;
@@ -479,18 +502,18 @@ SourceView* SourceManager::findSourceViewRecursively(SourceLoc loc) const
return nullptr;
}
-SourceFile* SourceManager::findSourceFile(const String& canonicalPath) const
+SourceFile* SourceManager::findSourceFile(const String& uniqueIdentity) const
{
- SourceFile*const* filePtr = m_sourceFileMap.TryGetValue(canonicalPath);
+ SourceFile*const* filePtr = m_sourceFileMap.TryGetValue(uniqueIdentity);
return (filePtr) ? *filePtr : nullptr;
}
-SourceFile* SourceManager::findSourceFileRecursively(const String& canonicalPath) const
+SourceFile* SourceManager::findSourceFileRecursively(const String& uniqueIdentity) const
{
const SourceManager* manager = this;
do
{
- SourceFile* sourceFile = manager->findSourceFile(canonicalPath);
+ SourceFile* sourceFile = manager->findSourceFile(uniqueIdentity);
if (sourceFile)
{
return sourceFile;
@@ -500,10 +523,10 @@ SourceFile* SourceManager::findSourceFileRecursively(const String& canonicalPath
return nullptr;
}
-void SourceManager::addSourceFile(const String& canonicalPath, SourceFile* sourceFile)
+void SourceManager::addSourceFile(const String& uniqueIdentity, SourceFile* sourceFile)
{
- SLANG_ASSERT(!findSourceFileRecursively(canonicalPath));
- m_sourceFileMap.Add(canonicalPath, sourceFile);
+ SLANG_ASSERT(!findSourceFileRecursively(uniqueIdentity));
+ m_sourceFileMap.Add(uniqueIdentity, sourceFile);
}
HumaneSourceLoc SourceManager::getHumaneLoc(SourceLoc loc, SourceLocType type)
diff --git a/source/slang/source-loc.h b/source/slang/source-loc.h
index ee4049473..aa0623e3d 100644
--- a/source/slang/source-loc.h
+++ b/source/slang/source-loc.h
@@ -44,32 +44,32 @@ struct PathInfo
enum class Type
{
Unknown, ///< The path is not known
- Normal, ///< Normal has both path and canonical path
- FoundPath, ///< Just has a found path (canonical path is unknown, or even 'unknowable')
+ Normal, ///< Normal has both path and uniqueIdentity
+ FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable')
TokenPaste, ///< No paths, just created to do a macro expansion
TypeParse, ///< No path, just created to do a type parse
CommandLine, ///< A macro constructed from the command line
};
/// True if has a canonical path
- SLANG_FORCE_INLINE bool hasCanonicalPath() const { return type == Type::Normal && canonicalPath.Length() > 0; }
+ SLANG_FORCE_INLINE bool hasUniqueIdentity() const { return type == Type::Normal && uniqueIdentity.Length() > 0; }
/// True if has a regular found path
SLANG_FORCE_INLINE bool hasFoundPath() const { return type == Type::Normal || type == Type::FoundPath; }
- /// The canonical path is unique, so return that if we have it. If not the regular path, otherwise the empty string.
- const String getMostUniquePath() const;
+ /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, else the foundPath, else "".
+ const String getMostUniqueIdentity() const;
// So simplify construction. In normal usage it's safer to use make methods over constructing directly.
static PathInfo makeUnknown() { return PathInfo { Type::Unknown, "unknown", String() }; }
static PathInfo makeTokenPaste() { return PathInfo{ Type::TokenPaste, "token paste", String()}; }
- static PathInfo makeNormal(const String& foundPathIn, const String& canonicalPathIn) { SLANG_ASSERT(canonicalPathIn.Length() > 0 && foundPathIn.Length() > 0); return PathInfo { Type::Normal, foundPathIn, canonicalPathIn }; }
+ static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) { SLANG_ASSERT(uniqueIdentity.Length() > 0 && foundPathIn.Length() > 0); return PathInfo { Type::Normal, foundPathIn, uniqueIdentity }; }
static PathInfo makePath(const String& pathIn) { SLANG_ASSERT(pathIn.Length() > 0); return PathInfo { Type::FoundPath, pathIn, String()}; }
static PathInfo makeTypeParse() { return PathInfo { Type::TypeParse, "type string", String() }; }
static PathInfo makeCommandLine() { return PathInfo { Type::CommandLine, "command line", String() }; }
Type type; ///< The type of path
String foundPath; ///< The path where the file was found (might contain relative elements)
- String canonicalPath; ///< Canonical version of the found path
+ String uniqueIdentity; ///< The unique identity of the file on the path found
};
class SourceLoc
@@ -139,6 +139,9 @@ struct SourceRange
SourceLoc end;
};
+// Pre-declare
+struct SourceManager;
+
// A logical or physical storage object for a range of input code
// that has logically contiguous source locations.
class SourceFile
@@ -178,13 +181,20 @@ public:
/// Set the content as a string
void setContents(const String& content);
+ /// Calculate a display path -> can canonicalize if necessary
+ String calcVerbosePath() const;
+
+ /// Get the source manager this was created on
+ SourceManager* getSourceManager() const { return m_sourceManager; }
+
/// Ctor
- SourceFile(const PathInfo& pathInfo, size_t contentSize);
+ SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize);
/// Dtor
~SourceFile();
protected:
+ 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.
@@ -210,8 +220,6 @@ struct HumaneSourceLoc
Int column = 0;
};
-// Pre-declare
-struct SourceManager;
/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or more precisely use of a source file.
It is distinct from a SourceFile - because a SourceFile may be included multiple times, with different interpretations (depending
@@ -257,7 +265,7 @@ class SourceView
/// Get the source file holds the contents this view
SourceFile* getSourceFile() const { return m_sourceFile; }
/// Get the source manager
- SourceManager* getSourceManager() const { return m_sourceManager; }
+ SourceManager* getSourceManager() const { return m_sourceFile->getSourceManager(); }
/// Get the associated 'content' (the source text)
const UnownedStringSlice& getContent() const { return m_sourceFile->getContent(); }
@@ -273,8 +281,7 @@ class SourceView
PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal);
/// Ctor
- SourceView(SourceManager* sourceManager, SourceFile* sourceFile, SourceRange range):
- m_sourceManager(sourceManager),
+ SourceView(SourceFile* sourceFile, SourceRange range):
m_range(range),
m_sourceFile(sourceFile)
{
@@ -283,7 +290,6 @@ class SourceView
protected:
PathInfo _getPathInfo(StringSlicePool::Handle pathHandle) const;
- SourceManager* m_sourceManager; /// Get the manager this belongs to
SourceRange m_range; ///< The range that this SourceView applies to
SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks
List<Entry> m_entries; ///< An array entries describing how we should interpret a range, starting from the start location.
@@ -292,7 +298,7 @@ class SourceView
struct SourceManager
{
// Initialize a source manager, with an optional parent
- void initialize(SourceManager* parent);
+ void initialize(SourceManager* parent, ISlangFileSystemExt* fileSystemExt);
/// Allocate a range of SourceLoc locations, these can be used to identify a specific location in the source
SourceRange allocateSourceRange(UInt size);
@@ -322,12 +328,17 @@ struct SourceManager
/// Searches this manager, and then the parent to see if can find a match for path.
/// If not found returns nullptr.
- SourceFile* findSourceFileRecursively(const String& canonicalPath) const;
+ SourceFile* findSourceFileRecursively(const String& uniqueIdentity) const;
/// Find if the source file is defined on this manager.
- SourceFile* findSourceFile(const String& canonicalPath) const;
+ SourceFile* findSourceFile(const String& uniqueIdentity) const;
- /// Add a source file, path must be unique for this manager AND any parents
- void addSourceFile(const String& canonicalPath, SourceFile* sourceFile);
+ /// Get the file system associated with this source manager
+ ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; }
+ /// Get the file system associated with this source manager
+ void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; }
+
+ /// Add a source file, uniqueIdentity must be unique for this manager AND any parents
+ void addSourceFile(const String& uniqueIdentity, SourceFile* sourceFile);
/// Get the slice pool
StringSlicePool& getStringSlicePool() { return m_slicePool; }
@@ -374,8 +385,10 @@ struct SourceManager
// Can be used for storing the decoded contents of Token. Content for example.
MemoryArena m_memoryArena;
- // Maps canonical paths to source files
- Dictionary<String, SourceFile*> m_sourceFileMap;
+ // Maps uniqueIdentities to source files
+ Dictionary<String, SourceFile*> m_sourceFileMap;
+
+ ComPtr<ISlangFileSystemExt> m_fileSystemExt;
};
} // namespace Slang