summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2018-08-22 12:35:46 +0200
committerAraq <rumpf_a@web.de>2018-08-22 12:35:46 +0200
commit64517445ea2347f29d91de44fe46ff78a6f655ab (patch)
tree630493227c0d7c953da3b0af087615d1727829db /lib/pure
parent9047c3f5821043a348e289335ff00b1147a34f88 (diff)
downloadNim-64517445ea2347f29d91de44fe46ff78a6f655ab.tar.gz
even more strict isNil handling for strings/seqs in order to detect bugs
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/cgi.nim7
-rw-r--r--lib/pure/collections/sets.nim2
-rw-r--r--lib/pure/httpclient.nim4
-rw-r--r--lib/pure/json.nim1
-rw-r--r--lib/pure/logging.nim13
-rw-r--r--lib/pure/marshal.nim3
-rw-r--r--lib/pure/os.nim11
-rw-r--r--lib/pure/parsesql.nim1
-rw-r--r--lib/pure/unidecode/unidecode.nim1
-rw-r--r--lib/pure/xmldom.nim182
10 files changed, 91 insertions, 134 deletions
diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim
index e0cdc2ec0..101146ace 100644
--- a/lib/pure/cgi.nim
+++ b/lib/pure/cgi.nim
@@ -135,10 +135,9 @@ iterator decodeData*(allowedMethods: set[RequestMethod] =
   ## Reads and decodes CGI data and yields the (name, value) pairs the
   ## data consists of. If the client does not use a method listed in the
   ## `allowedMethods` set, an `ECgi` exception is raised.
-  var data = getEncodedData(allowedMethods)
-  if not isNil(data):
-    for key, value in decodeData(data):
-      yield (key, value)
+  let data = getEncodedData(allowedMethods)
+  for key, value in decodeData(data):
+    yield (key, value)
 
 proc readData*(allowedMethods: set[RequestMethod] =
                {methodNone, methodPost, methodGet}): StringTableRef =
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index fdc3b4b03..0ef91c3cc 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -74,7 +74,7 @@ proc isValid*[A](s: HashSet[A]): bool =
   ##   proc savePreferences(options: HashSet[string]) =
   ##     assert options.isValid, "Pass an initialized set!"
   ##     # Do stuff here, may crash in release builds!
-  result = not s.data.isNil
+  result = s.data.len > 0
 
 proc len*[A](s: HashSet[A]): int =
   ## Returns the number of keys in `s`.
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 0192e71e7..139d4bb50 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -185,7 +185,7 @@ proc body*(response: Response): string =
   ## Retrieves the specified response's body.
   ##
   ## The response's body stream is read synchronously.
-  if response.body.isNil():
+  if response.body.len == 0:
     response.body = response.bodyStream.readAll()
   return response.body
 
@@ -198,7 +198,7 @@ proc `body=`*(response: Response, value: string) {.deprecated.} =
 proc body*(response: AsyncResponse): Future[string] {.async.} =
   ## Reads the response's body and caches it. The read is performed only
   ## once.
-  if response.body.isNil:
+  if response.body.len == 0:
     response.body = await readAll(response.bodyStream)
   return response.body
 
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 69ffb1796..3599667a8 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -256,7 +256,6 @@ proc add*(obj: JsonNode, key: string, val: JsonNode) =
 proc `%`*(s: string): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JString JsonNode`.
   new(result)
-  if s.isNil: return
   result.kind = JString
   result.str = s
 
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index cdff1f548..f2f5cac9e 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -103,14 +103,9 @@ var
 proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
   ## Format a log message using the ``frmt`` format string, ``level`` and varargs.
   ## See the module documentation for the format string syntax.
-  const nilString = "nil"
-
   var msgLen = 0
   for arg in args:
-    if arg.isNil:
-      msgLen += nilString.len
-    else:
-      msgLen += arg.len
+    msgLen += arg.len
   result = newStringOfCap(frmt.len + msgLen + 20)
   var i = 0
   while i < frmt.len:
@@ -137,10 +132,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
       of "levelname": result.add(LevelNames[level])
       else: discard
   for arg in args:
-    if arg.isNil:
-      result.add(nilString)
-    else:
-      result.add(arg)
+    result.add(arg)
 
 method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {.
             raises: [Exception], gcsafe,
@@ -338,7 +330,6 @@ template fatal*(args: varargs[string, `$`]) =
 
 proc addHandler*(handler: Logger) =
   ## Adds ``handler`` to the list of handlers.
-  if handlers.isNil: handlers = @[]
   handlers.add(handler)
 
 proc getHandlers*(): seq[Logger] =
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index b90d2899c..980439759 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -98,8 +98,7 @@ proc storeAny(s: Stream, a: Any, stored: var IntSet) =
   of akProc, akPointer, akCString: s.write($a.getPointer.ptrToInt)
   of akString:
     var x = getString(a)
-    if isNil(x): s.write("null")
-    elif x.validateUtf8() == -1: s.write(escapeJson(x))
+    if x.validateUtf8() == -1: s.write(escapeJson(x))
     else:
       s.write("[")
       var i = 0
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 8fbc20bb5..2b3cf5142 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -233,7 +233,7 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
   ## modification time is later than `b`'s.
   when defined(posix):
     # If we don't have access to nanosecond resolution, use '>='
-    when not StatHasNanoseconds:  
+    when not StatHasNanoseconds:
       result = getLastModificationTime(a) >= getLastModificationTime(b)
     else:
       result = getLastModificationTime(a) > getLastModificationTime(b)
@@ -1343,16 +1343,21 @@ elif defined(windows):
   # is always the same -- independent of the used C compiler.
   var
     ownArgv {.threadvar.}: seq[string]
+    ownParsedArgv {.threadvar.}: bool
 
   proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
-    if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
+    if not ownParsedArgv:
+      ownArgv = parseCmdLine($getCommandLine())
+      ownParsedArgv = true
     result = ownArgv.len-1
 
   proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
     tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
-    if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
+    if not ownParsedArgv:
+      ownArgv = parseCmdLine($getCommandLine())
+      ownParsedArgv = true
     if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i])
     raise newException(IndexError, "invalid index")
 
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index e3bab9a8d..9aef43c1b 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -593,7 +593,6 @@ proc len*(n: SqlNode): int =
 proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i]
 
 proc add*(father, n: SqlNode) =
-  if isNil(father.sons): father.sons = @[]
   add(father.sons, n)
 
 proc getTok(p: var SqlParser) =
diff --git a/lib/pure/unidecode/unidecode.nim b/lib/pure/unidecode/unidecode.nim
index 9d8843f06..63ebd8248 100644
--- a/lib/pure/unidecode/unidecode.nim
+++ b/lib/pure/unidecode/unidecode.nim
@@ -61,7 +61,6 @@ proc unidecode*(s: string): string =
   ##
   ## Results in: "Bei Jing"
   ##
-  assert(not isNil(translationTable))
   result = ""
   for r in runes(s):
     var c = int(r)
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 1a9e4ae26..82f88a996 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -172,34 +172,30 @@ proc documentElement*(doc: PDocument): PElement =
 proc findNodes(nl: PNode, name: string): seq[PNode] =
   # Made for getElementsByTagName
   var r: seq[PNode] = @[]
-  if isNil(nl.childNodes): return @[]
-  if nl.childNodes.len() == 0: return @[]
+  if nl.childNodes.len == 0: return @[]
 
   for i in items(nl.childNodes):
     if i.fNodeType == ElementNode:
       if i.fNodeName == name or name == "*":
         r.add(i)
 
-      if not isNil(i.childNodes):
-        if i.childNodes.len() != 0:
-          r.add(findNodes(i, name))
+      if i.childNodes.len() != 0:
+        r.add(findNodes(i, name))
 
   return r
 
 proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
   # Made for getElementsByTagNameNS
   var r: seq[PNode] = @[]
-  if isNil(nl.childNodes): return @[]
-  if nl.childNodes.len() == 0: return @[]
+  if nl.childNodes.len == 0: return @[]
 
   for i in items(nl.childNodes):
     if i.fNodeType == ElementNode:
       if (i.fNamespaceURI == namespaceURI or namespaceURI == "*") and (i.fLocalName == localName or localName == "*"):
         r.add(i)
 
-      if not isNil(i.childNodes):
-        if i.childNodes.len() != 0:
-          r.add(findNodesNS(i, namespaceURI, localName))
+      if i.childNodes.len != 0:
+        r.add(findNodesNS(i, namespaceURI, localName))
 
   return r
 
@@ -233,8 +229,8 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
   # Exceptions
   if qualifiedName.contains(':'):
     let qfnamespaces = qualifiedName.toLowerAscii().split(':')
-    if isNil(namespaceURI):
-      raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
+    if namespaceURI.len == 0:
+      raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
     elif qfnamespaces[0] == "xml" and
         namespaceURI != "http://www.w3.org/XML/1998/namespace" and
         qfnamespaces[1] notin stdattrnames:
@@ -312,8 +308,8 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
   ## Creates an element of the given qualified name and namespace URI.
   if qualifiedName.contains(':'):
     let qfnamespaces = qualifiedName.toLowerAscii().split(':')
-    if isNil(namespaceURI):
-      raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
+    if namespaceURI.len == 0:
+      raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
     elif qfnamespaces[0] == "xml" and
         namespaceURI != "http://www.w3.org/XML/1998/namespace" and
         qfnamespaces[1] notin stdattrnames:
@@ -453,7 +449,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
 proc firstChild*(n: PNode): PNode =
   ## Returns this node's first child
 
-  if not isNil(n.childNodes) and n.childNodes.len() > 0:
+  if n.childNodes.len > 0:
     return n.childNodes[0]
   else:
     return nil
@@ -461,8 +457,8 @@ proc firstChild*(n: PNode): PNode =
 proc lastChild*(n: PNode): PNode =
   ## Returns this node's last child
 
-  if not isNil(n.childNodes) and n.childNodes.len() > 0:
-    return n.childNodes[n.childNodes.len() - 1]
+  if n.childNodes.len > 0:
+    return n.childNodes[n.childNodes.len - 1]
   else:
     return nil
 
@@ -482,7 +478,7 @@ proc `namespaceURI=`*(n: PNode, value: string) =
 proc nextSibling*(n: PNode): PNode =
   ## Returns the next sibling of this node
 
-  if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes):
+  if isNil(n.fParentNode):
     return nil
   var nLow: int = low(n.fParentNode.childNodes)
   var nHigh: int = high(n.fParentNode.childNodes)
@@ -514,7 +510,7 @@ proc parentNode*(n: PNode): PNode =
 proc previousSibling*(n: PNode): PNode =
   ## Returns the previous sibling of this node
 
-  if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes):
+  if isNil(n.fParentNode):
     return nil
   var nLow: int = low(n.fParentNode.childNodes)
   var nHigh: int = high(n.fParentNode.childNodes)
@@ -531,8 +527,8 @@ proc `prefix=`*(n: PNode, value: string) =
   if illegalChars in value:
     raise newException(EInvalidCharacterErr, "Invalid character")
 
-  if isNil(n.fNamespaceURI):
-    raise newException(ENamespaceErr, "namespaceURI cannot be nil")
+  if n.fNamespaceURI.len == 0:
+    raise newException(ENamespaceErr, "namespaceURI cannot be empty")
   elif value.toLowerAscii() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace":
     raise newException(ENamespaceErr,
       "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
@@ -557,10 +553,9 @@ proc appendChild*(n: PNode, newChild: PNode) =
   ## If the newChild is already in the tree, it is first removed.
 
   # Check if n contains newChild
-  if not isNil(n.childNodes):
-    for i in low(n.childNodes)..high(n.childNodes):
-      if n.childNodes[i] == newChild:
-        raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
+  for i in low(n.childNodes)..high(n.childNodes):
+    if n.childNodes[i] == newChild:
+      raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
 
   # Check if newChild is from this nodes document
   if n.fOwnerDocument != newChild.fOwnerDocument:
@@ -572,7 +567,8 @@ proc appendChild*(n: PNode, newChild: PNode) =
   if n.nodeType in childlessObjects:
     raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
 
-  if isNil(n.childNodes): n.childNodes = @[]
+  when not defined(nimNoNilSeqs):
+    if isNil(n.childNodes): n.childNodes = @[]
 
   newChild.fParentNode = n
   for i in low(n.childNodes)..high(n.childNodes):
@@ -597,10 +593,10 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     newNode = PElement(n)
     # Import the childNodes
     var tmp: seq[PNode] = n.childNodes
-    n.childNodes = @[]
-    if deep and not isNil(tmp):
-      for i in low(tmp.len())..high(tmp.len()):
-        n.childNodes.add(cloneNode(tmp[i], deep))
+    newNode.childNodes = @[]
+    if deep:
+      for i in low(n.childNodes)..high(n.childNodes):
+        newNode.childNodes.add(cloneNode(n.childNodes[i], deep))
     return newNode
   else:
     var newNode: PNode
@@ -610,11 +606,11 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
 
 proc hasAttributes*(n: PNode): bool =
   ## Returns whether this node (if it is an element) has any attributes.
-  return not isNil(n.attributes) and n.attributes.len() > 0
+  return n.attributes.len > 0
 
 proc hasChildNodes*(n: PNode): bool =
   ## Returns whether this node has any children.
-  return not isNil(n.childNodes) and n.childNodes.len() > 0
+  return n.childNodes.len > 0
 
 proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   ## Inserts the node ``newChild`` before the existing child node ``refChild``.
@@ -624,9 +620,6 @@ proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   if n.fOwnerDocument != newChild.fOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if isNil(n.childNodes):
-    n.childNodes = @[]
-
   for i in low(n.childNodes)..high(n.childNodes):
     if n.childNodes[i] == refChild:
       n.childNodes.insert(newChild, i - 1)
@@ -641,7 +634,7 @@ proc isSupported*(n: PNode, feature: string, version: string): bool =
 
 proc isEmpty(s: string): bool =
 
-  if isNil(s) or s == "":
+  if s == "":
     return true
   for i in items(s):
     if i != ' ':
@@ -655,7 +648,7 @@ proc normalize*(n: PNode) =
 
   var newChildNodes: seq[PNode] = @[]
   while true:
-    if isNil(n.childNodes) or i >= n.childNodes.len:
+    if i >= n.childNodes.len:
       break
     if n.childNodes[i].nodeType == TextNode:
 
@@ -679,12 +672,11 @@ proc normalize*(n: PNode) =
 
 proc removeChild*(n: PNode, oldChild: PNode): PNode =
   ## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
-  if not isNil(n.childNodes):
-    for i in low(n.childNodes)..high(n.childNodes):
-      if n.childNodes[i] == oldChild:
-        result = n.childNodes[i]
-        n.childNodes.delete(i)
-        return
+  for i in low(n.childNodes)..high(n.childNodes):
+    if n.childNodes[i] == oldChild:
+      result = n.childNodes[i]
+      n.childNodes.delete(i)
+      return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -695,12 +687,11 @@ proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
   if n.fOwnerDocument != newChild.fOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if not isNil(n.childNodes):
-    for i in low(n.childNodes)..high(n.childNodes):
-      if n.childNodes[i] == oldChild:
-        result = n.childNodes[i]
-        n.childNodes[i] = newChild
-        return
+  for i in low(n.childNodes)..high(n.childNodes):
+    if n.childNodes[i] == oldChild:
+      result = n.childNodes[i]
+      n.childNodes[i] = newChild
+      return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -764,11 +755,10 @@ proc removeNamedItemNS*(nList: var seq[PNode], namespaceURI: string, localName:
 proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if not isNil(nList):
-    if nList.len() > 0:
-      #Check if newChild is from this nodes document
-      if nList[0].fOwnerDocument != arg.fOwnerDocument:
-        raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
+  if nList.len > 0:
+    #Check if newChild is from this nodes document
+    if nList[0].fOwnerDocument != arg.fOwnerDocument:
+      raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions End
 
   var item: PNode = nList.getNamedItem(arg.nodeName())
@@ -788,11 +778,10 @@ proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
 proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if not isNil(nList):
-    if nList.len() > 0:
-      # Check if newChild is from this nodes document
-      if nList[0].fOwnerDocument != arg.fOwnerDocument:
-        raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
+  if nList.len > 0:
+    # Check if newChild is from this nodes document
+    if nList[0].fOwnerDocument != arg.fOwnerDocument:
+      raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
   if not isNil(arg.fOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@@ -814,11 +803,10 @@ proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
 
 proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if not isNil(nList):
-    if nList.len() > 0:
-      # Check if newChild is from this nodes document
-      if nList[0].fOwnerDocument != arg.fOwnerDocument:
-        raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
+  if nList.len > 0:
+    # Check if newChild is from this nodes document
+    if nList[0].fOwnerDocument != arg.fOwnerDocument:
+      raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions end
 
   var item: PNode = nList.getNamedItemNS(arg.namespaceURI(), arg.localName())
@@ -837,11 +825,10 @@ proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
 
 proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if not isNil(nList):
-    if nList.len() > 0:
-      # Check if newChild is from this nodes document
-      if nList[0].fOwnerDocument != arg.fOwnerDocument:
-        raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
+  if nList.len > 0:
+    # Check if newChild is from this nodes document
+    if nList[0].fOwnerDocument != arg.fOwnerDocument:
+      raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
   if not isNil(arg.fOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@@ -868,17 +855,14 @@ proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
 # Attributes
 proc name*(a: PAttr): string =
   ## Returns the name of the Attribute
-
   return a.fName
 
 proc specified*(a: PAttr): bool =
   ## Specifies whether this attribute was specified in the original document
-
   return a.fSpecified
 
 proc ownerElement*(a: PAttr): PElement =
   ## Returns this Attributes owner element
-
   return a.fOwnerElement
 
 # Element
@@ -886,14 +870,11 @@ proc ownerElement*(a: PAttr): PElement =
 
 proc tagName*(el: PElement): string =
   ## Returns the Element Tag Name
-
   return el.fTagName
 
 # Procedures
 proc getAttribute*(el: PNode, name: string): string =
   ## Retrieves an attribute value by ``name``
-  if isNil(el.attributes):
-    return ""
   var attribute = el.attributes.getNamedItem(name)
   if not isNil(attribute):
     return attribute.value
@@ -902,8 +883,6 @@ proc getAttribute*(el: PNode, name: string): string =
 
 proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string =
   ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
-  if isNil(el.attributes):
-    return ""
   var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
   if not isNil(attribute):
     return attribute.value
@@ -913,14 +892,10 @@ proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string
 proc getAttributeNode*(el: PElement, name: string): PAttr =
   ## Retrieves an attribute node by ``name``
   ## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
-  if isNil(el.attributes):
-    return nil
   return el.attributes.getNamedItem(name)
 
 proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
   ## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
-  if isNil(el.attributes):
-    return nil
   return el.attributes.getNamedItemNS(namespaceURI, localName)
 
 proc getElementsByTagName*(el: PElement, name: string): seq[PNode] =
@@ -938,41 +913,34 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
 proc hasAttribute*(el: PElement, name: string): bool =
   ## Returns ``true`` when an attribute with a given ``name`` is specified
   ## on this element , ``false`` otherwise.
-  if isNil(el.attributes):
-    return false
   return not isNil(el.attributes.getNamedItem(name))
 
 proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
   ## Returns ``true`` when an attribute with a given ``localName`` and
   ## ``namespaceURI`` is specified on this element , ``false`` otherwise
-  if isNil(el.attributes):
-    return false
   return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName))
 
 proc removeAttribute*(el: PElement, name: string) =
   ## Removes an attribute by ``name``
-  if not isNil(el.attributes):
-    for i in low(el.attributes)..high(el.attributes):
-      if el.attributes[i].fName == name:
-        el.attributes.delete(i)
+  for i in low(el.attributes)..high(el.attributes):
+    if el.attributes[i].fName == name:
+      el.attributes.delete(i)
 
 proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
   ## Removes an attribute by ``localName`` and ``namespaceURI``
-  if not isNil(el.attributes):
-    for i in low(el.attributes)..high(el.attributes):
-      if el.attributes[i].fNamespaceURI == namespaceURI and
-          el.attributes[i].fLocalName == localName:
-        el.attributes.delete(i)
+  for i in low(el.attributes)..high(el.attributes):
+    if el.attributes[i].fNamespaceURI == namespaceURI and
+        el.attributes[i].fLocalName == localName:
+      el.attributes.delete(i)
 
 proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
   ## Removes the specified attribute node
   ## If the attribute node cannot be found raises ``ENotFoundErr``
-  if not isNil(el.attributes):
-    for i in low(el.attributes)..high(el.attributes):
-      if el.attributes[i] == oldAttr:
-        result = el.attributes[i]
-        el.attributes.delete(i)
-        return
+  for i in low(el.attributes)..high(el.attributes):
+    if el.attributes[i] == oldAttr:
+      result = el.attributes[i]
+      el.attributes.delete(i)
+      return
 
   raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
 
@@ -991,7 +959,6 @@ proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
 
-  if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItem(newAttr)
 
 proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
@@ -1009,7 +976,6 @@ proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
 
-  if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItemNS(newAttr)
 
 proc setAttribute*(el: PElement, name: string, value: string) =
@@ -1057,9 +1023,9 @@ proc splitData*(textNode: PText, offset: int): PText =
 
   var left: string = textNode.data.substr(0, offset)
   textNode.data = left
-  var right: string = textNode.data.substr(offset, textNode.data.len())
+  var right: string = textNode.data.substr(offset, textNode.data.len)
 
-  if not isNil(textNode.fParentNode) and not isNil(textNode.fParentNode.childNodes):
+  if not isNil(textNode.fParentNode) and textNode.fParentNode.childNodes.len > 0:
     for i in low(textNode.fParentNode.childNodes)..high(textNode.fParentNode.childNodes):
       if textNode.fParentNode.childNodes[i] == textNode:
         var newNode: PText = textNode.fOwnerDocument.createTextNode(right)
@@ -1098,11 +1064,10 @@ proc escapeXml*(s: string): string =
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
   result = spaces(indent) & "<" & n.nodeName
-  if not isNil(n.attributes):
-    for i in items(n.attributes):
-      result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
+  for i in items(n.attributes):
+    result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
 
-  if isNil(n.childNodes) or n.childNodes.len() == 0:
+  if n.childNodes.len == 0:
     result.add("/>") # No idea why this doesn't need a \n :O
   else:
     # End the beginning of this tag
@@ -1134,3 +1099,4 @@ proc `$`*(doc: PDocument): string =
   ## Converts a PDocument object into a string representation of it's XML
   result = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
   result.add(nodeToXml(doc.documentElement))
+  
\ No newline at end of file