summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-diagnostics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-diagnostics.cpp')
-rw-r--r--source/slang/slang-diagnostics.cpp141
1 files changed, 123 insertions, 18 deletions
diff --git a/source/slang/slang-diagnostics.cpp b/source/slang/slang-diagnostics.cpp
index a46e0515b..d16e8e84e 100644
--- a/source/slang/slang-diagnostics.cpp
+++ b/source/slang/slang-diagnostics.cpp
@@ -3,6 +3,9 @@
#include "slang-name.h"
+#include "../core/slang-memory-arena.h"
+#include "../core/slang-dictionary.h"
+
#include <assert.h>
#ifdef _WIN32
@@ -268,34 +271,136 @@ void DiagnosticSink::diagnoseRaw(
namespace Diagnostics
{
-#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, messageFormat };
+#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat };
#include "slang-diagnostic-defs.h"
+#undef DIAGNOSTIC
}
-DiagnosticInfo const* findDiagnosticByName(UnownedStringSlice const& name)
+static const DiagnosticInfo* const kAllDiagnostics[] =
{
- // TODO: We should eventually have a more formal system for associating individual
- // diagnostics, or groups of diagnostics, with user-exposed names for use when
- // enabling/disabling warnings (or turning warnings into errors, etc.).
- //
- // For now we build an ad hoc mapping from string names to corresponding single
- // diagnostics (not groups).
- //
- static const struct
+#define DIAGNOSTIC(id, severity, name, messageFormat) &Diagnostics::name,
+#include "slang-diagnostic-defs.h"
+#undef DIAGNOSTIC
+};
+
+class DiagnosticsLookup : public RefObject
+{
+public:
+ const DiagnosticInfo* findDiagostic(const UnownedStringSlice& slice) const
+ {
+ const Index* indexPtr = m_map.TryGetValue(slice);
+ return indexPtr ? kAllDiagnostics[*indexPtr] : nullptr;
+ }
+ Index _findDiagnosticIndex(const UnownedStringSlice& slice) const
{
- char const* name;
- DiagnosticInfo const* diagnostic;
- } kDiagnostics[] =
+ const Index* indexPtr = m_map.TryGetValue(slice);
+ return indexPtr ? *indexPtr : 0;
+ }
+ static DiagnosticsLookup* getSingleton()
+ {
+ static RefPtr<DiagnosticsLookup> singleton = new DiagnosticsLookup;
+ return singleton;
+ }
+
+ typedef uint8_t CharFlags;
+ struct CharFlag
{
- { "overlapping-bindings", &Diagnostics::parameterBindingsOverlap },
+ enum Enum : CharFlags
+ {
+ Upper = 0x1,
+ Lower = 0x2,
+ };
};
- for( auto& entry : kDiagnostics )
+ static CharFlags _classifyChar(char c)
+ {
+ CharFlags flags = 0;
+ flags |= (c >= 'a' && c <= 'z') ? CharFlag::Lower : 0;
+ flags |= (c >= 'A' && c <= 'Z') ? CharFlag::Upper : 0;
+ return flags;
+ }
+protected:
+ void _add(const char* name, Index index)
+ {
+ m_map.Add(UnownedStringSlice(name), index);
+
+ // Add a dashed version
+ {
+ m_work.Clear();
+
+ CharFlags prevFlags = 0;
+ for (const char* cur = name; *cur; cur++)
+ {
+ char c = *cur;
+ const CharFlags flags = _classifyChar(c);
+
+ if (flags & CharFlag::Upper)
+ {
+ if (prevFlags & CharFlag::Lower)
+ {
+ // If we go from lower to upper, insert a dash. aA -> a-a
+ m_work << '-';
+ }
+ else if (prevFlags & CharFlag::Upper)
+ {
+ // Could be an acronym, if the next character is lower, we need to insert a - here
+ if (_classifyChar(cur[1]) & CharFlag::Lower)
+ {
+ m_work << '-';
+ }
+ }
+ // Make it lower
+ c = c - 'A' + 'a';
+ }
+ m_work << c;
+
+ prevFlags = flags;
+ }
+
+ UnownedStringSlice dashSlice(m_arena.allocateString(m_work.getBuffer(), m_work.getLength()), m_work.getLength());
+ m_map.AddIfNotExists(dashSlice, index);
+ }
+ }
+ void _addAlias(const char* name, const char* diagnosticName)
+ {
+ const Index index = _findDiagnosticIndex(UnownedStringSlice(diagnosticName));
+ SLANG_ASSERT(index >= 0);
+ if (index >= 0)
+ {
+ _add(name, index);
+ }
+ }
+ DiagnosticsLookup();
+
+ StringBuilder m_work;
+ Dictionary<UnownedStringSlice, Index> m_map;
+ MemoryArena m_arena;
+};
+
+DiagnosticsLookup::DiagnosticsLookup():
+ m_arena(2048)
+{
+ // TODO: We should eventually have a more formal system for associating individual
+ // diagnostics, or groups of diagnostics, with user-exposed names for use when
+ // enabling/disabling warnings (or turning warnings into errors, etc.).
+ //
+ // For now we build a map from diagnostic name to it's entry. Two entries are typically
+ // added - the 'original name' as associated with the diagnostic in lowerCamel, and
+ // a dashified version.
+
+ for (Index i = 0; i < SLANG_COUNT_OF(kAllDiagnostics); ++i)
{
- if( name == entry.name )
- return entry.diagnostic;
+ const DiagnosticInfo* diagnostic = kAllDiagnostics[i];
+ _add(diagnostic->name, i);
}
- return nullptr;
+
+ // Add any aliases
+ _addAlias("overlappingBindings", "parameterBindingsOverlap");
+}
+
+DiagnosticInfo const* findDiagnosticByName(UnownedStringSlice const& name)
+{
+ return DiagnosticsLookup::getSingleton()->findDiagostic(name);
}