From 82fd4fdc0a7e0ffb2976ea63d3da5a7a5ec0b506 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 17 Apr 2025 14:56:47 +0700 Subject: [PATCH 1/4] Enabled NRT from some files. WIP. Pushing for assessment --- src/CSTools/Tools/Tools.csproj | 1 + src/CSTools/Tools/dfa.cs | 18 ++--- src/CSTools/Tools/genbase.cs | 4 +- src/CSTools/Tools/lexer.cs | 44 ++++++----- src/CSTools/Tools/olist.cs | 4 +- src/CSTools/Tools/parser.cs | 76 +++++++++---------- src/CSTools/Tools/serialise.cs | 22 +++--- src/CSTools/lg/lg.csproj | 1 + src/CSTools/pg/pg.csproj | 1 + src/SIL.LCModel.Build.Tasks/CellarModule.cs | 4 +- src/SIL.LCModel.Build.Tasks/Class.cs | 60 ++++++++------- src/SIL.LCModel.Build.Tasks/DummyClass.cs | 4 +- src/SIL.LCModel.Build.Tasks/IClass.cs | 4 +- .../LcmGenerateImpl.cs | 10 ++- src/SIL.LCModel.Core/Cellar/GenDate.cs | 6 +- .../Phonology/PhonEnv.lexer.cs | 4 +- .../Phonology/PhonEnvRecognizer.cs | 20 ++--- .../Phonology/phonenv.parser.cs | 72 +++++++++--------- src/SIL.LCModel.Core/Scripture/BCVRef.cs | 26 ++++--- .../Scripture/ScriptureUtilsException.cs | 14 ++-- .../SpellChecking/SpellEngine.cs | 8 +- .../SpellChecking/SpellingHelper.cs | 4 +- src/SIL.LCModel.Core/Text/StringSearcher.cs | 6 +- src/SIL.LCModel.Core/Text/TsPropsFactory.cs | 4 +- src/SIL.LCModel.Core/Text/TsStringComparer.cs | 6 +- .../Text/TsStringSerializer.cs | 6 +- src/SIL.LCModel.Core/Text/TsStringUtils.cs | 4 +- src/SIL.LCModel.Utils/EnvVarTraceListener.cs | 4 +- src/SIL.LCModel.Utils/ReflectionHelper.cs | 12 +-- src/SIL.LCModel.Utils/RegistryHelper.cs | 4 +- src/SIL.LCModel.Utils/SimpleBag.cs | 4 +- src/SIL.LCModel.Utils/SingletonsContainer.cs | 6 +- src/SIL.LCModel.Utils/SmallDictionary.cs | 10 ++- src/SIL.LCModel.Utils/TreeDictionary.cs | 22 +++--- .../Impl/RepositoryAdditions.cs | 52 ++++++------- src/SIL.LCModel/InterfaceDeclarations.cs | 2 +- .../RepositoryInterfaceAdditions.cs | 20 ++--- 37 files changed, 314 insertions(+), 255 deletions(-) diff --git a/src/CSTools/Tools/Tools.csproj b/src/CSTools/Tools/Tools.csproj index ec3cc4ed..f5b6ac94 100644 --- a/src/CSTools/Tools/Tools.csproj +++ b/src/CSTools/Tools/Tools.csproj @@ -9,6 +9,7 @@ ../../../CHANGELOG.md TRACE;GENTIME 1701;1702;0162 + disable diff --git a/src/CSTools/Tools/dfa.cs b/src/CSTools/Tools/dfa.cs index b54c2462..e4456397 100644 --- a/src/CSTools/Tools/dfa.cs +++ b/src/CSTools/Tools/dfa.cs @@ -46,7 +46,7 @@ public TokClassDef(GenBase gbs,string name,string bas) public string m_refToken = ""; public string m_initialisation = ""; public string m_implement = ""; - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new TokClassDef(); @@ -70,7 +70,7 @@ public Dfa(TokensGen tks) : base(tks) m_tokens = tks.m_tokens; } #endif - Tokens m_tokens = null; + Tokens? m_tokens = null; public static void SetTokens(Tokens tks, Hashtable h) // needed after deserialisation { foreach (Dfa v in h.Values) @@ -88,7 +88,7 @@ public class Action public Action a_next; public Action(int act,Action next) { a_act = act; a_next = next; } Action() {} - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new Action(); @@ -176,7 +176,7 @@ internal void AddActions() } } - internal Dfa Target(char ch) + internal Dfa? Target(char ch) { // construct or lookup the target for a new arc Dfa n = new Dfa(m_tks); @@ -223,7 +223,7 @@ internal bool SameAs(Dfa dfa) public int Match(string str,int ix,ref int action) { // return number of chars matched int r=0; - Dfa dfa=null; + Dfa? dfa =null; // if there is no arc or the string is exhausted, this is okay at a terminal if (ix>=str.Length || (dfa=((Dfa)m_map[m_tokens.Filter(str[ix])]))==null || @@ -295,7 +295,7 @@ public void Print() } } #endif - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new Dfa(); @@ -542,7 +542,7 @@ public Regex(TokensGen tks,int p,string str) tks.erh.Error(new CSToolsFatalException(1,tks.line(p),tks.position(p),str,String.Format("ill-formed regular expression <{0}>\n", str))); } protected Regex() {} // private - public Regex m_sub; + public Regex? m_sub; public virtual void Print(TextWriter s) { if (m_sub!=null) @@ -1068,8 +1068,8 @@ public Nfa(TokensGen tks,Regex re) : base(tks) // shame we have to do this ourselves, but SortedList doesn't allow incremental building of Dfas internal class NList { // sorted List of NfaNode - public NfaNode m_node; // null for the sentinel - public NList m_next; + public NfaNode? m_node; // null for the sentinel + public NList? m_next; public NList() { m_node=null; m_next=null; } // sentinel only NList(NfaNode nd,NList nx) { m_node=nd; m_next=nx; } public bool Add(NfaNode n) diff --git a/src/CSTools/Tools/genbase.cs b/src/CSTools/Tools/genbase.cs index decbf6de..805d3ffa 100644 --- a/src/CSTools/Tools/genbase.cs +++ b/src/CSTools/Tools/genbase.cs @@ -85,7 +85,7 @@ public bool NonWhite(string buf, ref int offset,int max) return offset - public void EmitClassDefin(string b,ref int p,int max,CsReader inf,string defbas,out string bas, out string name,bool lx) + public void EmitClassDefin(string b,ref int p,int max,CsReader? inf,string defbas,out string bas, out string name,bool lx) { bool defconseen = false; name = ""; @@ -170,7 +170,7 @@ public void EmitClassDefin(string b,ref int p,int max,CsReader inf,string defbas } m_outFile.WriteLine("}"); } - + [DoesNotReturn] public void Error(int n,int p,string str) { diff --git a/src/CSTools/Tools/lexer.cs b/src/CSTools/Tools/lexer.cs index ef1cb922..f3d71922 100644 --- a/src/CSTools/Tools/lexer.cs +++ b/src/CSTools/Tools/lexer.cs @@ -234,7 +234,7 @@ internal ChTest GetTest(string name) return new ChTest(Char.IsControl); // not reached } #endif - public virtual TOKEN OldAction(Lexer yyl,string yytext,int action,ref bool reject) + public virtual TOKEN? OldAction(Lexer yyl,string yytext,int action,ref bool reject) { return null; } @@ -247,7 +247,7 @@ public IEnumerator GetEnumerator() public class LineManager { public int lines = 1; // for error messages etc - public LineList list = null; + public LineList? list = null; public LineManager() {} public void newline(int pos) { @@ -353,7 +353,7 @@ public static Encoding GetEncoding(string enc, ref bool toupper,ErrorHandler erh } return Encoding.ASCII; } - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new Charset(); @@ -378,7 +378,7 @@ public static object Serialise(object o,Serialiser s) public class Tfactory { - public static object create(string cls_name,Lexer yyl) + public static object? create(string cls_name,Lexer yyl) { TCreator cr = (TCreator) yyl.tokens.types[cls_name]; // Console.WriteLine("TCreating {0} <{1}>",cls_name,yyl.yytext); @@ -414,13 +414,13 @@ public Tfactory(Tokens tks,string cls_name,TCreator cr) public class LineList { // based on Appel's ErrorMsg class public int head; - public CommentList comments = null; - public LineList tail; - public LineList(int h, LineList t) + public CommentList? comments = null; + public LineList? tail; + public LineList(int h, LineList? t) { - head=h; - comments = null; - tail=t; + head = h; + comments = null; + tail = t; } public int getpos(int pos) { @@ -434,7 +434,7 @@ public int getpos(int pos) public class CommentList { // similar for comments on a line public int spos,len; - public CommentList tail = null; + public CommentList? tail = null; public CommentList(int st,int ln, CommentList t) { spos = st; len = ln; @@ -629,8 +629,8 @@ protected SYMBOL() {} public virtual bool IsAction() { return false; } public virtual bool IsCSymbol() { return false; } //[NonSerialized] - public Parser yyps = null; - public Symbols yyact { get { return (yyps!=null)?yyps.m_symbols:null; }} + public Parser? yyps = null; + public Symbols? yyact { get { return (yyps!=null)?yyps.m_symbols:null; }} public SYMBOL(Parser yyp) { yyps=yyp; yylx=yyp.m_lexer; } public virtual bool Pass(Symbols syms,int snum,out ParserEntry entry) { @@ -823,9 +823,9 @@ public void Start(string buf) m_buf = m_buf.ToUpper(); m_pch = 0; } - public TOKEN Next() + public TOKEN? Next() { - TOKEN rv = null; + TOKEN? rv = null; while (PeekChar()!=0) { Matching(true); @@ -868,11 +868,17 @@ bool TryActions(Dfa dfa,ref TOKEN tok) { // last one might not be an old-style action if (m_debug) Console.WriteLine("creating a "+dfa.m_tokClass); - tok=(TOKEN)Tfactory.create(dfa.m_tokClass,this); + var createdToken = Tfactory.create(dfa.m_tokClass,this); + if (createdToken == null) + throw new InvalidOperationException($"Failed to create token of type {dfa.m_tokClass}"); + tok = (TOKEN)createdToken; } else { - tok = m_tokens.OldAction(this,yytext,action,ref reject); + var oldActionToken = m_tokens.OldAction(this,yytext,action,ref reject); + if (oldActionToken == null) + throw new InvalidOperationException("OldAction failed to create a valid token"); + tok = oldActionToken; if (m_debug && !reject) Console.WriteLine("Old action "+action); } @@ -919,14 +925,14 @@ public void Reset() public class _Enumerator { Lexer lxr; - TOKEN t; + TOKEN? t; public _Enumerator(Lexer x) { lxr = x; t = null; } public bool MoveNext() { t = lxr.Next(); return t!=null; } - public TOKEN Current { get { return t; } } + public TOKEN? Current { get { return t; } } public void Reset() { lxr.Reset(); } } } diff --git a/src/CSTools/Tools/olist.cs b/src/CSTools/Tools/olist.cs index 46ad14b0..beb7cd05 100644 --- a/src/CSTools/Tools/olist.cs +++ b/src/CSTools/Tools/olist.cs @@ -20,7 +20,7 @@ void Add0(Link a) { else last = last.next = a; } - object Get0(Link a,int x) { + object? Get0(Link a,int x) { if (a==null || x<0) // safety return null; if (x==0) @@ -39,7 +39,7 @@ public ObjectList() {} public class OListEnumerator : IEnumerator { ObjectList list; - Link cur = null; + Link? cur = null; public object Current { get { return cur.it; }} public OListEnumerator(ObjectList o) { diff --git a/src/CSTools/Tools/parser.cs b/src/CSTools/Tools/parser.cs index 7b2ebf10..a5fd6204 100644 --- a/src/CSTools/Tools/parser.cs +++ b/src/CSTools/Tools/parser.cs @@ -72,7 +72,7 @@ public void PrintTransitions(Func f,string s) #endif public ParseState m_accept; // support for actions - public virtual object Action(Parser yyp,SYMBOL yysym, int yyact) { return null; } // will be generated for the generated parser + public virtual object? Action(Parser yyp,SYMBOL yysym, int yyact) { return null; } // will be generated for the generated parser public Hashtable types = new Hashtable(); // string->SCreator // support for serialization public int[] arr; // defined in generated subclass @@ -139,9 +139,9 @@ protected SymbolsGen(ErrorHandler eh):base(eh) {} public int action = 0; internal ObjectList actions = new ObjectList(); // ParserAction internal int action_num = 0; // for old actions - public SymbolType stypes = null; // the list of grammar symbols + public SymbolType? stypes = null; // the list of grammar symbols internal int state=0; // for parsestates - public SymbolSet lahead = null; // support for lookahead sets + public SymbolSet? lahead = null; // support for lookahead sets public bool Find(CSymbol sym) { if (sym.yytext.Equals("Null")) // special case @@ -200,7 +200,7 @@ public virtual SYMBOL Action(Parser yyp) return s; } public override void Print() { Console.Write(m_sym.yytext); } - public CSymbol m_sym; + public CSymbol? m_sym; public int m_len; public override Boolean IsAction() { return true; } public virtual int ActNum() { return 0; } @@ -208,7 +208,7 @@ public virtual SYMBOL Action(Parser yyp) public ParserAction(SymbolsGen yyp) : base(yyp) {} #endif protected ParserAction() {} - public new static object Serialise(object o,Serialiser s) + public new static object? Serialise(object o,Serialiser s) { ParserAction p = (ParserAction)o; if (s.Encode) @@ -246,7 +246,7 @@ public ParserOldAction(SymbolsGen yyp) : base(yyp) { } #endif ParserOldAction() {} - public new static object Serialise(object o,Serialiser s) + public new static object? Serialise(object o,Serialiser s) { if (s==null) return new ParserOldAction(); @@ -278,7 +278,7 @@ public ParserSimpleAction(SymbolsGen yyp) : base(yyp) { } #endif ParserSimpleAction() {} - public new static object Serialise(object o,Serialiser s) + public new static object? Serialise(object o,Serialiser s) { if (s==null) return new ParserSimpleAction(); @@ -293,7 +293,7 @@ public ParserSimpleAction(SymbolsGen yyp) : base(yyp) { public abstract class ParserEntry { - public ParserAction m_action; + public ParserAction? m_action; [NonSerialized] public int m_priority = 0; public ParserEntry() { m_action = null; } public ParserEntry(ParserAction action) { m_action=action; } @@ -306,7 +306,7 @@ public virtual void Print(ParseState ps,CSymbol s) if (m_action!=null) m_action.Print(); } - public static object Serialise(object o, Serialiser s) + public static object? Serialise(object o, Serialiser s) { ParserEntry p = (ParserEntry)o; if (s.Encode) @@ -356,7 +356,7 @@ public override void Print(ParseState ps,CSymbol s) Transition.Follow(t).Print(); } #endif - public new static object Serialise(object o,Serialiser s) + public new static object? Serialise(object o,Serialiser s) { if (s==null) return new ParserShift(); @@ -380,7 +380,7 @@ public class ParserReduce : ParserEntry public ParserReduce(ParserAction action,int depth,Production prod) : base(action) {m_depth=depth; m_prod = prod; } ParserReduce() {} #if (GENTIME) - public SymbolSet m_lookAhead = null; + public SymbolSet? m_lookAhead = null; public void BuildLookback(Transition a) { SymbolsGen sg = a.m_ps.m_sgen; @@ -428,7 +428,7 @@ public override void Print(ParseState ps,CSymbol s) m_lookAhead.Print(); } #endif - public new static object Serialise(object o,Serialiser s) + public new static object? Serialise(object o,Serialiser s) { if (s==null) return new ParserReduce(); @@ -473,7 +473,7 @@ private ParsingInfo ParsingInfo return syms.GetSymbolInfo(m_A.yytext); } } - public ParserShift m_next = null; + public ParserShift? m_next = null; public Hashtable m_reduce = new Hashtable(); // Production->ParserReduce Hashtable m_reads = new Hashtable(); // Transition->bool Hashtable m_includes = new Hashtable(); // Transition->bool @@ -557,7 +557,7 @@ public static void BuildParseTable(Transition t) { Symbols syms = t.m_ps.m_sgen.m_symbols; ParsingInfo pi = t.ParsingInfo; - ParserReduce red = null; + ParserReduce? red = null; foreach (ParserReduce pr in t.m_reduce.Values) { if (t.m_ps.m_sgen.m_lalrParser? @@ -840,9 +840,9 @@ public class ParseStackEntry { public Parser yyps; public int m_state; - public SYMBOL m_value; + public SYMBOL? m_value; public ParseStackEntry(Parser yyp) {yyps = yyp; } - public ParseStackEntry(Parser yyp,int state,SYMBOL value) + public ParseStackEntry(Parser yyp,int state,SYMBOL? value) { yyps=yyp;m_state=state; m_value = value; } @@ -857,7 +857,7 @@ public ParsingInfo(string name) m_symName = name; } ParsingInfo() {} - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new ParsingInfo(); @@ -1115,7 +1115,7 @@ public CSymbol(SymbolsGen yyp) : base(yyp.m_lexer) } public override bool Matches(string s) { return false; } - internal ParseState Next(ParseState p) + internal ParseState? Next(ParseState p) { if (!p.m_transitions.Contains(yytext)) return null; @@ -1124,7 +1124,7 @@ internal ParseState Next(ParseState p) return null; return ps.m_next; } - internal Hashtable Reduce(ParseState p) // Objectlist of ParserReduce to distinct productions + internal Hashtable? Reduce(ParseState p) // Objectlist of ParserReduce to distinct productions { if (!p.m_transitions.Contains(yytext)) return null; @@ -1134,7 +1134,7 @@ internal Hashtable Reduce(ParseState p) // Objectlist of ParserReduce to distinc public virtual string TypeStr() { return yytext; } // for terminals - public Precedence m_prec; + public Precedence? m_prec; public bool ShiftPrecedence(Production prod,ParseState ps) { if (prod==null) // no reduce available @@ -1184,16 +1184,16 @@ public bool CouldBeEmpty() m_first.Contains(m_first.m_symbols.m_symbols.EmptySequence)); } // for nodesymbols - public CSymbol m_refSymbol; // maybe null + public CSymbol? m_refSymbol; // maybe null // class definition info public string m_initialisation=""; // may be empty public bool m_defined = false; public bool m_emitted = false; - public Production m_prod; // production where this initialisation occurs: maybe null + public Production? m_prod; // production where this initialisation occurs: maybe null #endif protected CSymbol() {} - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new CSymbol(); @@ -1266,7 +1266,7 @@ public class Production { public int m_pno; #if (GENTIME) - public CSymbol m_lhs; + public CSymbol? m_lhs; public bool m_actionsOnly; public int m_prec; public Production(SymbolsGen syms) @@ -1332,7 +1332,7 @@ public void StackRef(ref string str,int ch, int ix) } #endif Production() {} - public static object Serialise(object o,Serialiser s) + public static object? Serialise(object o,Serialiser s) { if (s==null) return new Production(); @@ -1361,10 +1361,10 @@ public ProdItem() m_pos = 0; m_done=false; } - public Production m_prod; + public Production? m_prod; public int m_pos; public bool m_done; - public CSymbol Next() + public CSymbol? Next() { if (m_pos",cls_name,yyl.yytext); diff --git a/src/CSTools/Tools/serialise.cs b/src/CSTools/Tools/serialise.cs index 9c12512b..2a1c4a05 100644 --- a/src/CSTools/Tools/serialise.cs +++ b/src/CSTools/Tools/serialise.cs @@ -51,8 +51,8 @@ static Serialiser() } // on Encode, we ignore the return value which is always null // Otherwise, o if non-null is an instance of the subclass - TextWriter f = null; - int[] b = null; + TextWriter? f = null; + int[]? b = null; int pos = 0; Hashtable obs = new Hashtable(); // object->int (code) or int->object (decode) static Hashtable tps = new Hashtable(); // type->SerType @@ -87,11 +87,11 @@ public int _Read() { return b[pos++]; } - static object NullSerialise(object o,Serialiser s) + static object? NullSerialise(object o,Serialiser s) { return null; } - static object IntSerialise(object o,Serialiser s) + static object? IntSerialise(object o,Serialiser s) { if (s.Encode) { @@ -100,7 +100,7 @@ static object IntSerialise(object o,Serialiser s) } return s._Read(); } - static object StringSerialise(object o,Serialiser s) + static object? StringSerialise(object o,Serialiser s) { if (s==null) return ""; @@ -120,7 +120,7 @@ static object StringSerialise(object o,Serialiser s) string r = e.GetString(bb,0,ln); return r; } - static object HashtableSerialise(object o,Serialiser s) + static object? HashtableSerialise(object o,Serialiser s) { if (s==null) return new Hashtable(); @@ -144,7 +144,7 @@ static object HashtableSerialise(object o,Serialiser s) } return h; } - static object CharSerialise(object o,Serialiser s) + static object? CharSerialise(object o,Serialiser s) { Encoding e = new UnicodeEncoding(); if (s.Encode) @@ -160,7 +160,7 @@ static object CharSerialise(object o,Serialiser s) string r = e.GetString(bb,0,2); return r[0]; } - static object BoolSerialise(object o,Serialiser s) + static object? BoolSerialise(object o,Serialiser s) { if (s.Encode) { @@ -170,7 +170,7 @@ static object BoolSerialise(object o,Serialiser s) int v = s._Read(); return v!=0; } - static object EncodingSerialise(object o,Serialiser s) + static object? EncodingSerialise(object o,Serialiser s) { if (s.Encode) { @@ -187,7 +187,7 @@ static object EncodingSerialise(object o,Serialiser s) } throw new Exception("Unknown encoding"); } - static object UnicodeCategorySerialise(object o,Serialiser s) + static object? UnicodeCategorySerialise(object o,Serialiser s) { if (s.Encode) { @@ -196,7 +196,7 @@ static object UnicodeCategorySerialise(object o,Serialiser s) } return (UnicodeCategory)s._Read(); } - static object SymtypeSerialise(object o,Serialiser s) + static object? SymtypeSerialise(object o,Serialiser s) { if (s.Encode) { diff --git a/src/CSTools/lg/lg.csproj b/src/CSTools/lg/lg.csproj index f3a07832..70b3e736 100644 --- a/src/CSTools/lg/lg.csproj +++ b/src/CSTools/lg/lg.csproj @@ -8,6 +8,7 @@ false Exe 1701;1702;0162 + disable diff --git a/src/CSTools/pg/pg.csproj b/src/CSTools/pg/pg.csproj index 40b97b35..64f1dcc3 100644 --- a/src/CSTools/pg/pg.csproj +++ b/src/CSTools/pg/pg.csproj @@ -8,6 +8,7 @@ false Exe 1701;1702;0162 + disable diff --git a/src/SIL.LCModel.Build.Tasks/CellarModule.cs b/src/SIL.LCModel.Build.Tasks/CellarModule.cs index 7a4144ba..613e48e6 100644 --- a/src/SIL.LCModel.Build.Tasks/CellarModule.cs +++ b/src/SIL.LCModel.Build.Tasks/CellarModule.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Xml; @@ -14,7 +16,7 @@ namespace SIL.LCModel.Build.Tasks /// ---------------------------------------------------------------------------------------- internal class CellarModule: Base { - private StringKeyCollection m_classes; + private StringKeyCollection? m_classes; /// ------------------------------------------------------------------------------------ /// diff --git a/src/SIL.LCModel.Build.Tasks/Class.cs b/src/SIL.LCModel.Build.Tasks/Class.cs index 5a335f84..711a7836 100644 --- a/src/SIL.LCModel.Build.Tasks/Class.cs +++ b/src/SIL.LCModel.Build.Tasks/Class.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -22,32 +24,32 @@ internal class Class: Base, IClass // ReSharper disable InconsistentNaming public const int kTenMillion = 10000000; // ReSharper restore InconsistentNaming - private StringKeyCollection m_properties; - private StringKeyCollection m_objectProperties; - private StringKeyCollection m_atomicProperties; - private StringKeyCollection m_atomicRefProperties; - private StringKeyCollection m_atomicOwnProperties; - private StringKeyCollection m_vectorProperties; - private StringKeyCollection m_owningProperties; - private StringKeyCollection m_referenceProperties; - private StringKeyCollection m_collectionOwnProperties; - private StringKeyCollection m_sequenceOwnProperties; - private StringKeyCollection m_collectionRefProperties; - private StringKeyCollection m_sequenceRefProperties; - private StringKeyCollection m_collectionProperties; - private StringKeyCollection m_sequenceProperties; - - private StringKeyCollection m_basicProperties; - private StringKeyCollection m_integerProperties; - private StringKeyCollection m_booleanProperties; - private StringKeyCollection m_guidProperties; - private StringKeyCollection m_dateTimeProperties; - private StringKeyCollection m_genDateProperties; - private StringKeyCollection m_binaryProperties; - private StringKeyCollection m_tsStringProperties; - private StringKeyCollection m_multiProperties; - private StringKeyCollection m_unicodeProperties; - private StringKeyCollection m_textPropBinaryProperties; + private StringKeyCollection? m_properties; + private StringKeyCollection? m_objectProperties; + private StringKeyCollection? m_atomicProperties; + private StringKeyCollection? m_atomicRefProperties; + private StringKeyCollection? m_atomicOwnProperties; + private StringKeyCollection? m_vectorProperties; + private StringKeyCollection? m_owningProperties; + private StringKeyCollection? m_referenceProperties; + private StringKeyCollection? m_collectionOwnProperties; + private StringKeyCollection? m_sequenceOwnProperties; + private StringKeyCollection? m_collectionRefProperties; + private StringKeyCollection? m_sequenceRefProperties; + private StringKeyCollection? m_collectionProperties; + private StringKeyCollection? m_sequenceProperties; + + private StringKeyCollection? m_basicProperties; + private StringKeyCollection? m_integerProperties; + private StringKeyCollection? m_booleanProperties; + private StringKeyCollection? m_guidProperties; + private StringKeyCollection? m_dateTimeProperties; + private StringKeyCollection? m_genDateProperties; + private StringKeyCollection? m_binaryProperties; + private StringKeyCollection? m_tsStringProperties; + private StringKeyCollection? m_multiProperties; + private StringKeyCollection? m_unicodeProperties; + private StringKeyCollection? m_textPropBinaryProperties; /// ------------------------------------------------------------------------------------ /// @@ -171,7 +173,7 @@ private string InternalBaseClassName /// /// The base class. /// ------------------------------------------------------------------------------------ - public Class BaseClass + public Class? BaseClass { get { @@ -680,7 +682,7 @@ from property in BasicProperties } } - private static StringKeyCollection GatherNonObjectProperties(ref StringKeyCollection propertyCollection, IEnumerable query) + private static StringKeyCollection GatherNonObjectProperties(ref StringKeyCollection? propertyCollection, IEnumerable query) { if (propertyCollection == null) { @@ -692,7 +694,7 @@ private static StringKeyCollection GatherNonObjectProperties(ref Strin return propertyCollection; } - private static StringKeyCollection GatherObjectProperties(ref StringKeyCollection propertyCollection, IEnumerable query) + private static StringKeyCollection GatherObjectProperties(ref StringKeyCollection? propertyCollection, IEnumerable query) { if (propertyCollection == null) { diff --git a/src/SIL.LCModel.Build.Tasks/DummyClass.cs b/src/SIL.LCModel.Build.Tasks/DummyClass.cs index 9dd2d667..2233021d 100644 --- a/src/SIL.LCModel.Build.Tasks/DummyClass.cs +++ b/src/SIL.LCModel.Build.Tasks/DummyClass.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + namespace SIL.LCModel.Build.Tasks { /// ---------------------------------------------------------------------------------------- @@ -30,7 +32,7 @@ public string Abbreviation /// /// The base class. /// ------------------------------------------------------------------------------------ - public Class BaseClass + public Class? BaseClass { get { return null; } } diff --git a/src/SIL.LCModel.Build.Tasks/IClass.cs b/src/SIL.LCModel.Build.Tasks/IClass.cs index c799cbb1..90718679 100644 --- a/src/SIL.LCModel.Build.Tasks/IClass.cs +++ b/src/SIL.LCModel.Build.Tasks/IClass.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + namespace SIL.LCModel.Build.Tasks { /// ---------------------------------------------------------------------------------------- @@ -25,7 +27,7 @@ internal interface IClass /// /// The base class. /// ------------------------------------------------------------------------------------ - Class BaseClass { get; } + Class? BaseClass { get; } /// ------------------------------------------------------------------------------------ /// diff --git a/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs b/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs index 5766d734..48c2e79b 100644 --- a/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs +++ b/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.IO; @@ -23,7 +25,7 @@ internal class LcmGenerateImpl public static LcmGenerateImpl Generator; private readonly string m_OutputDir; - private string m_OutputFileName; + private string? m_OutputFileName; private readonly VelocityEngine m_Engine; private readonly VelocityContext m_Context; private Dictionary> m_OverrideList; @@ -51,7 +53,7 @@ public LcmGenerateImpl(XmlDocument doc, string outputDir) /// The output dir. /// The output file name. /// ------------------------------------------------------------------------------------ - public LcmGenerateImpl(XmlDocument doc, string outputDir, string outputFile) + public LcmGenerateImpl(XmlDocument doc, string outputDir, string? outputFile) { Generator = this; m_Document = doc; @@ -137,7 +139,7 @@ public void SetOutput(string outputFile) /// ------------------------------------------------------------------------------------ public void Process(string templateName) { - Stream stream = null; + Stream? stream = null; try { stream = string.IsNullOrEmpty(m_OutputFileName) @@ -164,7 +166,7 @@ public void Process(string templateName) /// Name of the module. /// /// ------------------------------------------------------------------------------------ - public CellarModule GetModule(string moduleName) + public CellarModule? GetModule(string moduleName) { var query = string.Format("//CellarModule[@id='{0}']", moduleName); // ReSharper disable PossibleNullReferenceException diff --git a/src/SIL.LCModel.Core/Cellar/GenDate.cs b/src/SIL.LCModel.Core/Cellar/GenDate.cs index aa0322bd..aeaa40f8 100644 --- a/src/SIL.LCModel.Core/Cellar/GenDate.cs +++ b/src/SIL.LCModel.Core/Cellar/GenDate.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Text; @@ -148,7 +150,7 @@ public int ToInt() /// /// /// - public static string ValidateParts(int month, int day, int year, bool ad) + public static string? ValidateParts(int month, int day, int year, bool ad) { if (year != UnknownYear && (year < MinYear || year > MaxYear)) return "year"; @@ -401,7 +403,7 @@ public override string ToString() return ToLongString(); } - private static string[] s_monthNames = null; + private static string[]? s_monthNames = null; /// /// Try to parse the string as a generic date. If successful, return true and set all diff --git a/src/SIL.LCModel.Core/Phonology/PhonEnv.lexer.cs b/src/SIL.LCModel.Core/Phonology/PhonEnv.lexer.cs index d5578f4f..e770567f 100644 --- a/src/SIL.LCModel.Core/Phonology/PhonEnv.lexer.cs +++ b/src/SIL.LCModel.Core/Phonology/PhonEnv.lexer.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using SIL.LCModel.Tools; namespace SIL.LCModel.Core.Phonology { @@ -211,7 +213,7 @@ public class yytokens : Tokens { /// /// /// -public override TOKEN OldAction(Lexer yym,string yytext, int action, ref bool reject) { +public override TOKEN? OldAction(Lexer yym,string yytext, int action, ref bool reject) { switch(action) { case -1: break; case 8: ; diff --git a/src/SIL.LCModel.Core/Phonology/PhonEnvRecognizer.cs b/src/SIL.LCModel.Core/Phonology/PhonEnvRecognizer.cs index f0204797..54e7fb53 100644 --- a/src/SIL.LCModel.Core/Phonology/PhonEnvRecognizer.cs +++ b/src/SIL.LCModel.Core/Phonology/PhonEnvRecognizer.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Diagnostics; using System.Text; @@ -16,11 +18,11 @@ namespace SIL.LCModel.Core.Phonology /// public class PhonEnvRecognizer { - private bool m_fSuccess; - private string m_sErrorMessage; - private PhonEnvParser m_parser; - private string[] m_saNaturalClasses; - private string[] m_saSegments; + private bool m_fSuccess = false; + private string m_sErrorMessage = ""; + private PhonEnvParser? m_parser; + private string[] m_saNaturalClasses = {}; + private string[] m_saSegments = {}; /// @@ -47,7 +49,7 @@ public PhonEnvRecognizer(string[] saSegments, string[] saNaturalClasses) /// The new set of segments. public void ResetSegments(string[] saSegments) { - m_parser.ResetSegments(saSegments); + m_parser!.ResetSegments(saSegments); } @@ -57,7 +59,7 @@ public void ResetSegments(string[] saSegments) /// public void ResetNaturalClasses(string[] saNaturalClasses) { - m_parser.ResetNaturalClasses(saNaturalClasses); + m_parser!.ResetNaturalClasses(saNaturalClasses); } @@ -72,7 +74,7 @@ public bool Recognize(string sEnvironment) try { InitParser(sEnvironment, m_saNaturalClasses, m_saSegments); - m_parser.Parse(sEnvironment); + m_parser!.Parse(sEnvironment); if (m_parser.Success) m_fSuccess = true; else @@ -81,7 +83,7 @@ public bool Recognize(string sEnvironment) catch (CSToolsException exc) { StringBuilder sb = new StringBuilder(); - if (m_parser.ErrorMessage == null) + if (m_parser!.ErrorMessage == null) { sb.Append(" @@ -93,15 +95,15 @@ public class OptionalSegment_4_1 : OptionalSegment_4 { public OptionalSegment_4_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage(PhonEnvParser.SyntaxErrType.missingOpeningParen.ToString(), - ((TOKEN)(yyq.StackAt(1).m_value)) + ((TOKEN)(yyq.StackAt(1).m_value!)) .yytext, - ((Segment)(yyq.StackAt(2).m_value)) + ((Segment)(yyq.StackAt(2).m_value!)) .pos); ((PhonEnvParser )yyq).SyntaxErrorType = PhonEnvParser.SyntaxErrType.missingOpeningParen; ((PhonEnvParser )yyq).Position = - ((Segment)(yyq.StackAt(2).m_value)) + ((Segment)(yyq.StackAt(2).m_value!)) .pos; }} /// @@ -135,15 +137,15 @@ public class Class_2_1 : Class_2 { public Class_2_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage(PhonEnvParser.SyntaxErrType.missingClosingSquareBracket.ToString(), - ((TOKEN)(yyq.StackAt(2).m_value)) + ((TOKEN)(yyq.StackAt(2).m_value!)) .yytext, - ((error)(yyq.StackAt(0).m_value)) + ((error)(yyq.StackAt(0).m_value!)) .pos); ((PhonEnvParser )yyq).SyntaxErrorType = PhonEnvParser.SyntaxErrType.missingClosingSquareBracket; ((PhonEnvParser )yyq).Position = - ((error)(yyq.StackAt(0).m_value)) + ((error)(yyq.StackAt(0).m_value!)) .pos; }} /// @@ -163,15 +165,15 @@ public class Class_4_1 : Class_4 { public Class_4_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage(PhonEnvParser.SyntaxErrType.missingOpeningSquareBracket.ToString(), - ((TOKEN)(yyq.StackAt(1).m_value)) + ((TOKEN)(yyq.StackAt(1).m_value!)) .yytext, - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .pos); ((PhonEnvParser )yyq).SyntaxErrorType = PhonEnvParser.SyntaxErrType.missingOpeningSquareBracket; ((PhonEnvParser )yyq).Position = - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .pos; }} /// @@ -193,19 +195,19 @@ public Class_6_1(Parser yyq):base(yyq){ if (!((PhonEnvParser )yyq).IsValidClass( - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .yytext)) { ((PhonEnvParser )yyq).CreateErrorMessage("class", - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .yytext, - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .pos); ((PhonEnvParser )yyq).ThrowError( - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .pos); } }} @@ -228,11 +230,11 @@ public Class_8_1(Parser yyq):base(yyq){ StringBuilder sb = new StringBuilder(); sb.Append( - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .yytext); if (!((PhonEnvParser )yyq).IsValidClass(sb.ToString())) @@ -240,11 +242,11 @@ public Class_8_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage("class", sb.ToString(), - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .pos); ((PhonEnvParser )yyq).ThrowError( - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .pos); } }} @@ -265,15 +267,15 @@ public class Class_10_1 : Class_10 { public Class_10_1(Parser yyq):base(yyq){ StringBuilder sb = new StringBuilder(); sb.Append( - ((Ident)(yyq.StackAt(3).m_value)) + ((Ident)(yyq.StackAt(3).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .yytext); if (!((PhonEnvParser )yyq).IsValidClass(sb.ToString())) @@ -281,11 +283,11 @@ public Class_10_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage("class", sb.ToString(), - ((Ident)(yyq.StackAt(3).m_value)) + ((Ident)(yyq.StackAt(3).m_value!)) .pos); ((PhonEnvParser )yyq).ThrowError( - ((Ident)(yyq.StackAt(3).m_value)) + ((Ident)(yyq.StackAt(3).m_value!)) .pos); } }} @@ -308,19 +310,19 @@ public Class_12_1(Parser yyq):base(yyq){ StringBuilder sb = new StringBuilder(); sb.Append( - ((Ident)(yyq.StackAt(4).m_value)) + ((Ident)(yyq.StackAt(4).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(3).m_value)) + ((Ident)(yyq.StackAt(3).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(2).m_value)) + ((Ident)(yyq.StackAt(2).m_value!)) .yytext); sb.Append(" "); sb.Append( - ((Ident)(yyq.StackAt(1).m_value)) + ((Ident)(yyq.StackAt(1).m_value!)) .yytext); if (!((PhonEnvParser )yyq).IsValidClass(sb.ToString())) @@ -328,11 +330,11 @@ public Class_12_1(Parser yyq):base(yyq){ ((PhonEnvParser )yyq).CreateErrorMessage("class", sb.ToString(), - ((Ident)(yyq.StackAt(4).m_value)) + ((Ident)(yyq.StackAt(4).m_value!)) .pos); ((PhonEnvParser )yyq).ThrowError( - ((Ident)(yyq.StackAt(4).m_value)) + ((Ident)(yyq.StackAt(4).m_value!)) .pos); } }} @@ -359,17 +361,17 @@ public class Literal_2_1 : Literal_2 { /// public Literal_2_1(Parser yyq):base(yyq){ int iPos = - ((Ident)(yyq.StackAt(0).m_value)) + ((Ident)(yyq.StackAt(0).m_value!)) .pos; if (!((PhonEnvParser )yyq).IsValidSegment( - ((Ident)(yyq.StackAt(0).m_value)) + ((Ident)(yyq.StackAt(0).m_value!)) .yytext, ref iPos)) { ((PhonEnvParser )yyq).CreateErrorMessage("segment", - ((Ident)(yyq.StackAt(0).m_value)) + ((Ident)(yyq.StackAt(0).m_value!)) .yytext, iPos); ((PhonEnvParser )yyq).ThrowError(iPos); @@ -382,7 +384,7 @@ public class yyPhonEnvParser /// /// /// - public override object Action(Parser yyq,SYMBOL yysym, int yyact) { + public override object? Action(Parser yyq,SYMBOL yysym, int yyact) { switch(yyact) { case -1: break; //// keep compiler happy } return null; } diff --git a/src/SIL.LCModel.Core/Scripture/BCVRef.cs b/src/SIL.LCModel.Core/Scripture/BCVRef.cs index 5ec38c94..6cbd710b 100644 --- a/src/SIL.LCModel.Core/Scripture/BCVRef.cs +++ b/src/SIL.LCModel.Core/Scripture/BCVRef.cs @@ -7,6 +7,8 @@ // Responsibility: TE Team // --------------------------------------------------------------------------------------------- +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -246,9 +248,9 @@ public static implicit operator BCVRef(int nBCV) /// ------------------------------------------------------------------------------------ protected static bool AreEqual(BCVRef left, BCVRef right) { - if ((object)left == null && (object)right == null) + if (left is null && right is null) return true; - else if ((object)left == null || (object)right == null) + else if (left is null || right is null) return false; return left.CompareTo(right) == 0; } @@ -310,7 +312,7 @@ protected static bool AreEqual(BCVRef left, BCVRef right) /// ------------------------------------------------------------------------------------ /// Equals is same as == /// ------------------------------------------------------------------------------------ - public override bool Equals(object o) + public override bool Equals(object? o) { if (o == null) return false; @@ -684,12 +686,12 @@ public static string MakeReferenceString(BCVRef startRef, BCVRef endRef, /// The reference range as a formatted string. /// ------------------------------------------------------------------------------------ public static string MakeReferenceString(string bookName, BCVRef startRef, - BCVRef endRef, string chapterVerseSeparator, string verseBridge, - string literalTitleText, string literalIntroText) + BCVRef? endRef, string chapterVerseSeparator, string verseBridge, + string? literalTitleText, string? literalIntroText) { bookName = bookName.Trim(); - if (endRef == null || endRef.IsEmpty) + if (endRef is null || endRef.IsEmpty) endRef = startRef; // Build strings to use for the chapter/verse separator and the verse bridge. @@ -726,7 +728,7 @@ public static string MakeReferenceString(string bookName, BCVRef startRef, startRef.Verse.ToString(); } - string sLiteral = null; + string? sLiteral = null; switch (startRef.Chapter) { case 0: sLiteral = literalTitleText; break; @@ -744,12 +746,12 @@ public static string MakeReferenceString(string bookName, BCVRef startRef, /// The literal string to use in place of the chapter number or /// null to use the chapter number. /// ------------------------------------------------------------------------------------ - private static string FormatChapterOnlyRef(int chapter, string literal) + private static string FormatChapterOnlyRef(int chapter, string? literal) { - if (literal == String.Empty) - return String.Empty; + if (literal == String.Empty) + return String.Empty; - return " " + (literal != null ? literal : chapter.ToString()); + return " " + (literal ?? chapter.ToString()); } /// ------------------------------------------------------------------------------------ @@ -1329,4 +1331,4 @@ public BCVRef EndRef } } #endregion -} \ No newline at end of file +} diff --git a/src/SIL.LCModel.Core/Scripture/ScriptureUtilsException.cs b/src/SIL.LCModel.Core/Scripture/ScriptureUtilsException.cs index d98521ca..3708f23c 100644 --- a/src/SIL.LCModel.Core/Scripture/ScriptureUtilsException.cs +++ b/src/SIL.LCModel.Core/Scripture/ScriptureUtilsException.cs @@ -8,6 +8,8 @@ // // +#nullable enable + using System; namespace SIL.LCModel.Core.Scripture @@ -314,11 +316,11 @@ public ScriptureUtilsException(SUE_ErrorCode errorCode, string fileName, Excepti m_message += Environment.NewLine + string.Format(GetResourceString("kstidImportErrorFileDetails"), fileName); - Exception innerException = InnerException; + Exception? innerException = InnerException; while (innerException != null) { - m_message += Environment.NewLine + innerException.Message; - innerException = innerException.InnerException; + m_message += Environment.NewLine + innerException.Message; + innerException = innerException.InnerException; } } #endregion @@ -405,7 +407,7 @@ static public void GetErrorMsgAndHelpTopic(SUE_ErrorCode error, out string msg, { includeLineInfoInDetails = true; topic = "/Beginning_Tasks/Import_Standard_Format/Unable_to_Import"; - string stidErrorMsg = null; + string? stidErrorMsg = null; switch (error) { @@ -648,9 +650,9 @@ static public string FormatErrorDetails(string filename, bool includeLineInfo, /// String resource id /// String /// ----------------------------------------------------------------------------------- - public static string GetResourceString(string stid) + public static string GetResourceString(string? stid) { - return stid == null ? "NullStringID" : ScrUtilsStrings.ResourceManager.GetString(stid); + return stid == null ? "NullStringID" : ScrUtilsStrings.ResourceManager.GetString(stid) ?? $"Missing resource string: {stid}"; } #endregion } diff --git a/src/SIL.LCModel.Core/SpellChecking/SpellEngine.cs b/src/SIL.LCModel.Core/SpellChecking/SpellEngine.cs index 04757e7d..3a0ca055 100644 --- a/src/SIL.LCModel.Core/SpellChecking/SpellEngine.cs +++ b/src/SIL.LCModel.Core/SpellChecking/SpellEngine.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -18,11 +20,11 @@ internal abstract class SpellEngine : ISpellEngine, IDisposable /// Words are added by appearing, each on a line /// Words beginning * are known bad words. /// - internal string ExceptionPath { get; set; } + internal string? ExceptionPath { get; set; } internal static SpellEngine Create(string affixPath, string dictPath, string exceptionPath) { - SpellEngine spellEngine = null; + SpellEngine? spellEngine = null; try { spellEngine = new SpellEngineWeCantSpell(affixPath, dictPath, exceptionPath); @@ -50,7 +52,7 @@ private void Initialize() using (var reader = new StreamReader(ExceptionPath, Encoding.UTF8)) { - string line; + string? line; while ((line = reader.ReadLine()) != null) { var item = line; diff --git a/src/SIL.LCModel.Core/SpellChecking/SpellingHelper.cs b/src/SIL.LCModel.Core/SpellChecking/SpellingHelper.cs index d41d14fb..b8803be3 100644 --- a/src/SIL.LCModel.Core/SpellChecking/SpellingHelper.cs +++ b/src/SIL.LCModel.Core/SpellChecking/SpellingHelper.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -216,7 +218,7 @@ public static ISpellEngine GetSpellChecker(int ws, ILgWritingSystemFactory wsf) private static SpellEngine RawGetSpellChecker(string dictId) { - SpellEngine result = null; + SpellEngine? result = null; var rootDir = GetSpellingDirectoryPath(); var dictPath = GetShortName(Path.Combine(rootDir, Path.ChangeExtension(dictId, "dic"))); var affixPath = GetShortName(Path.Combine(rootDir, Path.ChangeExtension(dictId, "aff"))); diff --git a/src/SIL.LCModel.Core/Text/StringSearcher.cs b/src/SIL.LCModel.Core/Text/StringSearcher.cs index 6c2180da..1dfe1116 100644 --- a/src/SIL.LCModel.Core/Text/StringSearcher.cs +++ b/src/SIL.LCModel.Core/Text/StringSearcher.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -212,7 +214,7 @@ public IEnumerable Search(int indexId, ITsString tss) if (tss.RunCount == 1) // VERY common special case return Search(indexId, tss.get_WritingSystemAt(0), tss.Text) ?? Enumerable.Empty(); - IEnumerable results = null; + IEnumerable? results = null; foreach (Tuple wsStr in GetWsStrings(tss)) { IEnumerable items = Search(indexId, wsStr.Item1, wsStr.Item2); @@ -252,7 +254,7 @@ public IEnumerable Search(int indexId, int wsId, string text) } case SearchType.FullText: - IEnumerable results = null; + IEnumerable? results = null; string[] tokens = RemoveWhitespaceAndPunctTokens(m_tokenizer(wsId, text)).ToArray(); for (int i = 0; i < tokens.Length; i++) { diff --git a/src/SIL.LCModel.Core/Text/TsPropsFactory.cs b/src/SIL.LCModel.Core/Text/TsPropsFactory.cs index aeb67543..8fa3043e 100644 --- a/src/SIL.LCModel.Core/Text/TsPropsFactory.cs +++ b/src/SIL.LCModel.Core/Text/TsPropsFactory.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using SIL.LCModel.Core.KernelInterfaces; @@ -27,7 +29,7 @@ public ITsTextProps MakeProps(string bstrStyle, int ws, int ows) {(int) FwTextPropType.ktptWs, new TsIntPropValue(ows, ws)} }; - Dictionary strProps = null; + Dictionary? strProps = null; if (!string.IsNullOrEmpty(bstrStyle)) { strProps = new Dictionary diff --git a/src/SIL.LCModel.Core/Text/TsStringComparer.cs b/src/SIL.LCModel.Core/Text/TsStringComparer.cs index 28d6c8b8..33791b79 100644 --- a/src/SIL.LCModel.Core/Text/TsStringComparer.cs +++ b/src/SIL.LCModel.Core/Text/TsStringComparer.cs @@ -5,6 +5,8 @@ // File: TsStringComparer.cs // Responsibility: TE Team +#nullable enable + using System; using System.Collections; using SIL.LCModel.Core.KernelInterfaces; @@ -88,8 +90,8 @@ public int Compare(object x, object y) throw new ArgumentException(); } - string xString = (x is ITsString) ? ((ITsString)x).Text : x as string; - string yString = (y is ITsString) ? ((ITsString)y).Text : y as string; + string? xString = (x is ITsString) ? ((ITsString)x).Text : x as string; + string? yString = (y is ITsString) ? ((ITsString)y).Text : y as string; if (xString == string.Empty) xString = null; if (yString == string.Empty) diff --git a/src/SIL.LCModel.Core/Text/TsStringSerializer.cs b/src/SIL.LCModel.Core/Text/TsStringSerializer.cs index 56f0eac7..d3bc76ed 100644 --- a/src/SIL.LCModel.Core/Text/TsStringSerializer.cs +++ b/src/SIL.LCModel.Core/Text/TsStringSerializer.cs @@ -8,6 +8,8 @@ // // +#nullable enable + using System; using System.Linq; using System.Text; @@ -59,7 +61,7 @@ public static string SerializeTsStringToXml(ITsString tss, ILgWritingSystemFacto } // Write the properties and text for each run - string fieldName = null; + string? fieldName = null; for (int i = 0; i < normalizedTss.RunCount; i++) { TsRunInfo tri; @@ -112,7 +114,7 @@ public static string SerializeTsStringToXml(ITsString tss, ILgWritingSystemFacto TsPropsSerializer.WriteIntProperty(writer, lgwsf, tpt, var, value); } - byte[] pict = null; + byte[]? pict = null; bool hotGuid = false; for (int j = 0; j < textProps.StrPropCount; j++) { diff --git a/src/SIL.LCModel.Core/Text/TsStringUtils.cs b/src/SIL.LCModel.Core/Text/TsStringUtils.cs index f8f1c9a6..6f8b4642 100644 --- a/src/SIL.LCModel.Core/Text/TsStringUtils.cs +++ b/src/SIL.LCModel.Core/Text/TsStringUtils.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -1718,7 +1720,7 @@ public static TsStringDiffInfo GetDiffsInTsStrings(ITsString tssOld, ITsString t // and we choose to make the longer match at the start. // On the other hand, if the two strings are "xxxabc xxxdef" and "xxxdef", we could have deleted // "xxxabc " or "abc xxx", and we'd prefer the first interpretation, so we choose the longer match at the end. - ITsString longerString = null; + ITsString? longerString = null; // only used and valid if cvIns or cvDel < 0 var offsetIchMin = 0; if (cvIns < 0) diff --git a/src/SIL.LCModel.Utils/EnvVarTraceListener.cs b/src/SIL.LCModel.Utils/EnvVarTraceListener.cs index 25ca552c..9d74acb2 100644 --- a/src/SIL.LCModel.Utils/EnvVarTraceListener.cs +++ b/src/SIL.LCModel.Utils/EnvVarTraceListener.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Diagnostics; using System.Text.RegularExpressions; @@ -59,7 +61,7 @@ public EnvVarTraceListener() /// The initialization data, e.g. /// "assertuienabled='true' logfilename='%temp%/MyAssert.log' assertionexceptionenabled='false'". /// ------------------------------------------------------------------------------------ - public EnvVarTraceListener(string initializeData) + public EnvVarTraceListener(string? initializeData) { AssertionExceptionEnabled = true; // default to true diff --git a/src/SIL.LCModel.Utils/ReflectionHelper.cs b/src/SIL.LCModel.Utils/ReflectionHelper.cs index 27583be2..a180258e 100644 --- a/src/SIL.LCModel.Utils/ReflectionHelper.cs +++ b/src/SIL.LCModel.Utils/ReflectionHelper.cs @@ -7,6 +7,8 @@ // Responsibility: FW Team, especially David Olson (this is of interest to PA also) // --------------------------------------------------------------------------------------------- +#nullable enable + using System; using System.Configuration; using System.Diagnostics; @@ -117,7 +119,7 @@ static public Object CreateObject(string assemblyName, string className1, } string className = className1.Trim(); - Object thing = null; + object? thing = null; try { //make the object @@ -187,7 +189,7 @@ public static Type GetType(string assemblyName, string className1) { Assembly assembly; var codeBase = Assembly.GetExecutingAssembly().CodeBase; - string baseDir = Path.GetDirectoryName(codeBase)?.Substring(Environment.OSVersion.Platform == PlatformID.Unix ? 5 : 6); + string? baseDir = Path.GetDirectoryName(codeBase)?.Substring(Environment.OSVersion.Platform == PlatformID.Unix ? 5 : 6); if (baseDir == null) throw new InvalidOperationException("Could not get assembly base directory from CodeBase " + codeBase); string assemblyPath = Path.Combine(baseDir, assemblyName); @@ -225,9 +227,9 @@ public static Type GetType(string assemblyName, string className1) /// Name of the method to call. /// An array of arguments to pass to the method call. /// ------------------------------------------------------------------------------------ - public static string GetStrResult(object binding, string methodName, params object[] args) + public static string? GetStrResult(object binding, string methodName, params object[] args) { - return (GetResult(binding, methodName, args) as string); + return GetResult(binding, methodName, args) as string; } /// ------------------------------------------------------------------------------------ @@ -445,7 +447,7 @@ public static object GetField(object binding, string fieldName) /// specified binding. /// /// ------------------------------------------------------------------------------------ - private static object Invoke(object binding, string name, object[] args, BindingFlags flags) + private static object Invoke(object binding, string name, object[]? args, BindingFlags flags) { // If binding is a Type then assume we're invoking a static method, property // or field. Otherwise invoke an instance method, property or field. diff --git a/src/SIL.LCModel.Utils/RegistryHelper.cs b/src/SIL.LCModel.Utils/RegistryHelper.cs index 2057d247..f54dcb51 100644 --- a/src/SIL.LCModel.Utils/RegistryHelper.cs +++ b/src/SIL.LCModel.Utils/RegistryHelper.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Diagnostics; using System.Globalization; @@ -132,7 +134,7 @@ public static bool KeyExists(RegistryKey key, string subKey) /// [out] value of the registry entry if it exists; null otherwise. /// true if the registry entry exists, otherwise false /// ------------------------------------------------------------------------------------ - public static bool RegEntryValueExists(RegistryKey key, string subKey, string regEntry, out object value) + public static bool RegEntryValueExists(RegistryKey key, string subKey, string regEntry, out object? value) { if (key == null) throw new ArgumentNullException(nameof(key)); diff --git a/src/SIL.LCModel.Utils/SimpleBag.cs b/src/SIL.LCModel.Utils/SimpleBag.cs index 5c332602..dbe88021 100644 --- a/src/SIL.LCModel.Utils/SimpleBag.cs +++ b/src/SIL.LCModel.Utils/SimpleBag.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections; using System.Collections.Concurrent; @@ -15,7 +17,7 @@ namespace SIL.LCModel.Utils public class SimpleBag : IBag { private object m_lockObject = new Object(); - private object m_contents; + private object? m_contents; /// /// Add an item to the bag. diff --git a/src/SIL.LCModel.Utils/SingletonsContainer.cs b/src/SIL.LCModel.Utils/SingletonsContainer.cs index 0de1b799..adff1866 100644 --- a/src/SIL.LCModel.Utils/SingletonsContainer.cs +++ b/src/SIL.LCModel.Utils/SingletonsContainer.cs @@ -2,6 +2,8 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections.Generic; using System.Threading; @@ -145,7 +147,7 @@ public IDisposable Item(string key) /// InvalidCastException is thrown. /// /// -------------------------------------------------------------------------------- - public T Get(string key, Func createFunc, Action initFunc) + public T Get(string key, Func createFunc, Action? initFunc) where T : IDisposable { m_lock.EnterUpgradeableReadLock(); @@ -196,7 +198,7 @@ public bool Contains(string key) where T : IDisposable // ReSharper restore MemberHidesStaticFromOuterClass #endregion // class SingletonsContainerImpl - private static SingletonsContainerImpl s_container; + private static SingletonsContainerImpl? s_container; /// ------------------------------------------------------------------------------------ /// Gets the SingletonsContainer instance. diff --git a/src/SIL.LCModel.Utils/SmallDictionary.cs b/src/SIL.LCModel.Utils/SmallDictionary.cs index 35ac992f..117defa6 100644 --- a/src/SIL.LCModel.Utils/SmallDictionary.cs +++ b/src/SIL.LCModel.Utils/SmallDictionary.cs @@ -1,7 +1,9 @@ -// Copyright (c) 2015-2017 SIL International +// Copyright (c) 2015-2017 SIL International // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections; using System.Collections.Generic; @@ -14,9 +16,11 @@ namespace SIL.LCModel.Utils /// a few keys. It uses linear search and is optimized for a handful of items. /// public class SmallDictionary : IDictionary + where Tkey : notnull + where TValue : notnull { - private KeyValuePair m_first; - private KeyValuePair[] m_others; + private KeyValuePair m_first = new(default!, default!); + private KeyValuePair[]? m_others; #region IDictionary Members diff --git a/src/SIL.LCModel.Utils/TreeDictionary.cs b/src/SIL.LCModel.Utils/TreeDictionary.cs index 5d7c8ecd..9b00a8e2 100644 --- a/src/SIL.LCModel.Utils/TreeDictionary.cs +++ b/src/SIL.LCModel.Utils/TreeDictionary.cs @@ -1,7 +1,9 @@ -// Copyright (c) 2015-2017 SIL International +// Copyright (c) 2015-2017 SIL International // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +#nullable enable + using System; using System.Collections; using System.Collections.Generic; @@ -37,7 +39,7 @@ private enum Direction #region Data Members - private RedBlackNode m_rootNode; + private RedBlackNode? m_rootNode; private int m_nodeCount; private readonly IComparer m_comparer; @@ -374,7 +376,7 @@ public bool Remove(TKey key) /// The key whose value to get. /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. /// is null. - public bool TryGetValue(TKey key, out TValue value) + public bool TryGetValue(TKey key, out TValue? value) { if (key == null) throw new ArgumentNullException("key"); @@ -506,7 +508,7 @@ private bool AddPair(KeyValuePair pair) return InsertNode(pair, m_rootNode); } - private bool TryGetNode(TKey key, out RedBlackNode node) + private bool TryGetNode(TKey key, out RedBlackNode? node) { node = null; @@ -613,7 +615,7 @@ private bool InsertNode(KeyValuePair pair, RedBlackNode current) return true; } - private void CheckNode(RedBlackNode current) + private void CheckNode(RedBlackNode? current) { if (current == null) return; @@ -941,7 +943,7 @@ private void PerformHardDelete(RedBlackNode current) } } - private static RedBlackNode FindSuccessor(RedBlackNode node) + private static RedBlackNode? FindSuccessor(RedBlackNode node) { // The successor to a node is the node closest in value to it that is larger. if (node.RightNode == null) @@ -1130,7 +1132,7 @@ private void RotateRightChildLeftParent(RedBlackNode current) #region Tree Traversal Methods - private static IEnumerable> InOrderTraversal(RedBlackNode node, Func breakPredicate) + private static IEnumerable> InOrderTraversal(RedBlackNode? node, Func? breakPredicate) { if (node.LeftNode != null) { @@ -1175,11 +1177,11 @@ public Direction ParentDirection public KeyValuePair Pair { get; set; } - public RedBlackNode ParentNode { get; set; } + public RedBlackNode? ParentNode { get; set; } - public RedBlackNode LeftNode { get; set; } + public RedBlackNode? LeftNode { get; set; } - public RedBlackNode RightNode { get; set; } + public RedBlackNode? RightNode { get; set; } public Boolean IsRoot { diff --git a/src/SIL.LCModel/Infrastructure/Impl/RepositoryAdditions.cs b/src/SIL.LCModel/Infrastructure/Impl/RepositoryAdditions.cs index 11108333..539b0206 100644 --- a/src/SIL.LCModel/Infrastructure/Impl/RepositoryAdditions.cs +++ b/src/SIL.LCModel/Infrastructure/Impl/RepositoryAdditions.cs @@ -7,6 +7,8 @@ // Implementation of the additional interface information should go into the RepositoryAdditions.cs file. // +#nullable enable + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -82,7 +84,7 @@ public IAnalysis GetObject(Guid id) /// /// Try to get a value for an uncertain guid. /// - public bool TryGetObject(Guid guid, out IAnalysis obj) + public bool TryGetObject(Guid guid, out IAnalysis? obj) { ICmObject target; if (m_everythingRepos.TryGetObject(guid, out target)) @@ -103,7 +105,7 @@ public IAnalysis GetObject(int hvo) return (IAnalysis)m_everythingRepos.GetObject(hvo); } - public bool TryGetObject(int hvo, out IAnalysis obj) + public bool TryGetObject(int hvo, out IAnalysis? obj) { ICmObject result; if (m_everythingRepos.TryGetObject(hvo, out result)) @@ -436,7 +438,7 @@ internal partial class StFootnoteRepository /// The footnote referenced in the properties or null if the properties /// were not for a footnote ORC /// ------------------------------------------------------------------------------------ - public IStFootnote GetFootnoteFromObjData(string objData) + public IStFootnote? GetFootnoteFromObjData(string objData) { if (String.IsNullOrEmpty(objData)) return null; @@ -466,7 +468,7 @@ internal partial class ScrFootnoteRepository /// The footnote referenced in the properties or null if the properties /// were not for a footnote ORC /// ------------------------------------------------------------------------------------ - public IScrFootnote GetFootnoteFromProps(ITsTextProps ttp) + public IScrFootnote? GetFootnoteFromProps(ITsTextProps ttp) { Guid objGuid = TsStringUtils.GetHotObjectGuidFromProps(ttp); if (objGuid == Guid.Empty) @@ -487,7 +489,7 @@ public IScrFootnote GetFootnoteFromProps(ITsTextProps ttp) /// Footnote with footnoteGuid as its id /// true if the footnote is found; false otherwise /// ------------------------------------------------------------------------------------ - public bool TryGetFootnote(Guid footnoteGuid, out IScrFootnote footnote) + public bool TryGetFootnote(Guid footnoteGuid, out IScrFootnote? footnote) { footnote = null; ICmObject obj; @@ -568,7 +570,7 @@ void IPunctuationFormRepositoryInternal.UpdateForm(ITsString oldForm, IPunctuati { if (m_punctFormFromForm == null) return; // nothing cached. - string oldKey = RemoveForm(oldForm) ? oldForm.Text : null; + string? oldKey = RemoveForm(oldForm) ? oldForm.Text : null; if (AddFormToCache(pf)) { var action = new UndoUpdateFormAction(oldKey, pf.Form.Text, pf, m_punctFormFromForm); @@ -594,7 +596,7 @@ void IPunctuationFormRepositoryInternal.RemoveForm(ITsString oldForm) /// ------------------------------------------------------------------------------------ private bool AddFormToCache(IPunctuationForm pf) { - ITsString tssKey = (pf != null) ? pf.Form : null; + ITsString? tssKey = pf?.Form; if (tssKey == null || tssKey.Length == 0) return false; @@ -658,7 +660,7 @@ public OrcStringHashcode(ITsString tss) /// -------------------------------------------------------------------------------- public override bool Equals(object obj) { - OrcStringHashcode otherObj = obj as OrcStringHashcode; + OrcStringHashcode? otherObj = obj as OrcStringHashcode; // If either object has m_ws == 0, then it is a semi-bogus OrcStringHashcode and // is assumed to not be equal to any other. This can happen, for instance, if // the TSS used to initialize it was not an ORC. @@ -900,7 +902,7 @@ void IWfiWordformRepositoryInternal.UpdateForm(ITsString oldForm, IWfiWordform w Dictionary lookupTable; if (!m_wordformFromForm.TryGetValue(ws, out lookupTable)) return; // this ws not yet cached. - string oldKey = null; + string? oldKey = null; if (oldForm != null) { oldKey = oldForm.Text; @@ -941,7 +943,7 @@ class UndoUpdateFormAction : UndoUpdateDictionaryAction private IWfiWordformRepositoryInternal m_wfRepo; public UndoUpdateFormAction(ITsString oldForm, ITsString newForm, IWfiWordform wf, IWfiWordformRepositoryInternal wfRepo, Dictionary lookupTable) - : base(oldForm == null ? null : oldForm.Text , newForm == null ? null : newForm.Text, wf, lookupTable) + : base(oldForm?.Text , newForm?.Text, wf, lookupTable) { m_oldForm = oldForm; m_newForm = newForm; @@ -1037,7 +1039,7 @@ internal partial class MoMorphTypeRepository /// /// /// - public void GetMajorMorphTypes(out IMoMorphType mmtStem, out IMoMorphType mmtPrefix, out IMoMorphType mmtSuffix, out IMoMorphType mmtInfix, out IMoMorphType mmtBoundStem, out IMoMorphType mmtProclitic, out IMoMorphType mmtEnclitic, out IMoMorphType mmtSimulfix, out IMoMorphType mmtSuprafix) + public void GetMajorMorphTypes(out IMoMorphType? mmtStem, out IMoMorphType? mmtPrefix, out IMoMorphType? mmtSuffix, out IMoMorphType? mmtInfix, out IMoMorphType? mmtBoundStem, out IMoMorphType? mmtProclitic, out IMoMorphType? mmtEnclitic, out IMoMorphType? mmtSimulfix, out IMoMorphType? mmtSuprafix) { mmtStem = null; mmtPrefix = null; @@ -1090,7 +1092,7 @@ public void GetMajorMorphTypes(out IMoMorphType mmtStem, out IMoMorphType mmtPre internal partial class MoStemAllomorphRepository { - private Dictionary, IMoStemAllomorph> m_monomorphemicMorphData; + private Dictionary, IMoStemAllomorph>? m_monomorphemicMorphData; /// /// Return a dictionary keyed by ws/form pair of the stem allomorphs that can stand alone as wordforms. /// @@ -1151,8 +1153,7 @@ public IEnumerable GetVisibleComplexFormEntries(ICmObject mainEntryOr { if (ler.RefType == LexEntryRefTags.krtComplexForm && ler.ShowComplexFormsInRS.Contains(mainEntryOrSense)) { - Debug.Assert(ler.Owner is ILexEntry); - retval.Add(ler.Owner as ILexEntry); + retval.Add((ILexEntry)ler.Owner); } } return SortEntries(retval); @@ -1172,8 +1173,7 @@ public IEnumerable GetComplexFormEntries(ICmObject mainEntryOrSense) { if (ler.RefType == LexEntryRefTags.krtComplexForm) { - Debug.Assert(ler.Owner is ILexEntry); - retval.Add(ler.Owner as ILexEntry); + retval.Add((ILexEntry)ler.Owner); } } return SortEntries(retval); @@ -1194,7 +1194,6 @@ public string HeadWordText(ILexEntry entry) if (m_cachedHeadwords.TryGetValue(entry, out result)) return result; result = entry.HeadWord.Text; - Debug.Assert(result != null); m_cachedHeadwords[entry] = result; return result; } @@ -1216,8 +1215,7 @@ public IEnumerable GetSubentries(ICmObject mainEntryOrSense) { if (ler.RefType == LexEntryRefTags.krtComplexForm && ler.PrimaryLexemesRS.Contains(mainEntryOrSense)) { - Debug.Assert(ler.Owner is ILexEntry); - retval.Add(ler.Owner as ILexEntry); + retval.Add((ILexEntry)ler.Owner); } } return SortEntries(retval); @@ -1233,8 +1231,7 @@ public IEnumerable GetVariantFormEntries(ICmObject mainEntryOrSense) // For a variant, ComponentLexemes is all that matters; PrimaryLexemes is not used. if (ler.RefType == LexEntryRefTags.krtVariant && ler.ComponentLexemesRS.Contains(mainEntryOrSense)) { - Debug.Assert(ler.Owner is ILexEntry); - retval.Add(ler.Owner as ILexEntry); + retval.Add((ILexEntry)ler.Owner); } } return retval; @@ -1244,7 +1241,7 @@ public IEnumerable GetVariantFormEntries(ICmObject mainEntryOrSense) /// Dictionary to track homographs. Entry may be a single (non-homograph) entry, or a list of entries. /// Key is the HomographForm of each entry. /// - Dictionary m_homographInfo; + Dictionary? m_homographInfo; /// /// Clear the list of homograph information @@ -1316,9 +1313,9 @@ private void AddToHomographDict(ILexEntry entry) { string key = entry.HomographFormKey; object oldVal; - if (m_homographInfo.TryGetValue(key, out oldVal)) + if (m_homographInfo!.TryGetValue(key, out oldVal)) { - List list = oldVal as List; + List? list = oldVal as List; if (list == null) { list = new List(); @@ -1389,7 +1386,6 @@ List ILexEntryRepositoryInternal.CollectHomographs(string sForm, int return new List(0); var cache = entries[0].Cache; - Debug.Assert(cache != null); var rgHomographs = new List(); var morphOrder = HomographMorphOrder(cache, morphType); @@ -1544,7 +1540,7 @@ private int CompareEntriesByHomographNumber(ILexEntry x, ILexEntry y) /// /// /// ------------------------------------------------------------------------------------ - public ILexEntry FindEntryForWordform(LcmCache cache, ITsString tssWf) + public ILexEntry? FindEntryForWordform(LcmCache cache, ITsString tssWf) { if (tssWf == null || tssWf.Length == 0) return null; @@ -1841,7 +1837,7 @@ internal partial class ScrCheckRunRepository /// A GUID that uniquely identifies the editorial check /// The run history for the requested check or null /// ------------------------------------------------------------------------------------ - public IScrCheckRun InstanceForCheck(int bookId, Guid checkId) + public IScrCheckRun? InstanceForCheck(int bookId, Guid checkId) { IScrBookAnnotations annotations = @@ -1902,7 +1898,7 @@ internal partial class PublicationRepository /// Name of the desired publication /// The publication or null if no matching publicaiton is found /// ------------------------------------------------------------------------------------ - public IPublication FindByName(string name) + public IPublication? FindByName(string name) { foreach (var pub in AllInstances()) if (pub.Name == name) diff --git a/src/SIL.LCModel/InterfaceDeclarations.cs b/src/SIL.LCModel/InterfaceDeclarations.cs index d974b172..28be0b1b 100644 --- a/src/SIL.LCModel/InterfaceDeclarations.cs +++ b/src/SIL.LCModel/InterfaceDeclarations.cs @@ -724,7 +724,7 @@ public interface IRepository where T : ICmObject /// /// If the given ID is valid, return true and put the corresponding object in the out param. - /// Otherwise return false and set the out arguement to null. + /// Otherwise return false and set the out argument to null. /// bool TryGetObject(Guid guid, out T obj); diff --git a/src/SIL.LCModel/RepositoryInterfaceAdditions.cs b/src/SIL.LCModel/RepositoryInterfaceAdditions.cs index 851695c3..6f86d8ff 100644 --- a/src/SIL.LCModel/RepositoryInterfaceAdditions.cs +++ b/src/SIL.LCModel/RepositoryInterfaceAdditions.cs @@ -7,6 +7,8 @@ // Implementation of the additional interface information should go into the RepositoryAdditions.cs file. // +#nullable enable + using System; using System.Collections.Generic; using SIL.LCModel.Core.KernelInterfaces; @@ -236,7 +238,7 @@ public partial interface IScrFootnoteRepository /// The footnote referenced in the properties or null if the properties /// were not for a footnote ORC /// ------------------------------------------------------------------------------------ - IScrFootnote GetFootnoteFromProps(ITsTextProps ttp); + IScrFootnote? GetFootnoteFromProps(ITsTextProps ttp); /// ------------------------------------------------------------------------------------ /// @@ -385,11 +387,11 @@ public partial interface IMoMorphTypeRepository /// /// /// - void GetMajorMorphTypes(out IMoMorphType mmtStem, out IMoMorphType mmtPrefix, - out IMoMorphType mmtSuffix, out IMoMorphType mmtInfix, - out IMoMorphType mmtBoundStem, out IMoMorphType mmtProclitic, - out IMoMorphType mmtEnclitic, out IMoMorphType mmtSimulfix, - out IMoMorphType mmtSuprafix); + void GetMajorMorphTypes(out IMoMorphType? mmtStem, out IMoMorphType? mmtPrefix, + out IMoMorphType? mmtSuffix, out IMoMorphType? mmtInfix, + out IMoMorphType? mmtBoundStem, out IMoMorphType? mmtProclitic, + out IMoMorphType? mmtEnclitic, out IMoMorphType? mmtSimulfix, + out IMoMorphType? mmtSuprafix); } public partial interface ILexEntryRepository @@ -450,7 +452,7 @@ public partial interface ILexEntryRepository /// /// /// ------------------------------------------------------------------------------------ - ILexEntry FindEntryForWordform(LcmCache cache, ITsString tssWf); + ILexEntry? FindEntryForWordform(LcmCache cache, ITsString tssWf); } internal interface ILexEntryRepositoryInternal @@ -599,7 +601,7 @@ public partial interface IScrCheckRunRepository /// The canonical number (1-based) of the desired book /// A GUID that uniquely identifies the editorial check /// The run history for the requested check or null - IScrCheckRun InstanceForCheck(int bookId, Guid checkId); + IScrCheckRun? InstanceForCheck(int bookId, Guid checkId); } public partial interface IPublicationRepository @@ -609,7 +611,7 @@ public partial interface IPublicationRepository /// /// Name of the desired publication /// The publication or null if no matching publicaiton is found - IPublication FindByName(string name); + IPublication? FindByName(string name); } public partial interface IScrDraftRepository From 9def28a62d16bac55500b5f7583cc376253599b1 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 17 Apr 2025 15:39:29 +0700 Subject: [PATCH 2/4] Allowing null in a couple places This was likely recommended by AI, but it breaks a number of tests. --- src/CSTools/Tools/lexer.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/CSTools/Tools/lexer.cs b/src/CSTools/Tools/lexer.cs index f3d71922..431287c8 100644 --- a/src/CSTools/Tools/lexer.cs +++ b/src/CSTools/Tools/lexer.cs @@ -868,17 +868,11 @@ bool TryActions(Dfa dfa,ref TOKEN tok) { // last one might not be an old-style action if (m_debug) Console.WriteLine("creating a "+dfa.m_tokClass); - var createdToken = Tfactory.create(dfa.m_tokClass,this); - if (createdToken == null) - throw new InvalidOperationException($"Failed to create token of type {dfa.m_tokClass}"); - tok = (TOKEN)createdToken; + tok=(TOKEN)Tfactory.create(dfa.m_tokClass,this); } else { - var oldActionToken = m_tokens.OldAction(this,yytext,action,ref reject); - if (oldActionToken == null) - throw new InvalidOperationException("OldAction failed to create a valid token"); - tok = oldActionToken; + tok = m_tokens.OldAction(this,yytext,action,ref reject); if (m_debug && !reject) Console.WriteLine("Old action "+action); } From 0bc51495508f3add730174a8df6905ede885fef2 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 18 Apr 2025 12:33:49 +0700 Subject: [PATCH 3/4] Enabled NRT for Build.Tasks and fix warnings --- src/SIL.LCModel.Build.Tasks/Base.cs | 6 +-- src/SIL.LCModel.Build.Tasks/IdlImp.cs | 20 ++++----- src/SIL.LCModel.Build.Tasks/LcmGenerate.cs | 42 +++++++++---------- .../LcmGenerateImpl.cs | 10 ++--- src/SIL.LCModel.Build.Tasks/Model.cs | 2 +- src/SIL.LCModel.Build.Tasks/Property.cs | 20 ++++----- .../RelationalProperty.cs | 4 +- .../SIL.LCModel.Build.Tasks.csproj | 1 + .../StringKeyCollection.cs | 2 +- src/SIL.LCModel.Build.Tasks/TypeInfo.cs | 3 +- 10 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/SIL.LCModel.Build.Tasks/Base.cs b/src/SIL.LCModel.Build.Tasks/Base.cs index 99e13095..e254699b 100644 --- a/src/SIL.LCModel.Build.Tasks/Base.cs +++ b/src/SIL.LCModel.Build.Tasks/Base.cs @@ -51,7 +51,7 @@ public T Parent /// ------------------------------------------------------------------------------------ public string Name { - get { return m_node.Attributes["id"].Value; } + get { return m_node.Attributes["id"]!.Value; } } /// ------------------------------------------------------------------------------------ @@ -75,13 +75,13 @@ public override string ToString() /// The tabs. /// The parent node. /// - protected static string AsMSString(string tabs, XmlNode parentNode) + protected static string AsMSString(string tabs, XmlNode? parentNode) { if (parentNode == null) return string.Empty; var retval = string.Empty; - foreach (XmlNode paraNode in parentNode.SelectNodes("para")) + foreach (XmlNode paraNode in parentNode.SelectNodes("para")!) retval = retval + tabs+ "/// " + paraNode.OuterXml + Environment.NewLine; return retval.TrimEnd(); } diff --git a/src/SIL.LCModel.Build.Tasks/IdlImp.cs b/src/SIL.LCModel.Build.Tasks/IdlImp.cs index 5e4f353e..a9612d5b 100644 --- a/src/SIL.LCModel.Build.Tasks/IdlImp.cs +++ b/src/SIL.LCModel.Build.Tasks/IdlImp.cs @@ -58,7 +58,7 @@ public IdlImpLogger(TaskLoggingHelper msbuildLogger) _logger = msbuildLogger; } - public void Error(string text) + public void Error(string text) { _logger.LogError(text); } @@ -81,14 +81,14 @@ public IdlImp() /// Namespace. [Required] - public string Namespace { get; set; } + public string? Namespace { get; set; } /// ------------------------------------------------------------------------------------ /// /// Additional namespaces that are used. /// /// ------------------------------------------------------------------------------------ - public ITaskItem[] UsingNamespaces { get; set; } + public ITaskItem[]? UsingNamespaces { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -96,7 +96,7 @@ public IdlImp() /// /// ------------------------------------------------------------------------------------ [Required] - public ITaskItem[] IdhFiles { get; set; } + public ITaskItem[]? IdhFiles { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -104,7 +104,7 @@ public IdlImp() /// /// /// ------------------------------------------------------------------------------------ - public ITaskItem[] ReferenceFiles { get; set; } + public ITaskItem[]? ReferenceFiles { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -117,9 +117,9 @@ public IdlImp() /// The IDL file (typically only one) we want to compile. /// [Required] - public ITaskItem[] Sources { get; set; } + public ITaskItem[]? Sources { get; set; } - private static StringCollection GetFilesFrom(ITaskItem[] source) + private static StringCollection GetFilesFrom(ITaskItem[]? source) { var result = new StringCollection(); if (source == null) @@ -130,7 +130,7 @@ private static StringCollection GetFilesFrom(ITaskItem[] source) } [Required] - public string Output { get; set; } + public string? Output { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -150,7 +150,7 @@ public override bool Execute() } - foreach (var idlFile in Sources) + foreach (var idlFile in Sources!) { //Log.LogMessage(MessageImportance.Normal, "Creating IDL File " + Path.GetFileName(idlFile.ItemSpec)); Log.LogMessage(MessageImportance.Normal, "Processing IDL File " + Path.GetFileName(idlFile.ItemSpec) + " to produce " + Output); @@ -159,7 +159,7 @@ public override bool Execute() foreach (var s in GetFilesFrom(ReferenceFiles)) Log.LogMessage(MessageImportance.Low, "references: " + s); bool fOk = importer.Import(namespaces, idlFile.ItemSpec, null, - Output, Namespace, GetFilesFrom(IdhFiles), + Output!, Namespace!, GetFilesFrom(IdhFiles), GetFilesFrom(ReferenceFiles), CreateXmlComments); if (!fOk) { diff --git a/src/SIL.LCModel.Build.Tasks/LcmGenerate.cs b/src/SIL.LCModel.Build.Tasks/LcmGenerate.cs index 20f9df14..90d852fd 100644 --- a/src/SIL.LCModel.Build.Tasks/LcmGenerate.cs +++ b/src/SIL.LCModel.Build.Tasks/LcmGenerate.cs @@ -25,7 +25,7 @@ public class LcmGenerate: Task /// The XML file. /// ------------------------------------------------------------------------------------ [Required] - public string XmlFile { get; set; } + public string? XmlFile { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -34,7 +34,7 @@ public class LcmGenerate: Task /// The output directory. /// ------------------------------------------------------------------------------------ [Required] - public string OutputDir { get; set; } + public string? OutputDir { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -43,7 +43,7 @@ public class LcmGenerate: Task /// The output file name. /// ------------------------------------------------------------------------------------ [Required] - public string OutputFile { get; set; } + public string? OutputFile { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -52,7 +52,7 @@ public class LcmGenerate: Task /// The template file. /// ------------------------------------------------------------------------------------ [Required] - public string TemplateFile { get; set; } + public string? TemplateFile { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -60,18 +60,18 @@ public class LcmGenerate: Task /// /// The template file. /// ------------------------------------------------------------------------------------ - public string BackendTemplateFiles { get; set; } + public string? BackendTemplateFiles { get; set; } /// /// Gets or sets the working directory. /// /// The working directory. - public string WorkingDirectory { get; set; } + public string? WorkingDirectory { get; set; } /// /// Gets or sets the directory that contains HandGenerated.xml and IntPropTypeOverrides.xml /// - public string HandGeneratedDir { get; set; } + public string? HandGeneratedDir { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -83,13 +83,13 @@ public override bool Execute() string origDir = Directory.GetCurrentDirectory(); string oldDir; if (!String.IsNullOrEmpty(WorkingDirectory)) - oldDir = WorkingDirectory; + oldDir = WorkingDirectory!; else oldDir = origDir; try { var doc = new XmlDocument(); - string xmlPath = XmlFile; + string xmlPath = XmlFile!; if (!Path.IsPathRooted(xmlPath)) xmlPath = Path.Combine(oldDir, XmlFile); try @@ -118,14 +118,14 @@ public override bool Execute() { var props = new List(); // ReSharper disable PossibleNullReferenceException - foreach (XmlNode propertyNode in node.SelectNodes("property")) + foreach (XmlNode propertyNode in node.SelectNodes("property")!) // ReSharper restore PossibleNullReferenceException { - props.Add(propertyNode.Attributes["name"].Value); + props.Add(propertyNode.Attributes["name"]!.Value); } if (props.Count > 0) { - handGeneratedClasses.Add(node.Attributes["id"].Value, props); + handGeneratedClasses.Add(node.Attributes["id"]!.Value, props); } } } @@ -147,16 +147,14 @@ public override bool Execute() { // Dictionary var props = new Dictionary(); -// ReSharper disable PossibleNullReferenceException - foreach (XmlNode propertyNode in node.SelectNodes("property")) -// ReSharper restore PossibleNullReferenceException + foreach (XmlNode propertyNode in node.SelectNodes("property")!) { - props.Add(propertyNode.Attributes["name"].Value, - propertyNode.Attributes["type"].Value); + props.Add(propertyNode.Attributes["name"]!.Value, + propertyNode.Attributes["type"]!.Value); } if (props.Count > 0) { - intPropTypeOverridesClasses.Add(node.Attributes["id"].Value, props); + intPropTypeOverridesClasses.Add(node.Attributes["id"]!.Value, props); } } } @@ -173,7 +171,7 @@ public override bool Execute() var originalCurrentDirectory = Directory.GetCurrentDirectory(); Log.LogMessage(MessageImportance.Low, "Processing template {0}.", TemplateFile); - string outputDirPath = OutputDir; + string outputDirPath = OutputDir!; if (!Path.IsPathRooted(OutputDir)) outputDirPath = Path.Combine(oldDir, OutputDir); var lcmGenerate = new LcmGenerateImpl(doc, outputDirPath) @@ -181,11 +179,11 @@ public override bool Execute() Overrides = handGeneratedClasses, IntPropTypeOverrides = intPropTypeOverridesClasses }; - string outputPath = OutputFile; + string outputPath = OutputFile!; if (!Path.IsPathRooted(outputPath)) outputPath = Path.Combine(outputDirPath, OutputFile); // Generate the main code. - if (Path.GetDirectoryName(TemplateFile).Length > 0) + if (Path.GetDirectoryName(TemplateFile)!.Length > 0) Directory.SetCurrentDirectory(Path.GetDirectoryName(TemplateFile)); lcmGenerate.SetOutput(outputPath); lcmGenerate.Process(Path.GetFileName(TemplateFile)); @@ -193,7 +191,7 @@ public override bool Execute() // Generate the backend provider(s) code. if (!string.IsNullOrEmpty(BackendTemplateFiles)) { - foreach (var backendDir in BackendTemplateFiles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (var backendDir in BackendTemplateFiles!.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { var beDir = backendDir.Trim(); if (beDir == string.Empty) continue; diff --git a/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs b/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs index 48c2e79b..dbc3a286 100644 --- a/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs +++ b/src/SIL.LCModel.Build.Tasks/LcmGenerateImpl.cs @@ -22,14 +22,14 @@ namespace SIL.LCModel.Build.Tasks internal class LcmGenerateImpl { /// - public static LcmGenerateImpl Generator; + public static LcmGenerateImpl? Generator; private readonly string m_OutputDir; private string? m_OutputFileName; private readonly VelocityEngine m_Engine; private readonly VelocityContext m_Context; - private Dictionary> m_OverrideList; - private Dictionary> m_IntPropTypeOverrideList; + private Dictionary>? m_OverrideList; + private Dictionary>? m_IntPropTypeOverrideList; private readonly Model m_Model; private readonly XmlDocument m_Document; @@ -79,7 +79,7 @@ public LcmGenerateImpl(XmlDocument doc, string outputDir, string? outputFile) /// /// The list of override class names. /// ------------------------------------------------------------------------------------ - public Dictionary> Overrides + public Dictionary>? Overrides { get { return m_OverrideList; } set { m_OverrideList = value; } @@ -92,7 +92,7 @@ public Dictionary> Overrides /// /// The list of override class names. /// ------------------------------------------------------------------------------------ - public Dictionary> IntPropTypeOverrides + public Dictionary>? IntPropTypeOverrides { get { return m_IntPropTypeOverrideList; } set { m_IntPropTypeOverrideList = value; } diff --git a/src/SIL.LCModel.Build.Tasks/Model.cs b/src/SIL.LCModel.Build.Tasks/Model.cs index d7a239f9..41260256 100644 --- a/src/SIL.LCModel.Build.Tasks/Model.cs +++ b/src/SIL.LCModel.Build.Tasks/Model.cs @@ -18,7 +18,7 @@ namespace SIL.LCModel.Build.Tasks /// ---------------------------------------------------------------------------------------- internal class Model { - private StringKeyCollection m_modules; + private StringKeyCollection? m_modules; private readonly XmlElement m_node; /// ------------------------------------------------------------------------------------ diff --git a/src/SIL.LCModel.Build.Tasks/Property.cs b/src/SIL.LCModel.Build.Tasks/Property.cs index 63e07547..3b6db5da 100644 --- a/src/SIL.LCModel.Build.Tasks/Property.cs +++ b/src/SIL.LCModel.Build.Tasks/Property.cs @@ -85,7 +85,7 @@ public virtual int Number { get { - return Parent.Number * 1000 + Convert.ToInt32(m_node.Attributes["num"].Value); + return Parent.Number * 1000 + Convert.ToInt32(m_node.Attributes["num"]!.Value); } } @@ -99,7 +99,7 @@ public virtual string Signature { get { - string sig = m_node.Attributes["sig"].Value; + string sig = m_node.Attributes["sig"]!.Value; //if (sig == "MultiString" || sig == "MultiUnicode") // sig += "Accessor"; @@ -152,7 +152,7 @@ public virtual int BackRefNumber /// /// The type info. /// ------------------------------------------------------------------------------------ - protected virtual TypeInfo TypeInfo + protected virtual TypeInfo? TypeInfo { get { return TypeInfo.TypeInfos[Signature]; } } @@ -199,12 +199,12 @@ public bool IsHandGenerated get { var context = (VelocityContext) - RuntimeSingleton.GetApplicationAttribute("LcmGenerate.Context"); - var lcmGenerate = (LcmGenerateImpl)context.Get("lcmgenerate"); + RuntimeSingleton.GetApplicationAttribute("LcmGenerate.Context")!; + var lcmGenerate = (LcmGenerateImpl)context.Get("lcmgenerate")!; var className = Parent.Name; - return lcmGenerate.Overrides.ContainsKey(className) - && lcmGenerate.Overrides[className].Contains(Name); + return lcmGenerate.Overrides!.ContainsKey(className) && + lcmGenerate.Overrides[className].Contains(Name); } } @@ -220,11 +220,11 @@ public string OverridenType get { var context = (VelocityContext) - RuntimeSingleton.GetApplicationAttribute("LcmGenerate.Context"); - var lcmGenerate = (LcmGenerateImpl)context.Get("lcmgenerate"); + RuntimeSingleton.GetApplicationAttribute("LcmGenerate.Context")!; + var lcmGenerate = (LcmGenerateImpl)context.Get("lcmgenerate")!; var className = Parent.Name; - if (lcmGenerate.IntPropTypeOverrides.ContainsKey(className)) + if (lcmGenerate.IntPropTypeOverrides!.ContainsKey(className)) { if (lcmGenerate.IntPropTypeOverrides[className].ContainsKey(Name)) { diff --git a/src/SIL.LCModel.Build.Tasks/RelationalProperty.cs b/src/SIL.LCModel.Build.Tasks/RelationalProperty.cs index 92ec3531..60ef0e82 100644 --- a/src/SIL.LCModel.Build.Tasks/RelationalProperty.cs +++ b/src/SIL.LCModel.Build.Tasks/RelationalProperty.cs @@ -61,7 +61,7 @@ public override Card Cardinality { get { - var card = m_node.Attributes["card"].Value; + var card = m_node.Attributes["card"]!.Value; switch (card) { case "atomic": @@ -136,7 +136,7 @@ public override string CSharpType /// /// The type info. /// ------------------------------------------------------------------------------------ - protected override TypeInfo TypeInfo + protected override TypeInfo? TypeInfo { get { diff --git a/src/SIL.LCModel.Build.Tasks/SIL.LCModel.Build.Tasks.csproj b/src/SIL.LCModel.Build.Tasks/SIL.LCModel.Build.Tasks.csproj index b18aec90..dbf26c52 100644 --- a/src/SIL.LCModel.Build.Tasks/SIL.LCModel.Build.Tasks.csproj +++ b/src/SIL.LCModel.Build.Tasks/SIL.LCModel.Build.Tasks.csproj @@ -8,6 +8,7 @@ SIL.LCModel.Build.Tasks provides msbuild tasks for generating C# classes for the tools/$(TargetFramework) true true + enable diff --git a/src/SIL.LCModel.Build.Tasks/StringKeyCollection.cs b/src/SIL.LCModel.Build.Tasks/StringKeyCollection.cs index 0d81acee..9935261a 100644 --- a/src/SIL.LCModel.Build.Tasks/StringKeyCollection.cs +++ b/src/SIL.LCModel.Build.Tasks/StringKeyCollection.cs @@ -7,7 +7,7 @@ namespace SIL.LCModel.Build.Tasks /// Collection which can also be accessed by Name. /// /// ---------------------------------------------------------------------------------------- - internal class StringKeyCollection : KeyedCollection + internal class StringKeyCollection : KeyedCollection where T : notnull { /// ------------------------------------------------------------------------------------ /// diff --git a/src/SIL.LCModel.Build.Tasks/TypeInfo.cs b/src/SIL.LCModel.Build.Tasks/TypeInfo.cs index 1c7c8a80..53e881a6 100644 --- a/src/SIL.LCModel.Build.Tasks/TypeInfo.cs +++ b/src/SIL.LCModel.Build.Tasks/TypeInfo.cs @@ -52,7 +52,7 @@ public TypeInfo(string retrievalType, string cSharpType, Hungarian = hung; } - private static Dictionary s_TypeInfos; + private static Dictionary? s_TypeInfos; /// ------------------------------------------------------------------------------------ /// @@ -98,5 +98,4 @@ public static Dictionary TypeInfos } } } - } From a45a53ca31ff4bc2b11e055a020824cde0d27368 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 25 Apr 2025 15:52:30 +0700 Subject: [PATCH 4/4] Enabled NRT for LCM.Utils --- src/SIL.LCModel.Utils/ArrayPtr.cs | 16 ++- src/SIL.LCModel.Utils/ConsumerThread.cs | 46 ++++---- .../ContinuableErrorException.cs | 2 +- src/SIL.LCModel.Utils/FileUtils.cs | 24 ++--- src/SIL.LCModel.Utils/IThreadedProgress.cs | 2 +- src/SIL.LCModel.Utils/MarshalEx.cs | 8 +- src/SIL.LCModel.Utils/MiscUtils.cs | 14 +-- src/SIL.LCModel.Utils/PriorityQueue.cs | 17 +-- src/SIL.LCModel.Utils/RecentItemsCache.cs | 2 +- src/SIL.LCModel.Utils/RegistryHelper.cs | 26 ++--- .../SIL.LCModel.Utils.csproj | 1 + src/SIL.LCModel.Utils/SimpleBag.cs | 10 +- .../SingleThreadedSynchronizeInvoke.cs | 2 +- src/SIL.LCModel.Utils/SingletonsContainer.cs | 4 +- src/SIL.LCModel.Utils/SmallDictionary.cs | 43 ++++---- src/SIL.LCModel.Utils/StringUtils.cs | 2 +- .../SynchronizeInvokeExtensions.cs | 6 +- src/SIL.LCModel.Utils/TreeDictionary.cs | 100 +++++++++--------- 18 files changed, 152 insertions(+), 173 deletions(-) diff --git a/src/SIL.LCModel.Utils/ArrayPtr.cs b/src/SIL.LCModel.Utils/ArrayPtr.cs index dba591e4..4874bc81 100644 --- a/src/SIL.LCModel.Utils/ArrayPtr.cs +++ b/src/SIL.LCModel.Utils/ArrayPtr.cs @@ -29,7 +29,7 @@ public class ArrayPtr : IDisposable { private IntPtr m_ptr; private int m_Size; - private static ArrayPtr s_Null; + private static ArrayPtr? s_Null; /// If we are in charge of the memory(true) /// or if native code owns it(false) private bool m_ownMemory; @@ -262,8 +262,7 @@ public static ArrayPtr Null { get { - if (s_Null == null) - s_Null = new ArrayPtr(IntPtr.Zero); + s_Null ??= new ArrayPtr(IntPtr.Zero); return s_Null; } } @@ -325,7 +324,7 @@ private ArrayPtrMarshaler(string strCookie) { } - private static ArrayPtrMarshaler m_Marshaler; + private static ArrayPtrMarshaler? m_Marshaler; /// ------------------------------------------------------------------------------------ /// @@ -337,8 +336,7 @@ private ArrayPtrMarshaler(string strCookie) /// ------------------------------------------------------------------------------------ public static ICustomMarshaler GetInstance(string strCookie) { - if (m_Marshaler == null) - m_Marshaler = new ArrayPtrMarshaler(strCookie); + m_Marshaler ??= new ArrayPtrMarshaler(strCookie); return m_Marshaler; } @@ -351,8 +349,8 @@ public static ICustomMarshaler GetInstance(string strCookie) /// ------------------------------------------------------------------------------------ public void CleanUpManagedData(object managedObj) { - if (managedObj != null && managedObj is IDisposable) - ((IDisposable)managedObj).Dispose(); + if (managedObj is IDisposable disposable) + disposable.Dispose(); } /// ------------------------------------------------------------------------------------ @@ -395,7 +393,7 @@ public IntPtr MarshalManagedToNative(object managedObj) /// A pointer to the unmanaged data to be wrapped /// Returns the managed view of the COM data /// ------------------------------------------------------------------------------------ - public object MarshalNativeToManaged(IntPtr pNativeData) + public object? MarshalNativeToManaged(IntPtr pNativeData) { return (ArrayPtr)pNativeData; } diff --git a/src/SIL.LCModel.Utils/ConsumerThread.cs b/src/SIL.LCModel.Utils/ConsumerThread.cs index 3648c49d..e70690b2 100644 --- a/src/SIL.LCModel.Utils/ConsumerThread.cs +++ b/src/SIL.LCModel.Utils/ConsumerThread.cs @@ -33,7 +33,7 @@ public interface IQueueAccessor /// /// The work item. /// - bool GetNextWorkItem(out T workItem); + bool GetNextWorkItem(out T? workItem); /// /// Gets the next work item with a priority that is greater than @@ -42,7 +42,7 @@ public interface IQueueAccessor /// The lowest priority. /// The work item. /// - bool GetNextWorkItem(P lowestPriority, out T workItem); + bool GetNextWorkItem(P lowestPriority, out T? workItem); /// /// Gets the next work item and its corresponding priority. @@ -50,7 +50,7 @@ public interface IQueueAccessor /// The priority. /// The work item. /// - bool GetNextPriorityWorkItem(out P priority, out T workItem); + bool GetNextPriorityWorkItem(out P priority, out T? workItem); /// /// Gets the next work item with a priority that is greater than @@ -60,7 +60,7 @@ public interface IQueueAccessor /// The priority. /// The work item. /// - bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T workItem); + bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T? workItem); /// /// Gets all work items. @@ -101,7 +101,7 @@ public interface IQueueAccessor /// /// The queue priority type /// The work item type - public class ConsumerThread : IQueueAccessor, IDisposable + public class ConsumerThread : IQueueAccessor, IDisposable where P : notnull { #region Member variables private readonly Thread m_thread; @@ -110,11 +110,11 @@ public class ConsumerThread : IQueueAccessor, IDisposable private readonly ManualResetEvent m_stopEvent = new ManualResetEvent(false); private readonly ManualResetEvent m_idleEvent = new ManualResetEvent(true); private readonly PriorityQueue m_queue; - private readonly Action m_initHandler; + private readonly Action? m_initHandler; private readonly Action> m_workHandler; private bool m_hasWork; private bool m_isIdle = true; - private Exception m_unhandledException; + private Exception? m_unhandledException; private bool m_stopRequested; #endregion @@ -132,7 +132,7 @@ public ConsumerThread(Action> workHandler) : this(workHandl /// /// The work handler. /// The init handler. - public ConsumerThread(Action> workHandler, Action initHandler) + public ConsumerThread(Action> workHandler, Action? initHandler) : this(workHandler, initHandler, Comparer

