diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2023-04-20 13:42:20 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-20 13:42:20 -0400 |
| commit | 088644c21c015eb60a41a59f417990023f1f4ef8 (patch) | |
| tree | 596d224f99e35dcd3d66507cfe297bc25407336d /source | |
| parent | 4e67cdedbef8f643c90b48172d5419d3dd1839db (diff) | |
Improve SourceMap coverage/testing (#2818)
* #include an absolute path didn't work - because paths were taken to always be relative.
* WIP around more value like behavior for SourceMap/StringPool.
* Use default impls on SourceMap ctor/assignment.
* Handle comparison of SourceMaps.
Some small fixes.
Expand unit tests.
Diffstat (limited to 'source')
| -rw-r--r-- | source/compiler-core/slang-json-source-map-util.cpp | 12 | ||||
| -rw-r--r-- | source/compiler-core/slang-source-map.cpp | 99 | ||||
| -rw-r--r-- | source/compiler-core/slang-source-map.h | 24 | ||||
| -rw-r--r-- | source/core/slang-string-slice-pool.cpp | 94 | ||||
| -rw-r--r-- | source/core/slang-string-slice-pool.h | 12 |
5 files changed, 238 insertions, 3 deletions
diff --git a/source/compiler-core/slang-json-source-map-util.cpp b/source/compiler-core/slang-json-source-map-util.cpp index 193c812b7..30d722c4c 100644 --- a/source/compiler-core/slang-json-source-map-util.cpp +++ b/source/compiler-core/slang-json-source-map-util.cpp @@ -209,6 +209,7 @@ void _encode(Index v, StringBuilder& out) cur = StringSlicePool::kNullHandle; } + // Special case sourcesContent, because needs to be able to handle null or string for (Index i = 0; i < sourcesContentCount; ++i) { auto value = native.sourcesContent[i]; @@ -223,6 +224,17 @@ void _encode(Index v, StringBuilder& out) } } + // Copy over the names + { + const auto namesCount = native.names.getCount(); + outSourceMap.m_names.setCount(namesCount); + + for (Index i = 0; i < namesCount; ++i) + { + outSourceMap.m_names[i] = outSourceMap.m_slicePool.add(native.names[i]); + } + } + List<UnownedStringSlice> lines; StringUtil::split(native.mappings, ';', lines); diff --git a/source/compiler-core/slang-source-map.cpp b/source/compiler-core/slang-source-map.cpp index 7a6e368a4..43727838f 100644 --- a/source/compiler-core/slang-source-map.cpp +++ b/source/compiler-core/slang-source-map.cpp @@ -35,6 +35,105 @@ void SourceMap::swapWith(ThisType& rhs) m_slicePool.swapWith(rhs.m_slicePool); } +static bool _areEqual(const List<StringSlicePool::Handle>& a, const List<StringSlicePool::Handle>& b, const List<Index>& bToAMap) +{ + const auto count = a.getCount(); + if (count != b.getCount()) + { + return false; + } + + const auto* as = a.getBuffer(); + const auto* bs = a.getBuffer(); + + for (Index i = 0; i < count; ++i) + { + if (StringSlicePool::asIndex(as[i]) != bToAMap[StringSlicePool::asIndex(bs[i])]) + { + return false; + } + } + + return true; +} + +static bool _areEqual(const SourceMap::Entry& a, const SourceMap::Entry& b, const List<Index>& bToAMap) +{ + return a.generatedColumn == b.generatedColumn && + a.sourceLine == b.sourceLine && + a.sourceColumn == b.sourceColumn && + a.sourceFileIndex == bToAMap[b.sourceFileIndex] && + a.nameIndex == bToAMap[b.nameIndex]; +} + +static bool _areEqual(const List<SourceMap::Entry>& a, const List<SourceMap::Entry>&b, const List<Index>& bToAMap) +{ + const auto count = a.getCount(); + if (count != b.getCount()) + { + return false; + } + + for (Index i = 0; i < count; ++i) + { + if (!_areEqual(a[i], b[i], bToAMap)) + { + return false; + } + } + + return true; +} + +bool SourceMap::operator==(const ThisType& rhs) const +{ + if (this == &rhs) + { + return true; + } + + if (m_file != rhs.m_file || + m_sourceRoot != rhs.m_sourceRoot || + m_lineStarts != rhs.m_lineStarts) + { + return false; + } + + if (m_slicePool == rhs.m_slicePool) + { + // If the slice pools are the same we can just compare indices directly + return m_sources == rhs.m_sources && + m_sourcesContent == rhs.m_sourcesContent && + m_names == rhs.m_names && + m_lineEntries == rhs.m_lineEntries; + } + else + { + // Otherwise we need to remap the indices + // Maps a pool handle from the rhs source map to the + List<Index> rhsMap; + + Count count = rhs.m_slicePool.getSlicesCount(); + + rhsMap.setCount(count); + + const auto startIndex = rhs.m_slicePool.getFirstAddedIndex(); + + // Work out the map + for (Index i = 0; i < startIndex; ++i) + { + const auto rhsSlice = rhs.m_slicePool.getSlice(StringSlicePool::Handle(i)); + rhsMap[i] = (i < startIndex) ? i : m_slicePool.findIndex(rhsSlice); + } + + // Do the comparison taking into account the mapping. + return _areEqual(m_sources, rhs.m_sources, rhsMap) && + _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) && + _areEqual(m_names, rhs.m_names, rhsMap) && + _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap); + } +} + void SourceMap::advanceToLine(Index nextLineIndex) { const Count currentLineIndex = getGeneratedLineCount() - 1; diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h index e0c8d065a..0c55d3a1a 100644 --- a/source/compiler-core/slang-source-map.h +++ b/source/compiler-core/slang-source-map.h @@ -19,6 +19,8 @@ public: struct Entry { + typedef Entry ThisType; + void init() { generatedColumn = 0; @@ -28,6 +30,16 @@ public: nameIndex = 0; } + bool operator==(const ThisType& rhs) const + { + return generatedColumn == rhs.generatedColumn && + sourceFileIndex == rhs.sourceFileIndex && + sourceLine == rhs.sourceLine && + sourceColumn == rhs.sourceColumn && + nameIndex == rhs.nameIndex; + } + SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + // Note! All column/line are zero indexed Index generatedColumn; ///< The generated column Index sourceFileIndex; ///< The index into the source name/contents @@ -71,12 +83,24 @@ public: /// Swap this with rhs void swapWith(ThisType& rhs); + /// == + /// + /// Note that equality requires that entries for a line must be *in the same order* + /// even though strictly speaking with different orders could be considered equivalent. + bool operator==(const ThisType& rhs) const; + /// != + bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + /// Ctor SourceMap(): m_slicePool(StringSlicePool::Style::Default) { clear(); } + /// Copy Ctor + SourceMap(const ThisType& rhs) = default; + /// Assignment + ThisType& operator=(const ThisType& rhs) = default; String m_file; String m_sourceRoot; diff --git a/source/core/slang-string-slice-pool.cpp b/source/core/slang-string-slice-pool.cpp index 45cc811a3..5c4c7f61f 100644 --- a/source/core/slang-string-slice-pool.cpp +++ b/source/core/slang-string-slice-pool.cpp @@ -14,9 +14,103 @@ StringSlicePool::StringSlicePool(Style style) : clear(); } +StringSlicePool::StringSlicePool(const ThisType& rhs): + m_style(rhs.m_style), + m_arena(1024) +{ + // Set with rhs + _set(rhs); +} + +void StringSlicePool::operator=(const ThisType& rhs) +{ + if (&rhs != this) + { + _set(rhs); + } +} + +void StringSlicePool::_set(const ThisType& rhs) +{ + SLANG_ASSERT(this != &rhs); + m_style = rhs.m_style; + + clear(); + + const Index startIndex = rhs.getFirstAddedIndex(); + const Count count = rhs.m_slices.getCount(); + + // We need the same amount of slices + m_slices.setCount(count); + + // Work out the total size to store all slices including terminating 0 + // (which *isn't* part of the slice size) + size_t totalSize = 0; + + for (Index i = startIndex; i < count; ++i) + { + const auto slice = rhs.m_slices[i]; + totalSize += slice.getLength() + 1; + } + + char* dst = (char*)m_arena.allocate(totalSize); + + for (Index i = startIndex; i < count; ++i) + { + const auto srcSlice = rhs.m_slices[i]; + const auto sliceSize = srcSlice.getLength(); + + // Copy over the src slices contents + ::memcpy(dst, srcSlice.begin(), sliceSize); + // Zero terminate + dst[sliceSize] = 0; + + const UnownedStringSlice dstSlice(dst, sliceSize); + // Set the slice + m_slices[i] = dstSlice; + + // Add to the map + m_map.Add(dstSlice, Handle(i)); + + // Skip to next slices storage + dst += sliceSize + 1; + } +} + +bool StringSlicePool::operator==(const ThisType& rhs) const +{ + if (this == &rhs) + { + return true; + } + + if (m_style != rhs.m_style) + { + return false; + } + + const auto count = m_slices.getCount(); + + if (count != rhs.m_slices.getCount()) + { + return false; + } + + for (Index i = 0; i < count; ++i) + { + if (m_slices[i] != rhs.m_slices[i]) + { + return false; + } + } + + return true; +} + void StringSlicePool::clear() { m_map.Clear(); + m_arena.deallocateAll(); switch (m_style) { diff --git a/source/core/slang-string-slice-pool.h b/source/core/slang-string-slice-pool.h index 90586a527..843556296 100644 --- a/source/core/slang-string-slice-pool.h +++ b/source/core/slang-string-slice-pool.h @@ -102,13 +102,19 @@ public: /// Swap this with rhs void swapWith(ThisType& rhs); + /// True if the pools are identical. Same style, same slices in the same order. + bool operator==(const ThisType& rhs) const; + + /// Copy ctor + StringSlicePool(const ThisType& rhs); + /// Assignment + void operator=(const ThisType& rhs); + /// Ctor explicit StringSlicePool(Style style); protected: - // Disable copy ctor and assignment - StringSlicePool(const ThisType& rhs) = delete; - void operator=(const ThisType& rhs) = delete; + void _set(const ThisType& rhs); Style m_style; List<UnownedStringSlice> m_slices; |
