24 using System.Collections.Generic;
31 namespace Ntp.Analyzer.Config.Syntax
41 RequirePath = requirePath;
43 Nodes =
new List<ISyntaxNode>();
44 errors =
new List<string>();
47 private readonly List<string>
errors;
50 protected List<ISyntaxNode> Nodes {
get; }
52 protected string Name {
get; }
56 public bool RequirePath {
get; }
58 public int Line {
get; }
60 public bool HasErrors => errors.Count != 0;
62 public IEnumerable<string> Errors => errors;
73 return Nodes.GetEnumerator();
76 IEnumerator IEnumerable.GetEnumerator()
78 return GetEnumerator();
88 InternalResolve(table);
94 ValidateMandatories();
95 ValidateReferences(table);
100 if (compiledNode == null)
109 return compiledNode ?? (compiledNode = InternalCompile());
112 protected abstract T InternalCompile();
114 #region Validation methods 152 #region Validation helpers 154 protected void CheckTypeIs<TU>(
Symbol symbol)
157 foreach (var node
in Nodes.Where(n => n.Symbol == symbol))
163 var
b =
new StringBuilder();
166 b.Append(
"Error in line ");
170 b.Append(
"Value of setting ");
172 b.Append(
" must be ");
173 b.Append(
new TU().SettingValue);
174 errors.Add(b.ToString());
178 protected void CheckTypeIs<TU, TV>(
Symbol symbol)
179 where TU : SettingNode,
new()
180 where TV : SettingNode, new()
182 foreach (var node
in Nodes.Where(n => n.Symbol == symbol))
184 if (node is TU || node is TV)
188 var
b =
new StringBuilder();
191 b.Append(
"Error in line ");
195 b.Append(
"Value of setting ");
197 b.Append(
" must be ");
198 b.Append(
new TU().SettingValue);
200 b.Append(
new TV().SettingValue);
201 errors.Add(b.ToString());
208 Where(item => Nodes.Count(n => n.Symbol == item) == 0).
211 if (missing.Count == 0)
216 int count = missing.Count;
217 var
b =
new StringBuilder();
221 b.Append(
"Error in line ");
226 b.Append(
" section is missing the setting");
227 b.Append(missing.Count > 1 ?
"s: " :
": ");
229 foreach (var item
in missing)
233 if (i == count - 1 && count > 1)
247 errors.Add(
b.ToString());
252 var symbols = list as IList<Symbol> ?? list.ToList();
253 var
set =
new HashSet<Symbol>(symbols);
255 if (Nodes.Any(node =>
set.Contains(node.Symbol)))
260 int count = symbols.Count;
261 var
b =
new StringBuilder();
265 b.Append(
"Error in line ");
270 b.Append(
" section must contain at least one of the setting");
271 b.Append(count > 1 ?
"s: " :
": ");
273 foreach (var item
in symbols)
291 errors.Add(
b.ToString());
296 var symbols = list.ToList();
297 var
set =
new HashSet<Symbol>(symbols);
299 int a = Nodes.Count(node =>
set.Contains(node.Symbol));
306 int count = symbols.Count;
307 var
b =
new StringBuilder();
311 b.Append(
"Error in line ");
316 b.Append(
" section can only contain one of the setting");
317 b.Append(count > 1 ?
"s: " :
": ");
319 foreach (var item
in symbols)
337 errors.Add(
b.ToString());
344 let
c = Nodes.Count(n => n.Symbol == symbol)
349 if (nonUniques.Count == 0)
354 int count = nonUniques.Count;
355 var
b =
new StringBuilder();
359 b.Append(
"Error in line ");
364 b.Append(
" section has multiple occurrences of the setting");
365 b.Append(count > 1 ?
"s: " :
": ");
367 foreach (var item
in nonUniques)
385 errors.Add(
b.ToString());
394 string text = link.TrimStart();
396 if ((text.StartsWith(
"http://") ||
397 text.StartsWith(
"https://") ||
398 text.StartsWith(
"ftp://") ||
399 text.StartsWith(
"mailto:") ||
400 text.StartsWith(
"javascript:")) &&
401 Uri.TryCreate(link, UriKind.Absolute, out uri))
404 if (Uri.TryCreate(
"/" + link.TrimStart(
'/'), UriKind.Relative, out uri))
407 if (Uri.TryCreate(link, UriKind.Absolute, out uri))
411 var
b =
new StringBuilder();
414 b.Append(
"Error in line ");
418 b.Append($
"{keyword} {name} is not a wellformed link.");
419 AddError(b.ToString());
426 #region Error message helpers 430 var
b =
new StringBuilder();
433 b.Append(
"Error in line ");
437 b.Append($
"{keyword} {name} refers to a nonexistent section.");
438 AddError(b.ToString());
443 var
b =
new StringBuilder();
446 b.Append(
"Error in line ");
450 b.Append($
"{keyword} {name} does not refer to a {section} section.");
451 AddError(b.ToString());
IEnumerator< ISyntaxNode > GetEnumerator()
void CheckOneIsPresent(IEnumerable< Symbol > list)
void AddReferenceTypeError(ISyntaxNode node, string keyword, string section, string name)
Uri CheckLink(string link, string keyword)
SyntaxNode(Symbol symbol, string name, int line, bool requirePath=false)
void CheckOnlyOneIsPresent(IEnumerable< Symbol > list)
static Keyword Find(Symbol symbol)
void Assemble(ISyntaxNode node)
void CheckAllIsPresent(IEnumerable< Symbol > list)
virtual void InternalResolve(SymbolTable table)
Override to resolve references to other syntax nodes from this syntax node.
void Add(ISyntaxNode node)
void Resolve(SymbolTable table)
virtual void ValidateReferences(SymbolTable table)
Override to validates the references in this syntax node.
virtual void ValidateMandatories()
Override to validates the mandatory types in this syntax node.
virtual void ValidateTypes()
Override to validates the types in this syntax node.
void CheckIsUnique(IEnumerable< Symbol > list)
void Validate(SymbolTable table)
void AddReferenceNameError(ISyntaxNode node, string keyword, string name)
void AddError(string message)
ConfigurationNode CompiledNode
readonly List< string > errors