.Default, EqualityComparer.Default) { } @@ -144,7 +144,7 @@ public ConsumerThread(Action> workHandler, Action initHandl /// The init handler. /// The priority comparer. /// The work comparer. - public ConsumerThread(Action> workHandler, Action initHandler, IComparer

priorityComparer, + public ConsumerThread(Action> workHandler, Action? initHandler, IComparer

priorityComparer, IEqualityComparer workComparer) { if (workHandler == null) @@ -196,7 +196,7 @@ protected virtual void Dispose(bool fDisposing) ///

/// if there has been an error, this will return the exception that stopped it. /// - public Exception UnhandledException + public Exception? UnhandledException { get { @@ -246,7 +246,7 @@ private object SyncRoot /// The work. public void EnqueueWork(T work) { - EnqueueWork(default(P), work); + EnqueueWork(default!, work); } /// @@ -351,7 +351,7 @@ bool IQueueAccessor.StopRequested /// Gets the next work item. /// /// The work item. - bool IQueueAccessor.GetNextWorkItem(out T workItem) + bool IQueueAccessor.GetNextWorkItem(out T? workItem) { P priority; return GetNextPriorityWorkItem(out priority, out workItem); @@ -363,7 +363,7 @@ bool IQueueAccessor.GetNextWorkItem(out T workItem) ///
/// The lowest priority. /// The work item. - bool IQueueAccessor.GetNextWorkItem(P lowestPriority, out T workItem) + bool IQueueAccessor.GetNextWorkItem(P lowestPriority, out T? workItem) { P priority; return GetNextPriorityWorkItem(lowestPriority, out priority, out workItem); @@ -374,7 +374,7 @@ bool IQueueAccessor.GetNextWorkItem(P lowestPriority, out T workItem) ///
/// The priority. /// The work item. - bool IQueueAccessor.GetNextPriorityWorkItem(out P priority, out T workItem) + bool IQueueAccessor.GetNextPriorityWorkItem(out P priority, out T? workItem) { return GetNextPriorityWorkItem(out priority, out workItem); } @@ -386,7 +386,7 @@ bool IQueueAccessor.GetNextPriorityWorkItem(out P priority, out T workItem /// The lowest priority. /// The priority. /// The work item. - bool IQueueAccessor.GetNextPriorityWorkItem(P lowestPriority, out P priority, out T workItem) + bool IQueueAccessor.GetNextPriorityWorkItem(P lowestPriority, out P priority, out T? workItem) { return GetNextPriorityWorkItem(lowestPriority, out priority, out workItem); } @@ -484,7 +484,7 @@ private void WorkLoop() ///
/// The priority. /// The work item. - private bool GetNextPriorityWorkItem(out P priority, out T workItem) + private bool GetNextPriorityWorkItem(out P priority, out T? workItem) { lock (SyncRoot) { @@ -499,8 +499,8 @@ private bool GetNextPriorityWorkItem(out P priority, out T workItem) { // the queue is empty, so idle SetNoWork(); - priority = default(P); - workItem = default(T); + priority = default!; + workItem = default; return false; } } @@ -513,7 +513,7 @@ private bool GetNextPriorityWorkItem(out P priority, out T workItem) /// The lowest priority. /// The priority. /// The work item. - private bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T workItem) + private bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T? workItem) { lock (SyncRoot) { @@ -544,8 +544,8 @@ private bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T wor { // the next item has a lower priority than the lowest allowed priority, so idle SetNoWork(); - priority = default(P); - workItem = default(T); + priority = default!; + workItem = default; return false; } } @@ -553,8 +553,8 @@ private bool GetNextPriorityWorkItem(P lowestPriority, out P priority, out T wor { // the queue is empty, so idle SetNoWork(); - priority = default(P); - workItem = default(T); + priority = default!; + workItem = default; return false; } } diff --git a/src/SIL.LCModel.Utils/ContinuableErrorException.cs b/src/SIL.LCModel.Utils/ContinuableErrorException.cs index 45baeb4a..87e3c55f 100644 --- a/src/SIL.LCModel.Utils/ContinuableErrorException.cs +++ b/src/SIL.LCModel.Utils/ContinuableErrorException.cs @@ -36,7 +36,7 @@ public ContinuableErrorException(string message) /// The message. /// The inner exception. /// ------------------------------------------------------------------------------------ - public ContinuableErrorException(string message, Exception innerException) : + public ContinuableErrorException(string message, Exception? innerException) : base(message, innerException) { } diff --git a/src/SIL.LCModel.Utils/FileUtils.cs b/src/SIL.LCModel.Utils/FileUtils.cs index a2d2fea1..8849d041 100644 --- a/src/SIL.LCModel.Utils/FileUtils.cs +++ b/src/SIL.LCModel.Utils/FileUtils.cs @@ -658,7 +658,7 @@ public static bool IsFileReadableAndWritable(string filename) ///
/// The extension of the filename or null for '.tmp'. /// ------------------------------------------------------------------------------------ - public static string GetTempFile(string extension) + public static string? GetTempFile(string? extension) { var fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); return Path.ChangeExtension(fileName, extension ?? ".tmp"); @@ -924,7 +924,7 @@ public static Stream OpenStreamForRead(string fileName) /// Paths starting with drive letters other than "C:" are not handled since they /// are not as easily interpretable as a Linux path, and an exception will be thrown. ///
- public static string ChangeWindowsPathIfLinux(string windowsPath) + public static string? ChangeWindowsPathIfLinux(string? windowsPath) { if (!Platform.IsUnix) return windowsPath; @@ -950,8 +950,8 @@ public static string ChangeWindowsPathIfLinux(string windowsPath) /// This allows paths to be processed which are prefixed by /// FwObjDataTypes.kodtExternalPathName. ///
- public static string ChangeWindowsPathIfLinuxPreservingPrefix(string windowsPath, - string prefix) + public static string? ChangeWindowsPathIfLinuxPreservingPrefix(string? windowsPath, + string? prefix) { if (windowsPath == null || prefix == null || !windowsPath.StartsWith(prefix, StringComparison.Ordinal)) return ChangeWindowsPathIfLinux(windowsPath); @@ -968,14 +968,14 @@ public static string ChangeWindowsPathIfLinuxPreservingPrefix(string windowsPath /// Paths to removable media such as "/media/cdrom/dir" will simply /// be converted to "C:\media\cdrom\dir". ///
- public static string ChangeLinuxPathIfWindows(string linuxPath) + public static string? ChangeLinuxPathIfWindows(string? linuxPath) { if (Platform.IsUnix) return linuxPath; if (String.IsNullOrEmpty(linuxPath)) return linuxPath; // Collapse two or more adjacent slashes - if (linuxPath.Contains("//")) + if (linuxPath!.Contains("//")) linuxPath = Regex.Replace(linuxPath, "/+", "/"); // Prepend "C:" for absolute paths) if (linuxPath[0] == '/') @@ -989,8 +989,8 @@ public static string ChangeLinuxPathIfWindows(string linuxPath) /// This allows paths to be processed which are prefixed by /// FwObjDataTypes.kodtExternalPathName. /// - public static string ChangeLinuxPathIfWindowsPreservingPrefix(string linuxPath, - string prefix) + public static string? ChangeLinuxPathIfWindowsPreservingPrefix(string? linuxPath, + string? prefix) { if (linuxPath == null || prefix == null || !linuxPath.StartsWith(prefix, StringComparison.Ordinal)) return ChangeLinuxPathIfWindows(linuxPath); @@ -1006,7 +1006,7 @@ public static string ChangeLinuxPathIfWindowsPreservingPrefix(string linuxPath, /// For example, on Windows, changes "/dir/file.txt" to "C:\dir\file.txt", /// and on Linux, changes "C:\dir\file.txt" to "/dir/file.txt". /// - public static string ChangePathToPlatform(string path) + public static string? ChangePathToPlatform(string? path) { if (Platform.IsUnix) return ChangeWindowsPathIfLinux(path); @@ -1025,7 +1025,7 @@ public static string ChangePathToPlatform(string path) /// than "C:" are not handled since they are not as easily interpretable as a /// Linux path, and an exception will be thrown. /// - public static string ChangePathToPlatformPreservingPrefix(string path, string prefix) + public static string? ChangePathToPlatformPreservingPrefix(string? path, string? prefix) { if (Platform.IsUnix) return ChangeWindowsPathIfLinuxPreservingPrefix(path, prefix); @@ -1043,7 +1043,7 @@ public static string ChangePathToPlatformPreservingPrefix(string path, string pr /// specified folders. /// The list of folders to check. /// ------------------------------------------------------------------------------------ - public static string GetRelativePath(string fullPath, Action relFolderSideEffect, + public static string GetRelativePath(string fullPath, Action? relFolderSideEffect, params string[] foldersToCheck) { foreach (string dir in foldersToCheck) @@ -1084,7 +1084,7 @@ public static string GetRelativePath(string fullPath, Action relFolderSi /// /// FWNX-607 /// - public static string StripFilePrefix(string fileString) + public static string? StripFilePrefix(string? fileString) { if (fileString == null) return fileString; diff --git a/src/SIL.LCModel.Utils/IThreadedProgress.cs b/src/SIL.LCModel.Utils/IThreadedProgress.cs index 94d6988c..5de9e8a9 100644 --- a/src/SIL.LCModel.Utils/IThreadedProgress.cs +++ b/src/SIL.LCModel.Utils/IThreadedProgress.cs @@ -75,7 +75,7 @@ public class WorkerThreadException : Exception /// The message. /// The inner exception. /// ------------------------------------------------------------------------------------ - public WorkerThreadException(string message, Exception innerException) + public WorkerThreadException(string message, Exception? innerException) : base(message, innerException) { } diff --git a/src/SIL.LCModel.Utils/MarshalEx.cs b/src/SIL.LCModel.Utils/MarshalEx.cs index 21398f09..e31e5dd7 100644 --- a/src/SIL.LCModel.Utils/MarshalEx.cs +++ b/src/SIL.LCModel.Utils/MarshalEx.cs @@ -116,7 +116,7 @@ static private void CopyElements(ArrayPtr unmanagedObj, T[] array) IntPtr current = (IntPtr)unmanagedObj; if (elementType.IsValueType) { - foreach (object obj in array) + foreach (object? obj in array) { Marshal.StructureToPtr(obj, current, true); current = (IntPtr)((ulong)current + (ulong)elemSize); @@ -125,7 +125,7 @@ static private void CopyElements(ArrayPtr unmanagedObj, T[] array) else { int i = 0; - foreach(object obj in array) + foreach(object? obj in array) { if (obj == null) Marshal.WriteIntPtr(current, i * elemSize, IntPtr.Zero); @@ -147,12 +147,12 @@ static private void CopyElements(ArrayPtr unmanagedObj, T[] array) /// This method is only necessary for [out] or [in,out] arrays. For /// [in] arrays the .NET marshalling works. /// ----------------------------------------------------------------------------------- - static public T[] NativeToArray(ArrayPtr nativeData, int cElem) + static public T?[] NativeToArray(ArrayPtr nativeData, int cElem) { var type = typeof(T); int elemSize = SizeOf(type); IntPtr current = (IntPtr)nativeData; - T[] array = new T[cElem]; + T?[] array = new T[cElem]; if (type.IsValueType) { diff --git a/src/SIL.LCModel.Utils/MiscUtils.cs b/src/SIL.LCModel.Utils/MiscUtils.cs index 763c4ab6..b805958a 100644 --- a/src/SIL.LCModel.Utils/MiscUtils.cs +++ b/src/SIL.LCModel.Utils/MiscUtils.cs @@ -540,7 +540,7 @@ public void GetPhysicalMemoryBytes(object stateInfo) /// /// /// ------------------------------------------------------------------------------------ - public static int IndexOfAnyString(this string s, string[] rgs, out int iMatched) + public static int IndexOfAnyString(this string? s, string[]? rgs, out int iMatched) { return IndexOfAnyString(s, rgs, out iMatched, StringComparison.CurrentCulture); } @@ -556,7 +556,7 @@ public static int IndexOfAnyString(this string s, string[] rgs, out int iMatched /// culture rule to use /// /// ------------------------------------------------------------------------------------ - public static int IndexOfAnyString(this string s, string[] rgs, out int iMatched, StringComparison sc) + public static int IndexOfAnyString(this string? s, string[]? rgs, out int iMatched, StringComparison sc) { iMatched = -1; if (s == null || rgs == null || rgs.Length == 0) @@ -643,9 +643,9 @@ public static string CurrentUICulture /// /// /// ------------------------------------------------------------------------------------ - public static CultureInfo GetCultureForWs(string sWs) + public static CultureInfo? GetCultureForWs(string sWs) { - CultureInfo ci = null; + CultureInfo? ci = null; int idx = sWs.Length; while (ci == null && idx > 0) { @@ -699,7 +699,7 @@ public static bool WsHasValidCulture(string sWs) /// from FwUtils.DirectoryFinder /// /// ------------------------------------------------------------------------------------ - public static IEnumerable GetAdditionalUILanguages(string baseConfigPath) + public static IEnumerable GetAdditionalUILanguages(string? baseConfigPath) { var additionalWs = new List(); if (Directory.Exists(baseConfigPath)) @@ -788,7 +788,7 @@ public static string CleanupXmlString(string text) /// True if input is made of only one or more upper or lowercase English letters, /// otherwise false. /// - public static bool IsAlpha(string input) + public static bool IsAlpha(string? input) { if (input == null) return false; @@ -801,7 +801,7 @@ public static bool IsAlpha(string input) /// registry key. /// /// ------------------------------------------------------------------------------------ - public static bool CanWriteKey(this RegistryKey key) + public static bool CanWriteKey(this RegistryKey? key) { if (key == null) return false; diff --git a/src/SIL.LCModel.Utils/PriorityQueue.cs b/src/SIL.LCModel.Utils/PriorityQueue.cs index d787558f..ce667a3e 100644 --- a/src/SIL.LCModel.Utils/PriorityQueue.cs +++ b/src/SIL.LCModel.Utils/PriorityQueue.cs @@ -14,19 +14,12 @@ namespace SIL.LCModel.Utils /// priority values, such as an enumeration. The queue is indexed by the values so that /// Remove and Contains are close to O(1). /// - public class PriorityQueue : ICollection + public class PriorityQueue : ICollection where P : notnull { private struct IndexEntry { - public P Priority - { - get; set; - } - - public LinkedListNode Node - { - get; set; - } + public P Priority { get; set; } + public LinkedListNode Node { get; set; } } private readonly SortedDictionary> m_queues; @@ -36,7 +29,7 @@ public LinkedListNode Node /// Initializes a new instance of the class. /// public PriorityQueue() - : this (Comparer

.Default, EqualityComparer.Default) + : this(Comparer

.Default, EqualityComparer.Default) { } @@ -278,7 +271,7 @@ IEnumerator IEnumerable.GetEnumerator() /// The object to add. public void Add(T item) { - Enqueue(default(P), item); + Enqueue(default!, item); } ///

diff --git a/src/SIL.LCModel.Utils/RecentItemsCache.cs b/src/SIL.LCModel.Utils/RecentItemsCache.cs index abddea7d..7082204c 100644 --- a/src/SIL.LCModel.Utils/RecentItemsCache.cs +++ b/src/SIL.LCModel.Utils/RecentItemsCache.cs @@ -13,7 +13,7 @@ namespace SIL.LCModel.Utils /// if passed duplicate arguments. For now, the value looked up is parameterized, but the input is /// always a string. The user specifies the maximum number of items to save. /// - public class RecentItemsCache + public class RecentItemsCache where K : notnull { int MaxValuesToSave { get; set; } // This is the actual cache. diff --git a/src/SIL.LCModel.Utils/RegistryHelper.cs b/src/SIL.LCModel.Utils/RegistryHelper.cs index f54dcb51..fbe82102 100644 --- a/src/SIL.LCModel.Utils/RegistryHelper.cs +++ b/src/SIL.LCModel.Utils/RegistryHelper.cs @@ -27,14 +27,14 @@ public static class RegistryHelper /// Sets the name of the company used for registry settings. /// /// ------------------------------------------------------------------------------------ - public static string CompanyName { get; set; } + public static string? CompanyName { get; set; } /// ------------------------------------------------------------------------------------ /// /// Sets the name of the product used for registry settings. /// /// ------------------------------------------------------------------------------------ - public static string ProductName { get; set; } + public static string? ProductName { get; set; } /// ------------------------------------------------------------------------------------ /// @@ -182,7 +182,7 @@ public static RegistryKey SettingsKey(params string[] subKeys) /// NOTE: This key is not opened for write access, because 64-bit apps should write to their own registry space. /// /// Zero or more subkeys (e.g., a specific application name, project name, etc.) - public static RegistryKey SettingsKeyOld32Bit(params string[] subKeys) + public static RegistryKey? SettingsKeyOld32Bit(params string[] subKeys) { return CompanyKeyOld32Bit?.OpenSubKey(GetSubkeyName(subKeys)); } @@ -193,7 +193,7 @@ public static RegistryKey SettingsKeyOld32Bit(params string[] subKeys) /// NOTE: This key is not opened for write access because it will fail on non-administrator logins. /// /// Zero or more subkeys (e.g., a specific application name, project name, etc.) - public static RegistryKey SettingsKeyLocalMachine(params string[] subKeys) + public static RegistryKey? SettingsKeyLocalMachine(params string[] subKeys) { try { @@ -211,7 +211,7 @@ public static RegistryKey SettingsKeyLocalMachine(params string[] subKeys) /// NOTE: This key is not opened for write access because it will fail on non-administrator logins. /// /// Zero or more subkeys (e.g., a specific application name, project name, etc.) - public static RegistryKey SettingsKeyLocalMachineOld32Bit(params string[] subKeys) + public static RegistryKey? SettingsKeyLocalMachineOld32Bit(params string[] subKeys) { try { @@ -348,7 +348,7 @@ protected virtual void Dispose(bool fDisposing) /// The value. /// /// ------------------------------------------------------------------------------------ - protected virtual object GetPersistableForm(T value) + protected virtual object? GetPersistableForm(T value) { return value; } @@ -494,20 +494,6 @@ public RegistryBoolSetting(RegistryKey regKey, string entry, bool defaultValue) { } - /// ------------------------------------------------------------------------------------ - /// - /// Constructor for instantiating an object for setting\retrieving a boolean registry - /// value for use in views where we do not want to persist settings or in tests. - /// - /// The key whose value is to be stored/retrieved - /// The default value to use when retrieving the value of an - /// unitialized key - /// ------------------------------------------------------------------------------------ - public RegistryBoolSetting(string keyName, bool defaultValue) - : base(null, keyName, defaultValue) - { - } - /// ------------------------------------------------------------------------------------ /// /// Converts the specified value to the desired type. diff --git a/src/SIL.LCModel.Utils/SIL.LCModel.Utils.csproj b/src/SIL.LCModel.Utils/SIL.LCModel.Utils.csproj index 59686716..651edab2 100644 --- a/src/SIL.LCModel.Utils/SIL.LCModel.Utils.csproj +++ b/src/SIL.LCModel.Utils/SIL.LCModel.Utils.csproj @@ -5,6 +5,7 @@ SIL.LCModel.Utils The liblcm library is the core FieldWorks model for linguistic analyses of languages. Tools in this library provide the ability to store and interact with language and culture data, including anthropological, text corpus, and linguistics data. SIL.LCModel.Utils provides utility classes. + enable diff --git a/src/SIL.LCModel.Utils/SimpleBag.cs b/src/SIL.LCModel.Utils/SimpleBag.cs index dbe88021..58d14be0 100644 --- a/src/SIL.LCModel.Utils/SimpleBag.cs +++ b/src/SIL.LCModel.Utils/SimpleBag.cs @@ -33,7 +33,7 @@ public void Add(T item) } if (m_contents is T) { - if (item.Equals((T)m_contents)) + if (item!.Equals((T)m_contents)) { // Direct to duplicates. var contents = new ConcurrentDictionary(); @@ -50,7 +50,7 @@ public void Add(T item) return; } // Otherwise it must be a dictionary. - AddToDict(m_contents as ConcurrentDictionary, item); + AddToDict((m_contents as ConcurrentDictionary)!, item); } } @@ -61,7 +61,7 @@ public bool Remove(T item) { lock (m_lockObject) { - if (m_contents is T && item.Equals((T)m_contents)) + if (m_contents is T && item!.Equals((T)m_contents)) { m_contents = null; return true; @@ -71,7 +71,7 @@ public bool Remove(T item) { // In theory, if we are down to just one item, we could go back to a simpler representation; // but it's not worth it as this case is vanishingly rare. - return RemoveFromDict(m_contents as ConcurrentDictionary, item); + return RemoveFromDict((m_contents as ConcurrentDictionary)!, item); } return false; } @@ -131,7 +131,7 @@ public int Count public int Occurrences(T item) { if (m_contents is T) - if (item.Equals(m_contents)) + if (item!.Equals(m_contents)) return 1; else return 0; diff --git a/src/SIL.LCModel.Utils/SingleThreadedSynchronizeInvoke.cs b/src/SIL.LCModel.Utils/SingleThreadedSynchronizeInvoke.cs index dc9b9854..8ce8f746 100644 --- a/src/SIL.LCModel.Utils/SingleThreadedSynchronizeInvoke.cs +++ b/src/SIL.LCModel.Utils/SingleThreadedSynchronizeInvoke.cs @@ -84,7 +84,7 @@ public WaitHandle AsyncWaitHandle get { throw new NotSupportedException(); } } - public object AsyncState + public object? AsyncState { get { return null; } } diff --git a/src/SIL.LCModel.Utils/SingletonsContainer.cs b/src/SIL.LCModel.Utils/SingletonsContainer.cs index adff1866..48037cab 100644 --- a/src/SIL.LCModel.Utils/SingletonsContainer.cs +++ b/src/SIL.LCModel.Utils/SingletonsContainer.cs @@ -113,7 +113,7 @@ public bool Remove(string key) /// get disposed, causing the problem all this is aimed at preventing. /// /// -------------------------------------------------------------------------------- - public IDisposable Item(string key) + public IDisposable? Item(string key) { m_lock.EnterReadLock(); try @@ -265,7 +265,7 @@ public static bool Remove(IDisposable singleton) /// it is replaced, possibly breaking clients still using it, or it would never get /// disposed, causing the problem all this is aimed at preventing. /// ------------------------------------------------------------------------------------ - public static IDisposable Item(string key) + public static IDisposable? Item(string key) { if (s_container == null) return null; diff --git a/src/SIL.LCModel.Utils/SmallDictionary.cs b/src/SIL.LCModel.Utils/SmallDictionary.cs index 117defa6..0af783cb 100644 --- a/src/SIL.LCModel.Utils/SmallDictionary.cs +++ b/src/SIL.LCModel.Utils/SmallDictionary.cs @@ -17,10 +17,9 @@ namespace SIL.LCModel.Utils /// public class SmallDictionary : IDictionary where Tkey : notnull - where TValue : notnull { - private KeyValuePair m_first = new(default!, default!); - private KeyValuePair[]? m_others; + private KeyValuePair m_first = new(default!, default); + private KeyValuePair[]? m_others; #region IDictionary Members @@ -33,7 +32,7 @@ public void Add(Tkey key, TValue value) throw new ArgumentException("SmallDictionary does not allow the default value of the key type to be used as a key"); if (indexOfKey(key) != -2) throw new ArgumentException("Key " + key + " already present."); - var newItem = new KeyValuePair(key, value); + var newItem = new KeyValuePair(key, value); if (m_first.Key.Equals(default(Tkey))) { m_first = newItem; @@ -41,12 +40,12 @@ public void Add(Tkey key, TValue value) } if (m_others == null) { - m_others = new KeyValuePair[1]; + m_others = new KeyValuePair[1]; } else { var temp = m_others; - m_others = new KeyValuePair[temp.Length + 1]; + m_others = new KeyValuePair[temp.Length + 1]; Array.Copy(temp, m_others, temp.Length); } m_others[m_others.Length - 1] = newItem; @@ -110,7 +109,7 @@ public bool Remove(Tkey key) if (m_others == null) { // No others: make the special-case so it is empty. - m_first = new KeyValuePair(default(Tkey), default(TValue)); + m_first = new KeyValuePair(default!, default); return true; } // Removing the first one, but there are others: copy the first thing in m_others to first @@ -118,13 +117,13 @@ public bool Remove(Tkey key) // Now we've saved the first one from m_others in m_first, treat as if removing that first one. index = 0; } - if (m_others.Length == 1) + if (m_others!.Length == 1) { m_others = null; return true; } var temp = m_others; - m_others = new KeyValuePair[m_others.Length - 1]; + m_others = new KeyValuePair[m_others.Length - 1]; Array.Copy(temp, 0, m_others, 0, index); // copy ones before removed Array.Copy(temp, index + 1, m_others, index, m_others.Length - index); // copy ones after removed return true; @@ -138,15 +137,15 @@ public bool TryGetValue(Tkey key, out TValue value) int index = indexOfKey(key); if (index >= 0) { - value = m_others[index].Value; + value = m_others![index].Value!; return true; } if (index == -2) { - value = default(TValue); + value = default!; return false; } - value = m_first.Value; + value = m_first.Value!; return true; } @@ -159,10 +158,10 @@ public ICollection Values { var result = new TValue[Count]; if (result.Length > 0) - result[0] = m_first.Value; + result[0] = m_first.Value!; if (m_others != null) for (int i = 0; i < m_others.Length; i++) - result[i + 1] = m_others[i].Value; + result[i + 1] = m_others[i].Value!; return result; } } @@ -175,11 +174,11 @@ public TValue this[Tkey key] get { if (m_first.Key.Equals(key) && !key.Equals(default(Tkey))) - return m_first.Value; + return m_first.Value!; if (m_others != null) foreach (var item in m_others) if (item.Key.Equals(key)) - return item.Value; + return item.Value!; if (key.Equals(default(Tkey))) throw new ArgumentException("Cannot use default type for Key in SmallDictionary"); throw new KeyNotFoundException("Key " + key.ToString() + " not found."); @@ -188,7 +187,7 @@ public TValue this[Tkey key] { if (key.Equals(default(Tkey))) throw new ArgumentException("SmallDictionary does not allow the default value of the key type to be used as a key"); - var newItem = new KeyValuePair(key, value); + var newItem = new KeyValuePair(key, value); if (m_first.Key.Equals(key) || m_first.Key.Equals(default(Tkey))) { m_first = newItem; @@ -196,7 +195,7 @@ public TValue this[Tkey key] } if (m_others == null) { - m_others = new KeyValuePair[1]; + m_others = new KeyValuePair[1]; } else { @@ -209,7 +208,7 @@ public TValue this[Tkey key] } } var temp = m_others; - m_others = new KeyValuePair[temp.Length + 1]; + m_others = new KeyValuePair[temp.Length + 1]; Array.Copy(temp, m_others, temp.Length); } m_others[m_others.Length - 1] = newItem; @@ -235,7 +234,7 @@ public void Add(KeyValuePair item) public void Clear() { m_others = null; - m_first = new KeyValuePair(default(Tkey), default(TValue)); + m_first = new KeyValuePair(default!, default); } /// @@ -300,10 +299,10 @@ public bool Remove(KeyValuePair item) public IEnumerator> GetEnumerator() { if (!m_first.Key.Equals(default(Tkey))) - yield return m_first; + yield return new KeyValuePair(m_first.Key, m_first.Value!); if (m_others != null) foreach (var item in m_others) - yield return item; + yield return new KeyValuePair(item.Key, item.Value!); } diff --git a/src/SIL.LCModel.Utils/StringUtils.cs b/src/SIL.LCModel.Utils/StringUtils.cs index 79504bf9..3daea510 100644 --- a/src/SIL.LCModel.Utils/StringUtils.cs +++ b/src/SIL.LCModel.Utils/StringUtils.cs @@ -296,7 +296,7 @@ public static string ReadString(BinaryReader reader, int length) /// /// Remove all whitespace from a string. /// - public static string StripWhitespace(string s) + public static string? StripWhitespace(string? s) { if (s == null) return s; diff --git a/src/SIL.LCModel.Utils/SynchronizeInvokeExtensions.cs b/src/SIL.LCModel.Utils/SynchronizeInvokeExtensions.cs index 19e63bfa..95edc46c 100644 --- a/src/SIL.LCModel.Utils/SynchronizeInvokeExtensions.cs +++ b/src/SIL.LCModel.Utils/SynchronizeInvokeExtensions.cs @@ -73,7 +73,7 @@ public static void InvokeAsync(this ISynchronizeInvoke si, Action action) /// public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T param1) { - si.BeginInvoke(action, new object[] {param1}); + si.BeginInvoke(action, new object?[] {param1}); } /// @@ -83,7 +83,7 @@ public static void InvokeAsync(this ISynchronizeInvoke si, Action action, /// public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T1 param1, T2 param2) { - si.BeginInvoke(action, new object[] {param1, param2}); + si.BeginInvoke(action, new object?[] {param1, param2}); } /// @@ -93,7 +93,7 @@ public static void InvokeAsync(this ISynchronizeInvoke si, Action public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T1 param1, T2 param2, T3 param3) { - si.BeginInvoke(action, new object[] {param1, param2, param3}); + si.BeginInvoke(action, new object?[] {param1, param2, param3}); } } } diff --git a/src/SIL.LCModel.Utils/TreeDictionary.cs b/src/SIL.LCModel.Utils/TreeDictionary.cs index 9b00a8e2..9b94417f 100644 --- a/src/SIL.LCModel.Utils/TreeDictionary.cs +++ b/src/SIL.LCModel.Utils/TreeDictionary.cs @@ -67,7 +67,7 @@ public KeyValuePair Minimum // You can get the min value by traversing left from the root until you can't any more. var node = m_rootNode; - while (node.LeftNode != null) + while (node!.LeftNode != null) node = node.LeftNode; return node.Pair; @@ -86,7 +86,7 @@ public KeyValuePair Maximum // You can get the max value by traversing right from the root until you can't any more. var node = m_rootNode; - while (node.RightNode != null) + while (node!.RightNode != null) node = node.RightNode; return node.Pair; @@ -198,7 +198,7 @@ public IEnumerable> GetRangeBelow(TKey upper) if (IsEmpty) yield break; - foreach (KeyValuePair pair in InOrderTraversal(m_rootNode, n => m_comparer.Compare(upper, n.Pair.Key) < 0)) + foreach (KeyValuePair pair in InOrderTraversal(m_rootNode!, n => m_comparer.Compare(upper, n.Pair.Key) < 0)) yield return pair; } @@ -231,9 +231,9 @@ public void Clear() /// The object to locate in the . bool ICollection>.Contains(KeyValuePair item) { - RedBlackNode node; + RedBlackNode? node; if (TryGetNode(item.Key, out node)) - return EqualityComparer>.Default.Equals(item, node.Pair); + return EqualityComparer>.Default.Equals(item, node!.Pair); return false; } @@ -274,10 +274,10 @@ void ICollection>.CopyTo(KeyValuePair[] /// The object to remove from the . bool ICollection>.Remove(KeyValuePair item) { - RedBlackNode node; + RedBlackNode? node; if (TryGetNode(item.Key, out node)) { - if (EqualityComparer>.Default.Equals(item, node.Pair)) + if (EqualityComparer>.Default.Equals(item, node!.Pair)) { HardDelete(node); return true; @@ -327,8 +327,7 @@ public bool ContainsKey(TKey key) { if (key == null) throw new ArgumentNullException("key"); - RedBlackNode node; - return TryGetNode(key, out node); + return TryGetNode(key, out _); } /// @@ -358,10 +357,10 @@ public bool Remove(TKey key) { if (key == null) throw new ArgumentNullException("key"); - RedBlackNode node; + RedBlackNode? node; if (TryGetNode(key, out node)) { - HardDelete(node); + HardDelete(node!); return true; } return false; @@ -376,15 +375,18 @@ public bool Remove(TKey key) /// The key whose value to get. /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. /// is null. +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). public bool TryGetValue(TKey key, out TValue? value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + { if (key == null) throw new ArgumentNullException("key"); - RedBlackNode node; + RedBlackNode? node; if (TryGetNode(key, out node)) { - value = node.Pair.Value; + value = node!.Pair.Value; return true; } value = default(TValue); @@ -406,9 +408,9 @@ public TValue this[TKey key] { if (key == null) throw new ArgumentNullException("key"); - TValue value; + TValue? value; if (TryGetValue(key, out value)) - return value; + return value!; throw new KeyNotFoundException(); } @@ -416,10 +418,10 @@ public TValue this[TKey key] { if (key == null) throw new ArgumentNullException("key"); - RedBlackNode node; + RedBlackNode? node; if (TryGetNode(key, out node)) { - node.Pair = new KeyValuePair(key, value); + node!.Pair = new KeyValuePair(key, value); return; } Add(key, value); @@ -468,7 +470,7 @@ public ICollection Values /// public IEnumerator> GetEnumerator() { - foreach (KeyValuePair pair in InOrderTraversal(m_rootNode, null)) + foreach (KeyValuePair pair in InOrderTraversal(m_rootNode!, null)) yield return pair; } @@ -539,7 +541,7 @@ private bool TryGetNode(TKey key, out RedBlackNode? node) private Stack GetLowerBoundNodes(TKey lower) { var stack = new Stack(); - RedBlackNode current = m_rootNode; + RedBlackNode? current = m_rootNode; while (current != null) { int compare = m_comparer.Compare(lower, current.Pair.Key); @@ -611,7 +613,7 @@ private bool InsertNode(KeyValuePair pair, RedBlackNode current) CheckNode(current); // Automatically make sure the root node is black. (this is valid in a red/black tree) - m_rootNode.Color = NodeColor.Black; + m_rootNode!.Color = NodeColor.Black; return true; } @@ -627,10 +629,10 @@ private void CheckNode(RedBlackNode? current) // Switch colors and then check grandparent. uncleNode.Color = NodeColor.Black; current.Color = NodeColor.Black; - current.ParentNode.Color = NodeColor.Red; + current.ParentNode!.Color = NodeColor.Red; // We don't have to check the root node, I'm just going to turn it black. - if (current.ParentNode.ParentNode != null && m_comparer.Compare(current.ParentNode.ParentNode.Pair.Key, m_rootNode.Pair.Key) != 0) + if (current.ParentNode.ParentNode != null && m_comparer.Compare(current.ParentNode.ParentNode.Pair.Key, m_rootNode!.Pair.Key) != 0) { var node = current.ParentNode.ParentNode; CheckNode(node); @@ -674,7 +676,7 @@ private void CheckNode(RedBlackNode? current) } } - private RedBlackNode GetSiblingNode(RedBlackNode current) + private RedBlackNode? GetSiblingNode(RedBlackNode current) { if (current == null || current.ParentNode == null) return null; @@ -694,7 +696,7 @@ private void HardDelete(RedBlackNode current) { // Find the successor node, swap the value up the tree, and delete the successor. var successor = FindSuccessor(current); - current.Pair = successor.Pair; + current.Pair = successor!.Pair; PerformHardDelete(successor); } else @@ -710,9 +712,9 @@ private void PerformHardDelete(RedBlackNode current) // In this case we are deleting a leaf node, just get rid of it. if (current.ParentDirection == Direction.Left) - current.ParentNode.RightNode = null; + current.ParentNode!.RightNode = null; else - current.ParentNode.LeftNode = null; + current.ParentNode!.LeftNode = null; current.ParentNode = null; @@ -729,7 +731,7 @@ private void PerformHardDelete(RedBlackNode current) // Turn the sibling node red to compensate for the black node being deleted, // and make sure the parent is black. sibling.Color = NodeColor.Red; - sibling.ParentNode.Color = NodeColor.Black; + sibling.ParentNode!.Color = NodeColor.Black; } else if (sibling.LeftNode == null && sibling.RightNode != null) { @@ -739,7 +741,7 @@ private void PerformHardDelete(RedBlackNode current) // There will need to be a rotation to fix this situation, and // nodes will have to be re-colored. sibling.RightNode.Color = NodeColor.Black; - sibling.Color = sibling.ParentNode.Color; + sibling.Color = sibling.ParentNode!.Color; sibling.ParentNode.Color = NodeColor.Black; RotateRightChildLeftParent(sibling); } @@ -749,7 +751,7 @@ private void PerformHardDelete(RedBlackNode current) // it becomes the exact same case as above. RotateRightChildRightParent(sibling); sibling.Color = NodeColor.Black; - sibling.ParentNode.Color = sibling.ParentNode.ParentNode.Color; + sibling.ParentNode!.Color = sibling.ParentNode.ParentNode!.Color; sibling.ParentNode.ParentNode.Color = NodeColor.Black; RotateLeftChildRightParent(sibling.ParentNode); } @@ -763,7 +765,7 @@ private void PerformHardDelete(RedBlackNode current) // it becomes the exact same case as above. RotateLeftChildLeftParent(sibling); sibling.Color = NodeColor.Black; - sibling.ParentNode.Color = sibling.ParentNode.ParentNode.Color; + sibling.ParentNode!.Color = sibling.ParentNode.ParentNode!.Color; sibling.ParentNode.ParentNode.Color = NodeColor.Black; RotateRightChildLeftParent(sibling.ParentNode); } @@ -772,7 +774,7 @@ private void PerformHardDelete(RedBlackNode current) // There will need to be a rotation to fix this situation, and // nodes will have to be re-colored. sibling.LeftNode.Color = NodeColor.Black; - sibling.Color = sibling.ParentNode.Color; + sibling.Color = sibling.ParentNode!.Color; sibling.ParentNode.Color = NodeColor.Black; RotateLeftChildRightParent(sibling); } @@ -787,7 +789,7 @@ private void PerformHardDelete(RedBlackNode current) // There will need to be a rotation to fix this situation, and // nodes will have to be re-colored. sibling.RightNode.Color = NodeColor.Black; - sibling.Color = sibling.ParentNode.Color; + sibling.Color = sibling.ParentNode!.Color; sibling.ParentNode.Color = NodeColor.Black; RotateRightChildLeftParent(sibling); } @@ -797,7 +799,7 @@ private void PerformHardDelete(RedBlackNode current) // There will need to be a rotation to fix this situation, and // nodes will have to be re-colored. sibling.LeftNode.Color = NodeColor.Black; - sibling.Color = sibling.ParentNode.Color; + sibling.Color = sibling.ParentNode!.Color; sibling.ParentNode.Color = NodeColor.Black; RotateLeftChildRightParent(sibling); } @@ -806,7 +808,7 @@ private void PerformHardDelete(RedBlackNode current) { // This is the case where the sibling of the deleted node is red with 2 black children. // First, swap the sibling color with the parent color. - sibling.ParentNode.Color = NodeColor.Red; + sibling.ParentNode!.Color = NodeColor.Red; sibling.Color = NodeColor.Black; if (m_comparer.Compare(sibling.Pair.Key, current.Pair.Key) > 0) @@ -820,7 +822,7 @@ private void PerformHardDelete(RedBlackNode current) if ((newSib.LeftNode == null || (newSib.LeftNode != null && newSib.LeftNode.Color == NodeColor.Black)) && (newSib.RightNode == null || (newSib.RightNode != null && newSib.RightNode.Color == NodeColor.Black))) { - newSib.Color = newSib.ParentNode.Color; + newSib.Color = newSib.ParentNode!.Color; newSib.ParentNode.Color = NodeColor.Black; // Perform additional re-coloring and rotation to fix violations. @@ -837,7 +839,7 @@ private void PerformHardDelete(RedBlackNode current) // Perform additional re-coloring and rotation to fix violations. newSib.RightNode.Color = NodeColor.Black; - newSib.Color = newSib.ParentNode.Color; + newSib.Color = newSib.ParentNode!.Color; newSib.ParentNode.Color = NodeColor.Black; RotateRightChildLeftParent(newSib); } @@ -847,7 +849,7 @@ private void PerformHardDelete(RedBlackNode current) // Perform additional re-coloring and rotatin to fix violations. RotateLeftChildLeftParent(newSib); newSib.Color = NodeColor.Black; - newSib.ParentNode.Color = newSib.ParentNode.ParentNode.Color; + newSib.ParentNode!.Color = newSib.ParentNode.ParentNode!.Color; newSib.ParentNode.ParentNode.Color = NodeColor.Black; if (newSib.ParentNode.Color == NodeColor.Red) @@ -866,7 +868,7 @@ private void PerformHardDelete(RedBlackNode current) if ((newSib.LeftNode == null || (newSib.LeftNode != null && newSib.LeftNode.Color == NodeColor.Black)) && (newSib.RightNode == null || (newSib.RightNode != null && newSib.RightNode.Color == NodeColor.Black))) { - newSib.Color = newSib.ParentNode.Color; + newSib.Color = newSib.ParentNode!.Color; newSib.ParentNode.Color = NodeColor.Black; // Perform additional re-coloring and rotation to fix violations. @@ -882,7 +884,7 @@ private void PerformHardDelete(RedBlackNode current) // Perform additional re-coloring and rotation to fix violations. newSib.LeftNode.Color = NodeColor.Black; - newSib.Color = newSib.ParentNode.Color; + newSib.Color = newSib.ParentNode!.Color; newSib.ParentNode.Color = NodeColor.Black; RotateLeftChildRightParent(newSib); } @@ -892,7 +894,7 @@ private void PerformHardDelete(RedBlackNode current) // Perform additional re-coloring and rotatin to fix violations. RotateRightChildRightParent(newSib); newSib.Color = NodeColor.Black; - newSib.ParentNode.Color = newSib.ParentNode.ParentNode.Color; + newSib.ParentNode!.Color = newSib.ParentNode.ParentNode!.Color; newSib.ParentNode.ParentNode.Color = NodeColor.Black; if (newSib.ParentNode.Color == NodeColor.Red) @@ -985,9 +987,9 @@ private void RotateRightChildRightParent(RedBlackNode current) if (current.IsRoot) return; - var tmpNode = current.RightNode.LeftNode; + var tmpNode = current.RightNode!.LeftNode; current.RightNode.ParentNode = current.ParentNode; - current.ParentNode.LeftNode = current.RightNode; + current.ParentNode!.LeftNode = current.RightNode; current.ParentNode = current.RightNode; current.RightNode.LeftNode = current; @@ -1012,9 +1014,9 @@ private void RotateLeftChildLeftParent(RedBlackNode current) if (current.IsRoot) return; - var tmpNode = current.LeftNode.RightNode; + var tmpNode = current.LeftNode!.RightNode; current.LeftNode.ParentNode = current.ParentNode; - current.ParentNode.RightNode = current.LeftNode; + current.ParentNode!.RightNode = current.LeftNode; current.ParentNode = current.LeftNode; current.LeftNode.RightNode = current; @@ -1041,12 +1043,12 @@ private void RotateLeftChildRightParent(RedBlackNode current) if (current.RightNode != null) { - current.ParentNode.LeftNode = current.RightNode; + current.ParentNode!.LeftNode = current.RightNode; current.RightNode.ParentNode = current.ParentNode; } else { - current.ParentNode.LeftNode = current.RightNode; + current.ParentNode!.LeftNode = current.RightNode; } var tmpNode = current.ParentNode.ParentNode; @@ -1089,12 +1091,12 @@ private void RotateRightChildLeftParent(RedBlackNode current) if (current.LeftNode != null) { - current.ParentNode.RightNode = current.LeftNode; + current.ParentNode!.RightNode = current.LeftNode; current.LeftNode.ParentNode = current.ParentNode; } else { - current.ParentNode.RightNode = current.LeftNode; + current.ParentNode!.RightNode = current.LeftNode; } var tmpNode = current.ParentNode.ParentNode; @@ -1132,7 +1134,7 @@ private void RotateRightChildLeftParent(RedBlackNode current) #region Tree Traversal Methods - private static IEnumerable> InOrderTraversal(RedBlackNode? node, Func? breakPredicate) + private static IEnumerable> InOrderTraversal(RedBlackNode node, Func? breakPredicate) { if (node.LeftNode != null) {