diff --git a/source/dub/description.d b/source/dub/description.d index c4596a0..9f519cb 100644 --- a/source/dub/description.d +++ b/source/dub/description.d @@ -28,7 +28,7 @@ PackageDescription[] packages; /// All packages in the dependency tree TargetDescription[] targets; /// Build targets @ignore size_t[string] targetLookup; /// Target index by package name name - + /// Targets by name ref inout(TargetDescription) lookupTarget(string name) inout { diff --git a/source/dub/dub.d b/source/dub/dub.d index d23131e..32c84bf 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -149,7 +149,7 @@ loading a package. This constructor corresponds to the "--bare" option of the command line - interface. Use + interface. Use */ this(Path override_path) { @@ -243,7 +243,7 @@ Single-file packages are D files that contain a package receipe comment at their top. A recipe comment must be a nested `/+ ... +/` style - comment, containing the virtual recipe file name and a colon, followed by the + comment, containing the virtual recipe file name and a colon, followed by the recipe contents (what would normally be in dub.sdl/dub.json). Example: @@ -736,7 +736,7 @@ logInfo("Removing %s in %s", pack.name, pack.path.toNativeString()); if (!m_dryRun) m_packageManager.remove(pack); } - + /// Compatibility overload. Use the version without a `force_remove` argument instead. void remove(in Package pack, bool force_remove) { diff --git a/source/dub/generators/cmake.d b/source/dub/generators/cmake.d index fcf0b94..269c136 100644 --- a/source/dub/generators/cmake.d +++ b/source/dub/generators/cmake.d @@ -26,7 +26,7 @@ { super(project); } - + override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) { auto script = appender!(char[]); @@ -34,45 +34,45 @@ bool[string] visited; Path projectRoot = m_project.rootPackage.path; Path cmakeListsPath = projectRoot ~ "CMakeLists.txt"; - + foreach(name, info; targets) { if(visited.get(name, false)) continue; - + visited[name] = true; name = name.sanitize; string targetType; string libType; bool addTarget = true; - + switch(info.buildSettings.targetType) with(TargetType) { case autodetect: throw new Exception("Don't know what to do about autodetect target type"); case executable: targetType = "executable"; - + break; case dynamicLibrary: libType = "SHARED"; - + goto case; case library: case staticLibrary: targetType = "library"; - + break; case sourceLibrary: addTarget = false; - + break; case none: continue; default: assert(false); } - + script.put("include(UseD)\n"); script.put( "add_d_conditions(VERSION %s DEBUG %s)\n".format( @@ -80,17 +80,17 @@ info.buildSettings.debugVersions.dup.join(" "), ) ); - + foreach(directory; info.buildSettings.importPaths) script.put("include_directories(%s)\n".format(directory.sanitizeSlashes)); - + if(addTarget) { script.put("add_%s(%s %s\n".format(targetType, name, libType)); - + foreach(file; info.buildSettings.sourceFiles) script.put(" %s\n".format(file.sanitizeSlashes)); - + script.put(")\n"); script.put( "target_link_libraries(%s %s %s)\n".format( @@ -106,16 +106,16 @@ ) ~ "\n" ); } - + string filename = (projectRoot ~ "%s.cmake".format(name)).toNativeString; File file = File(filename, "w"); - + file.write(script.data); file.close; script.shrinkTo(0); scripts.put(filename); } - + if(!cmakeListsPath.existsFile) { logWarn("You must use a fork of CMake which has D support for these scripts to function properly."); @@ -123,12 +123,12 @@ logInfo("Generating default CMakeLists.txt"); script.put("cmake_minimum_required(VERSION 3.0)\n"); script.put("project(%s D)\n".format(m_project.rootPackage.name)); - + foreach(path; scripts.data) script.put("include(%s)\n".format(path)); - + File file = File(cmakeListsPath.toNativeString, "w"); - + file.write(script.data); file.close; } diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index c5f4b79..7b67e52 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -363,7 +363,7 @@ in BuildSettings buildsettings, Path target_path, bool generate_binary) { import std.path : globMatch; - + if (buildsettings.postGenerateCommands.length && !isRecursiveInvocation(pack.name)) { logInfo("Running post-generate commands for %s...", pack.name); runBuildCommands(buildsettings.postGenerateCommands, pack, proj, settings, buildsettings); @@ -513,7 +513,7 @@ env["DUB_PARALLEL_BUILD"] = settings.parallelBuild? "TRUE" : ""; env["DUB_RUN_ARGS"] = (cast(string[])settings.runArgs).map!(escapeShellFileName).join(" "); - + auto depNames = proj.dependencies.map!((a) => a.name).array(); storeRecursiveInvokations(env, proj.rootPackage.name ~ depNames); runCommands(commands, env); diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d index c6ebdd3..c22fcb1 100644 --- a/source/dub/generators/sublimetext.d +++ b/source/dub/generators/sublimetext.d @@ -34,7 +34,7 @@ { auto buildSettings = targets[m_project.name].buildSettings; logDebug("About to generate sublime project for %s.", m_project.rootPackage.name); - + auto root = Json([ "folders": targets.byValue.map!(f => targetFolderJson(f)).array.Json, "build_systems": buildSystems(settings.platform), @@ -100,7 +100,7 @@ "variants": [ [ "name": "Run".Json, - "cmd": ["dub", "run", "--build=" ~ buildType, "--arch=" ~ arch, "--compiler="~buildPlatform.compilerBinary].map!Json.array.Json, + "cmd": ["dub", "run", "--build=" ~ buildType, "--arch=" ~ arch, "--compiler="~buildPlatform.compilerBinary].map!Json.array.Json, ].Json ].array.Json, ]); diff --git a/source/dub/internal/libInputVisitor.d b/source/dub/internal/libInputVisitor.d index ba091b0..d388b78 100644 --- a/source/dub/internal/libInputVisitor.d +++ b/source/dub/internal/libInputVisitor.d @@ -12,17 +12,17 @@ To Public License, Version 2, as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 -Copyright (C) 2004 Sam Hocevar +Copyright (C) 2004 Sam Hocevar -Everyone is permitted to copy and distribute verbatim or modified -copies of this license document, and changing it is allowed as long -as the name is changed. +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. +/ @@ -50,7 +50,7 @@ { obj.visit(this); } - + private void ensureStarted() { if(!started) @@ -59,7 +59,7 @@ started = true; } } - + // Member 'front' must be a function due to DMD Issue #5403 private Elem _front; @property Elem front() @@ -67,19 +67,19 @@ ensureStarted(); return _front; } - + void popFront() { ensureStarted(); call(); } - + @property bool empty() { ensureStarted(); return state == Fiber.State.TERM; } - + void yield(Elem elem) { _front = elem; diff --git a/source/dub/internal/sdlang/ast.d b/source/dub/internal/sdlang/ast.d index cf4f0e0..cf0776c 100644 --- a/source/dub/internal/sdlang/ast.d +++ b/source/dub/internal/sdlang/ast.d @@ -27,7 +27,7 @@ { Value value; Location location; - + private Tag _parent; /// Get parent tag. To set a parent, attach this Attribute to its intended /// parent tag by calling 'Tag.add(...)', or by passing it to @@ -62,7 +62,7 @@ else _namespace = value; } - + private string _name; /// Not including namespace. Use 'fullName' if you want the namespace included. @property string name() @@ -75,7 +75,7 @@ if(_parent && _name != value) { _parent.updateId++; - + void removeFromGroupedLookup(string ns) { // Remove from _parent._attributes[ns] @@ -83,14 +83,14 @@ auto targetIndex = sameNameAttrs.countUntil(this); _parent._attributes[ns][_name].removeIndex(targetIndex); } - + // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); // Change name _name = value; - + // Add to new locations in _parent._attributes _parent._attributes[_namespace][_name] ~= this; _parent._attributes["*"][_name] ~= this; @@ -111,7 +111,7 @@ this.location = location; this.value = value; } - + this(string name, Value value, Location location = Location(0, 0, 0)) { this._namespace = ""; @@ -119,14 +119,14 @@ this.location = location; this.value = value; } - + /// Removes 'this' from its parent, if any. Returns 'this' for chaining. /// Inefficient ATM, but it works. Attribute remove() { if(!_parent) return this; - + void removeFromGroupedLookup(string ns) { // Remove from _parent._attributes[ns] @@ -134,7 +134,7 @@ auto targetIndex = sameNameAttrs.countUntil(this); _parent._attributes[ns][_name].removeIndex(targetIndex); } - + // Remove from _parent._attributes removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); @@ -147,13 +147,13 @@ auto sameNamespaceAttrs = _parent.attributeIndicies[_namespace]; auto attrIndiciesIndex = sameNamespaceAttrs.countUntil(allAttrsIndex); _parent.attributeIndicies[_namespace].removeIndex(attrIndiciesIndex); - + // Fixup other indicies foreach(ns, ref nsAttrIndicies; _parent.attributeIndicies) foreach(k, ref v; nsAttrIndicies) if(v > allAttrsIndex) v--; - + _parent.removeNamespaceIfEmpty(_namespace); _parent.updateId++; _parent = null; @@ -171,7 +171,7 @@ _name == a._name && value == a.value; } - + string toSDLString()() { Appender!string sink; @@ -232,7 +232,7 @@ else _namespace = value; } - + private string _name; /// Not including namespace. Use 'fullName' if you want the namespace included. @property string name() @@ -245,7 +245,7 @@ if(_parent && _name != value) { _parent.updateId++; - + void removeFromGroupedLookup(string ns) { // Remove from _parent._tags[ns] @@ -253,14 +253,14 @@ auto targetIndex = sameNameTags.countUntil(this); _parent._tags[ns][_name].removeIndex(targetIndex); } - + // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); - + // Change name _name = value; - + // Add to new locations in _parent._tags _parent._tags[_namespace][_name] ~= this; _parent._tags["*"][_name] ~= this; @@ -268,7 +268,7 @@ else _name = value; } - + /// This tag's name, including namespace if one exists. @property string fullName() { @@ -279,7 +279,7 @@ // could invalidate existing ranges. This way, the ranges can detect when // they've been invalidated. private size_t updateId=0; - + this(Tag parent = null) { if(parent) @@ -304,7 +304,7 @@ if(parent) parent.add(this); - + this.values = values; this.add(attributes); this.add(children); @@ -319,7 +319,7 @@ private Attribute[][string][string] _attributes; // attributes[namespace or "*"][name][i] private Tag[][string][string] _tags; // tags[namespace or "*"][name][i] - + /// Adds a Value, Attribute, Tag (or array of such) as a member/child of this Tag. /// Returns 'this' for chaining. /// Throws 'SDLangValidationException' if trying to add an Attribute or Tag @@ -330,7 +330,7 @@ updateId++; return this; } - + ///ditto Tag add(Value[] vals) { @@ -339,7 +339,7 @@ return this; } - + ///ditto Tag add(Attribute attr) { @@ -350,12 +350,12 @@ "Use Attribute.remove() before adding it to another tag." ); } - + if(!allNamespaces.canFind(attr._namespace)) allNamespaces ~= attr._namespace; attr._parent = this; - + allAttributes ~= attr; attributeIndicies[attr._namespace] ~= allAttributes.length-1; _attributes[attr._namespace][attr._name] ~= attr; @@ -364,7 +364,7 @@ updateId++; return this; } - + ///ditto Tag add(Attribute[] attrs) { @@ -373,7 +373,7 @@ return this; } - + ///ditto Tag add(Tag tag) { @@ -387,18 +387,18 @@ if(!allNamespaces.canFind(tag._namespace)) allNamespaces ~= tag._namespace; - + tag._parent = this; allTags ~= tag; tagIndicies[tag._namespace] ~= allTags.length-1; _tags[tag._namespace][tag._name] ~= tag; _tags["*"] [tag._name] ~= tag; - + updateId++; return this; } - + ///ditto Tag add(Tag[] tags) { @@ -407,14 +407,14 @@ return this; } - + /// Removes 'this' from its parent, if any. Returns 'this' for chaining. /// Inefficient ATM, but it works. Tag remove() { if(!_parent) return this; - + void removeFromGroupedLookup(string ns) { // Remove from _parent._tags[ns] @@ -422,7 +422,7 @@ auto targetIndex = sameNameTags.countUntil(this); _parent._tags[ns][_name].removeIndex(targetIndex); } - + // Remove from _parent._tags removeFromGroupedLookup(_namespace); removeFromGroupedLookup("*"); @@ -435,19 +435,19 @@ auto sameNamespaceTags = _parent.tagIndicies[_namespace]; auto tagIndiciesIndex = sameNamespaceTags.countUntil(allTagsIndex); _parent.tagIndicies[_namespace].removeIndex(tagIndiciesIndex); - + // Fixup other indicies foreach(ns, ref nsTagIndicies; _parent.tagIndicies) foreach(k, ref v; nsTagIndicies) if(v > allTagsIndex) v--; - + _parent.removeNamespaceIfEmpty(_namespace); _parent.updateId++; _parent = null; return this; } - + private void removeNamespaceIfEmpty(string namespace) { // If namespace has no attributes, remove it from attributeIndicies/_attributes @@ -463,7 +463,7 @@ tagIndicies.remove(namespace); _tags.remove(namespace); } - + // If namespace is now empty, remove it from allNamespaces if( namespace !in tagIndicies && @@ -474,7 +474,7 @@ allNamespaces = allNamespaces[0..allNamespacesIndex] ~ allNamespaces[allNamespacesIndex+1..$]; } } - + struct NamedMemberRange(T, string membersGrouped) { private Tag tag; @@ -498,7 +498,7 @@ else endIndex = 0; } - + invariant() { assert( @@ -511,7 +511,7 @@ { return frontIndex == endIndex; } - + private size_t frontIndex; @property T front() { @@ -537,13 +537,13 @@ endIndex--; } - + alias length opDollar; @property size_t length() { return endIndex - frontIndex; } - + @property typeof(this) save() { auto r = typeof(this)(this.tag, this.namespace, this.name, this.updateId); @@ -551,25 +551,25 @@ r.endIndex = this.endIndex; return r; } - + typeof(this) opSlice() { return save(); } - + typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; - + if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); - + return r; } @@ -604,10 +604,10 @@ initialEndIndex = mixin("tag."~memberIndicies~"[namespace].length"); else initialEndIndex = 0; - + endIndex = initialEndIndex; } - + invariant() { assert( @@ -620,7 +620,7 @@ { return frontIndex == endIndex; } - + private size_t frontIndex; @property T front() { @@ -646,13 +646,13 @@ endIndex--; } - + alias length opDollar; @property size_t length() { return endIndex - frontIndex; } - + @property typeof(this) save() { auto r = typeof(this)(this.tag, this.namespace, this.isMaybe); @@ -662,28 +662,28 @@ r.updateId = this.updateId; return r; } - + typeof(this) opSlice() { return save(); } - + typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; - + if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); - + return r; } - + T opIndex(size_t index) { if(empty) @@ -694,7 +694,7 @@ else return mixin("tag."~allMembers~"[ tag."~memberIndicies~"[namespace][frontIndex+index] ]"); } - + alias NamedMemberRange!(T,membersGrouped) ThisNamedMemberRange; ThisNamedMemberRange opIndex(string name) { @@ -707,10 +707,10 @@ "range and that you aren't using a slice of the range." ); } - + if(!isMaybe && empty) throw new SDLangRangeException("Range is empty"); - + if(!isMaybe && name !in this) throw new SDLangRangeException(`No such `~T.stringof~` named: "`~name~`"`); @@ -728,10 +728,10 @@ "range and that you aren't using a slice of the range." ); } - + return namespace in mixin("tag."~membersGrouped) && - name in mixin("tag."~membersGrouped~"[namespace]") && + name in mixin("tag."~membersGrouped~"[namespace]") && mixin("tag."~membersGrouped~"[namespace][name].length") > 0; } } @@ -758,12 +758,12 @@ "This range has been invalidated by a change to the tag." ); } - + @property bool empty() { return frontIndex == endIndex; } - + private size_t frontIndex; @property NamespaceAccess front() { @@ -773,7 +773,7 @@ { if(empty) throw new SDLangRangeException("Range is empty"); - + frontIndex++; } @@ -786,16 +786,16 @@ { if(empty) throw new SDLangRangeException("Range is empty"); - + endIndex--; } - + alias length opDollar; @property size_t length() { return endIndex - frontIndex; } - + @property NamespaceRange save() { auto r = NamespaceRange(this.tag, this.isMaybe); @@ -804,28 +804,28 @@ r.updateId = this.updateId; return r; } - + typeof(this) opSlice() { return save(); } - + typeof(this) opSlice(size_t start, size_t end) { auto r = save(); r.frontIndex = this.frontIndex + start; r.endIndex = this.frontIndex + end; - + if( r.frontIndex > this.endIndex || r.endIndex > this.endIndex || r.frontIndex > r.endIndex ) throw new SDLangRangeException("Slice out of range"); - + return r; } - + NamespaceAccess opIndex(size_t index) { if(empty) @@ -838,22 +838,22 @@ TagRange(tag, namespace, isMaybe) ); } - + NamespaceAccess opIndex(string namespace) { if(!isMaybe && empty) throw new SDLangRangeException("Range is empty"); - + if(!isMaybe && namespace !in this) throw new SDLangRangeException(`No such namespace: "`~namespace~`"`); - + return NamespaceAccess( namespace, AttributeRange(tag, namespace, isMaybe), TagRange(tag, namespace, isMaybe) ); } - + /// Inefficient when range is a slice or has used popFront/popBack, but it works. bool opBinaryRight(string op)(string namespace) if(op=="in") { @@ -893,7 +893,7 @@ { return TagRange(this, "", false); } - + /// Access all namespaces in this tag, and the attributes/tags within them. @property NamespaceRange namespaces() { @@ -926,7 +926,7 @@ { return TagRange(tag, "", true); } - + /// Access all namespaces in this tag, and the attributes/tags within them. @property NamespaceRange namespaces() { @@ -944,7 +944,7 @@ ); } } - + /// Access 'attributes', 'tags', 'namespaces' and 'all' like normal, /// except that looking up a non-existant name/namespace with /// opIndex(string) results in an empty array instead of a thrown SDLangRangeException. @@ -952,13 +952,13 @@ { return MaybeAccess(this); } - + override bool opEquals(Object o) { auto t = cast(Tag)o; if(!t) return false; - + if(_namespace != t._namespace || _name != t._name) return false; @@ -969,7 +969,7 @@ allTags .length != t.allTags .length ) return false; - + if(values != t.values) return false; @@ -978,12 +978,12 @@ if(allAttributes != t.allAttributes) return false; - + // Ok because cycles are not allowed //TODO: Actually check for or prevent cycles. return allTags == t.allTags; } - + /// Treats 'this' as the root tag. Note that root tags cannot have /// values or attributes, and cannot be part of a namespace. /// If this isn't a valid root tag, 'SDLangValidationException' will be thrown. @@ -993,7 +993,7 @@ toSDLDocument(sink, indent, indentLevel); return sink.data; } - + ///ditto void toSDLDocument(Sink)(ref Sink sink, string indent="\t", int indentLevel=0) if(isOutputRange!(Sink,char)) @@ -1006,11 +1006,11 @@ if(_namespace != "") throw new SDLangValidationException("Root tags cannot have a namespace."); - + foreach(tag; allTags) tag.toSDLString(sink, indent, indentLevel); } - + /// Output this entire tag in SDL format. Does *not* treat 'this' as /// a root tag. If you intend this to be the root of a standard SDL /// document, use 'toSDLDocument' instead. @@ -1020,21 +1020,21 @@ toSDLString(sink, indent, indentLevel); return sink.data; } - + ///ditto void toSDLString(Sink)(ref Sink sink, string indent="\t", int indentLevel=0) if(isOutputRange!(Sink,char)) { if(_name == "" && values.length == 0) throw new SDLangValidationException("Anonymous tags must have at least one value."); - + if(_name == "" && _namespace != "") throw new SDLangValidationException("Anonymous tags cannot have a namespace."); - + // Indent foreach(i; 0..indentLevel) sink.put(indent); - + // Name if(_namespace != "") { @@ -1042,24 +1042,24 @@ sink.put(':'); } sink.put(_name); - + // Values foreach(i, v; values) { // Omit the first space for anonymous tags if(_name != "" || i > 0) sink.put(' '); - + v.toSDLString(sink); } - + // Attributes foreach(attr; allAttributes) { sink.put(' '); attr.toSDLString(sink); } - + // Child tags bool foundChild=false; foreach(tag; allTags) @@ -1089,7 +1089,7 @@ import std.algorithm : sort; Appender!string buf; - + buf.put("\n"); buf.put("Tag "); if(_namespace != "") @@ -1113,21 +1113,21 @@ string namespaceStr; if(attr._namespace != "") namespaceStr = "["~attr._namespace~"]"; - + buf.put( " %s%s(%s): %s\n".format( namespaceStr, attr._name, .toString(attr.value.type), attr.value ) ); } - + // Children foreach(tagNamespace; _tags.keys.sort()) if(tagNamespace != "*") foreach(tagName; _tags[tagNamespace].keys.sort()) foreach(tag; _tags[tagNamespace][tagName]) buf.put( tag.toDebugString().replace("\n", "\n ") ); - + return buf.data; } } @@ -1147,14 +1147,14 @@ assert(range.empty); return; } - + static bool defaultEquals(E e1, E e2) { return e1 == e2; } if(equals is null) equals = &defaultEquals; - + assert(equals(range.front, expected[0])); assert(equals(range.front, expected[0])); // Ensure consistent result from '.front' assert(equals(range.front, expected[0])); // Ensure consistent result from '.front' @@ -1162,20 +1162,20 @@ assert(equals(range.back, expected[$-1])); assert(equals(range.back, expected[$-1])); // Ensure consistent result from '.back' assert(equals(range.back, expected[$-1])); // Ensure consistent result from '.back' - + // Forward iteration auto original = range.save; auto r2 = range.save; foreach(i; 0..expected.length) { //trace("Forward iteration: ", i); - + // Test length/empty assert(range.length == expected.length - i); assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); - + // Test front assert(equals(range.front, expected[i])); assert(equals(range.front, r2.front)); @@ -1201,7 +1201,7 @@ assert(range.empty); assert(r2.empty); assert(original.length == expected.length); - + // Backwards iteration range = original.save; r2 = original.save; @@ -1214,7 +1214,7 @@ assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); - + // Test front assert(equals(range.front, expected[0])); assert(equals(range.front, r2.front)); @@ -1240,7 +1240,7 @@ assert(range.empty); assert(r2.empty); assert(original.length == expected.length); - + // Random access range = original.save; r2 = original.save; @@ -1253,7 +1253,7 @@ assert(range.length == r2.length); assert(!range.empty); assert(!r2.empty); - + // Test front assert(equals(range.front, expected[0])); assert(equals(range.front, r2.front)); @@ -1278,13 +1278,13 @@ import sdlang.parser; writeln("Unittesting sdlang ast..."); stdout.flush(); - + Tag root; root = parseSource(""); testRandomAccessRange(root.attributes, cast( Attribute[])[]); testRandomAccessRange(root.tags, cast( Tag[])[]); testRandomAccessRange(root.namespaces, cast(Tag.NamespaceAccess[])[]); - + root = parseSource(` blue 3 "Lee" isThree=true blue 5 "Chan" 12345 isThree=false @@ -1293,7 +1293,7 @@ stuff:triangle data:points=3 data:dimensions=2 nothing namespaces small:A=1 med:A=2 big:A=3 small:B=10 big:B=30 - + people visitor:a=1 b=2 { chiyo "Small" "Flies?" nemesis="Car" score=100 yukari @@ -1407,7 +1407,7 @@ ], [chiyo, yukari, sana, tomo, hayama] ); - + assert(blue3 .opEquals( blue3 )); assert(blue5 .opEquals( blue5 )); assert(orange .opEquals( orange )); @@ -1421,19 +1421,19 @@ assert(sana .opEquals( sana )); assert(tomo .opEquals( tomo )); assert(hayama .opEquals( hayama )); - + assert(!blue3.opEquals(orange)); assert(!blue3.opEquals(people)); assert(!blue3.opEquals(sana)); assert(!blue3.opEquals(blue5)); assert(!blue5.opEquals(blue3)); - + alias Tag.NamespaceAccess NSA; static bool namespaceEquals(NSA n1, NSA n2) { return n1.name == n2.name; } - + testRandomAccessRange(root.attributes, cast(Attribute[])[]); testRandomAccessRange(root.tags, [blue3, blue5, nothing, namespaces, people]); testRandomAccessRange(root.namespaces, [NSA(""), NSA("stuff")], &namespaceEquals); @@ -1480,7 +1480,7 @@ assertThrown!SDLangRangeException(root.all.tags["foobar"]); assertThrown!SDLangRangeException(root.attributes["foobar"]); assertThrown!SDLangRangeException(root.all.attributes["foobar"]); - + // DMD Issue #12585 causes a segfault in these two tests when using 2.064 or 2.065, // so work around it. //assertThrown!SDLangRangeException(root.namespaces["foobar"].tags["foobar"]); @@ -1491,7 +1491,7 @@ catch(SDLangRangeException e) didCatch = true; assert(didCatch); - + didCatch = false; try auto x = root.namespaces["foobar"].attributes["foobar"]; @@ -1520,19 +1520,19 @@ testRandomAccessRange(blue3.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(blue3.all.attributes, [ new Attribute("isThree", Value(true)) ]); testRandomAccessRange(blue3.all.tags, cast(Tag[])[]); - + testRandomAccessRange(blue5.attributes, [ new Attribute("isThree", Value(false)) ]); testRandomAccessRange(blue5.tags, cast(Tag[])[]); testRandomAccessRange(blue5.namespaces, [NSA("")], &namespaceEquals); testRandomAccessRange(blue5.all.attributes, [ new Attribute("isThree", Value(false)) ]); testRandomAccessRange(blue5.all.tags, cast(Tag[])[]); - + testRandomAccessRange(orange.attributes, cast(Attribute[])[]); testRandomAccessRange(orange.tags, cast(Tag[])[]); testRandomAccessRange(orange.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(orange.all.attributes, cast(Attribute[])[]); testRandomAccessRange(orange.all.tags, cast(Tag[])[]); - + testRandomAccessRange(square.attributes, [ new Attribute("points", Value(4)), new Attribute("dimensions", Value(2)), @@ -1546,7 +1546,7 @@ new Attribute("points", Value("Still four")), ]); testRandomAccessRange(square.all.tags, cast(Tag[])[]); - + testRandomAccessRange(triangle.attributes, cast(Attribute[])[]); testRandomAccessRange(triangle.tags, cast(Tag[])[]); testRandomAccessRange(triangle.namespaces, [NSA("data")], &namespaceEquals); @@ -1565,13 +1565,13 @@ new Attribute("data", "dimensions", Value(2)), ]); testRandomAccessRange(triangle.all.tags, cast(Tag[])[]); - + testRandomAccessRange(nothing.attributes, cast(Attribute[])[]); testRandomAccessRange(nothing.tags, cast(Tag[])[]); testRandomAccessRange(nothing.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(nothing.all.attributes, cast(Attribute[])[]); testRandomAccessRange(nothing.all.tags, cast(Tag[])[]); - + testRandomAccessRange(namespaces.attributes, cast(Attribute[])[]); testRandomAccessRange(namespaces.tags, cast(Tag[])[]); testRandomAccessRange(namespaces.namespaces, [NSA("small"), NSA("med"), NSA("big")], &namespaceEquals); @@ -1680,19 +1680,19 @@ new Attribute("score", Value(100)), ]); testRandomAccessRange(chiyo.all.tags, cast(Tag[])[]); - + testRandomAccessRange(yukari.attributes, cast(Attribute[])[]); testRandomAccessRange(yukari.tags, cast(Tag[])[]); testRandomAccessRange(yukari.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(yukari.all.attributes, cast(Attribute[])[]); testRandomAccessRange(yukari.all.tags, cast(Tag[])[]); - + testRandomAccessRange(sana.attributes, cast(Attribute[])[]); testRandomAccessRange(sana.tags, cast(Tag[])[]); testRandomAccessRange(sana.namespaces, cast(NSA[])[], &namespaceEquals); testRandomAccessRange(sana.all.attributes, cast(Attribute[])[]); testRandomAccessRange(sana.all.tags, cast(Tag[])[]); - + testRandomAccessRange(people.attributes, [new Attribute("b", Value(2))]); testRandomAccessRange(people.tags, [chiyo, yukari, tomo]); testRandomAccessRange(people.namespaces, [NSA("visitor"), NSA("")], &namespaceEquals); @@ -1712,7 +1712,7 @@ new Attribute("b", Value(2)), ]); testRandomAccessRange(people.all.tags, [chiyo, yukari, sana, tomo, hayama]); - + people.attributes["b"][0].name = "b_"; people.namespaces["visitor"].attributes["a"][0].name = "a_"; people.tags["chiyo"][0].name = "chiyo_"; @@ -1751,7 +1751,7 @@ testRandomAccessRange(people.namespaces["visitor"].tags, [sana_]); testRandomAccessRange(people.namespaces[ ""].tags, [yukari]); testRandomAccessRange(people.all.tags, [yukari, sana_]); - + people.attributes["b_"][0].namespace = "_"; people.namespaces["visitor"].attributes["a_"][0].namespace = "visitor_"; assert("_" in people.namespaces); @@ -1767,7 +1767,7 @@ assert(people.namespaces["_" ].attributes["b_"][0] == new Attribute("_", "b_", Value(2))); assert(people.namespaces["visitor_"].attributes["a_"][0] == new Attribute("visitor_", "a_", Value(1))); assert(people.namespaces["visitor_"].tags["sana_"][0] == sanaVisitor_); - + people.tags["yukari"][0].remove(); people.namespaces["visitor_"].tags["sana_"][0].remove(); people.namespaces["visitor_"].attributes["a_"][0].namespace = "visitor"; @@ -1782,7 +1782,7 @@ testRandomAccessRange(people.namespaces["visitor"].tags, cast(Tag[])[]); testRandomAccessRange(people.namespaces[ ""].tags, cast(Tag[])[]); testRandomAccessRange(people.all.tags, cast(Tag[])[]); - + people.namespaces["visitor"].attributes["a_"][0].remove(); testRandomAccessRange(people.attributes, [new Attribute("b_", Value(2))]); testRandomAccessRange(people.namespaces, [NSA("")], &namespaceEquals); @@ -1794,7 +1794,7 @@ testRandomAccessRange(people.all.attributes, [ new Attribute("b_", Value(2)), ]); - + people.attributes["b_"][0].remove(); testRandomAccessRange(people.attributes, cast(Attribute[])[]); testRandomAccessRange(people.namespaces, cast(NSA[])[], &namespaceEquals); @@ -1811,7 +1811,7 @@ import sdlang.parser; writeln("ast: Regression test issue #11..."); stdout.flush(); - + auto root = parseSource( `// a`); @@ -1829,7 +1829,7 @@ null, "", "child", null, null, null ); - + assert("parent" in root.tags); assert("child" !in root.tags); testRandomAccessRange(root.tags["parent"][0].tags, [child]); diff --git a/source/dub/internal/sdlang/lexer.d b/source/dub/internal/sdlang/lexer.d index 4cc754b..2295ed7 100644 --- a/source/dub/internal/sdlang/lexer.d +++ b/source/dub/internal/sdlang/lexer.d @@ -35,7 +35,7 @@ Token[] lexSource(string source, string filename=null) { auto lexer = scoped!Lexer(source, filename); - + // Can't use 'std.array.array(Range)' because 'lexer' is scoped // and therefore cannot have its reference copied. Appender!(Token[]) tokens; @@ -98,18 +98,18 @@ private size_t posAfterLookahead; // Position after lookahead character (an index into source) private Location tokenStart; // The starting location of the token being lexed - + // Length so far of the token being lexed, not including current char private size_t tokenLength; // Length in UTF-8 code units private size_t tokenLength32; // Length in UTF-32 code units - + // Slight kludge: // If a numeric fragment is found after a Date (separated by arbitrary // whitespace), it could be the "hours" part of a DateTime, or it could // be a separate numeric literal that simply follows a plain Date. If the // latter, then the Date must be emitted, but numeric fragment that was // found after it needs to be saved for the the lexer's next iteration. - // + // // It's a slight kludge, and could instead be implemented as a slightly // kludgey parser hack, but it's the only situation where SDL's lexing // needs to lookahead more than one character, so this is good enough. @@ -121,12 +121,12 @@ Location tokenStart; } private LookaheadTokenInfo lookaheadTokenInfo; - + this(string source=null, string filename=null) { this.filename = filename; this.source = source; - + _front = Token(symbol!"Error", Location()); lookaheadTokenInfo = LookaheadTokenInfo.init; @@ -135,14 +135,14 @@ source = source[ ByteOrderMarks[BOM.UTF8].length .. $ ]; this.source = source; } - + foreach(bom; ByteOrderMarks) if( source.startsWith(bom) ) error(Location(filename,0,0,0), "SDL spec only supports UTF-8, not UTF-16 or UTF-32"); - + if(source == "") mixin(accept!"EOF"); - + // Prime everything hasNextCh = true; nextCh = source.decode(posAfterLookahead); @@ -150,12 +150,12 @@ location = Location(filename, 0, 0, 0); popFront(); } - + @property bool empty() { return _front.symbol == symbol!"EOF"; } - + Token _front; @property Token front() { @@ -183,12 +183,12 @@ tok.data = tokenData; return tok; } - + private @property string tokenData() { return source[ tokenStart.index .. location.index ]; } - + /// Check the lookahead character private bool lookahead(dchar ch) { @@ -228,20 +228,20 @@ if(ch >= '0' && ch <= '9') return true; - + return ch == '+' || ch == '/' || ch == '='; } - + /// Is the current character one that's allowed /// immediately *after* an int/float literal? private bool isEndOfNumber() { if(isEOF) return true; - + return !isDigit(ch) && ch != ':' && ch != '_' && !isAlpha(ch); } - + /// Is current character the last one in an ident? private bool isEndOfIdentCached = false; private bool _isEndOfIdent; @@ -253,10 +253,10 @@ _isEndOfIdent = true; else _isEndOfIdent = !isIdentChar(nextCh); - + isEndOfIdentCached = true; } - + return _isEndOfIdent; } @@ -265,12 +265,12 @@ { if(isAlpha(ch)) return true; - + else if(isNumber(ch)) return true; - + else - return + return ch == '-' || ch == '_' || ch == '.' || @@ -281,7 +281,7 @@ { return ch >= '0' && ch <= '9'; } - + private enum KeywordResult { Accept, // Keyword is matched @@ -350,7 +350,7 @@ hasNextCh = false; return; } - + nextCh = source.decode(posAfterLookahead); isEndOfIdentCached = false; } @@ -370,12 +370,12 @@ if(isEOF) mixin(accept!"EOF"); - + tokenStart = location; tokenLength = 0; tokenLength32 = 0; isEndOfIdentCached = false; - + if(lookaheadTokenInfo.exists) { tokenStart = lookaheadTokenInfo.tokenStart; @@ -385,31 +385,31 @@ lexNumeric(prevLATokenInfo); return; } - + if(ch == '=') { advanceChar(ErrorOnEOF.No); mixin(accept!"="); } - + else if(ch == '{') { advanceChar(ErrorOnEOF.No); mixin(accept!"{"); } - + else if(ch == '}') { advanceChar(ErrorOnEOF.No); mixin(accept!"}"); } - + else if(ch == ':') { advanceChar(ErrorOnEOF.No); mixin(accept!":"); } - + else if(ch == ';') { advanceChar(ErrorOnEOF.No); @@ -421,7 +421,7 @@ advanceChar(cnt, ErrorOnEOF.No); mixin(accept!"EOL"); } - + else if(isAlpha(ch) || ch == '_') lexIdentKeyword(); @@ -430,7 +430,7 @@ else if(ch == '`') lexRawString(); - + else if(ch == '\'') lexCharacter(); @@ -451,7 +451,7 @@ private void lexIdentKeyword() { assert(isAlpha(ch) || ch == '_'); - + // Keyword struct Key { @@ -471,10 +471,10 @@ keywords[4] = Key("null", Value(null )); keywordsInited = true; } - + foreach(ref key; keywords) key.failed = false; - + auto numKeys = keywords.length; do @@ -486,10 +486,10 @@ { case KeywordResult.Accept: mixin(accept!("Value", "key.value")); - + case KeywordResult.Continue: break; - + case KeywordResult.Failed: key.failed = true; numKeys--; @@ -520,13 +520,13 @@ { if(tokenLength == 0) assert(isAlpha(ch) || ch == '_'); - + while(!isEOF && isIdentChar(ch)) advanceChar(ErrorOnEOF.No); mixin(accept!"Ident"); } - + /// Lex regular string private void lexRegularString() { @@ -534,7 +534,7 @@ Appender!string buf; size_t spanStart = nextPos; - + // Doesn't include current character void updateBuf() { @@ -543,7 +543,7 @@ buf.put( source[spanStart..location.index] ); } - + advanceChar(ErrorOnEOF.Yes); while(ch != '"') { @@ -564,7 +564,7 @@ default: wasEscSequence = false; break; } } - + if(wasEscSequence) { advanceChar(ErrorOnEOF.Yes); @@ -582,7 +582,7 @@ advanceChar(ErrorOnEOF.Yes); } - + updateBuf(); advanceChar(ErrorOnEOF.No); // Skip closing double-quote mixin(accept!("Value", "buf.data")); @@ -592,21 +592,21 @@ private void lexRawString() { assert(ch == '`'); - + do advanceChar(ErrorOnEOF.Yes); while(ch != '`'); - + advanceChar(ErrorOnEOF.No); // Skip closing back-tick mixin(accept!("Value", "tokenData[1..$-1]")); } - + /// Lex character literal private void lexCharacter() { assert(ch == '\''); advanceChar(ErrorOnEOF.Yes); // Skip opening single-quote - + dchar value; if(ch == '\\') { @@ -634,25 +634,25 @@ mixin(accept!("Value", "value")); } - + /// Lex base64 binary literal private void lexBinary() { assert(ch == '['); advanceChar(ErrorOnEOF.Yes); - + void eatBase64Whitespace() { while(!isEOF && isWhite(ch)) { if(isNewline(ch)) advanceChar(ErrorOnEOF.Yes); - + if(!isEOF && isWhite(ch)) eatWhite(); } } - + eatBase64Whitespace(); // Iterates all valid base64 characters, ending at ']'. @@ -662,17 +662,17 @@ Lexer lexer; private bool isInited = false; private int numInputCharsMod4 = 0; - + @property bool empty() { if(lexer.ch == ']') { if(numInputCharsMod4 != 0) lexer.error("Length of Base64 encoding must be a multiple of 4. ("~to!string(numInputCharsMod4)~")"); - + return true; } - + return false; } @@ -680,7 +680,7 @@ { return lexer.ch; } - + void popFront() { auto lex = lexer; @@ -692,14 +692,14 @@ numInputCharsMod4++; numInputCharsMod4 %= 4; } - + isInited = true; } - + lex.advanceChar(lex.ErrorOnEOF.Yes); eatBase64Whitespace(); - + if(lex.isEOF) lex.error("Unexpected end of file."); @@ -707,13 +707,13 @@ { if(!lex.isBase64(lex.ch)) lex.error("Invalid character in base64 binary literal."); - + numInputCharsMod4++; numInputCharsMod4 %= 4; } } } - + // This is a slow ugly hack. It's necessary because Base64.decode // currently requires the source to have known length. //TODO: Remove this when DMD issue #9543 is fixed. @@ -729,7 +729,7 @@ outputBuf.put(ch); } } - + try //Base64.decode(Base64InputRange(this), OutputBuf()); Base64.decode(tmpBuf, OutputBuf()); @@ -737,11 +737,11 @@ //TODO: Starting with dmd 2.062, this should be a Base64Exception catch(Exception e) error("Invalid character in base64 binary literal."); - + advanceChar(ErrorOnEOF.No); // Skip ']' mixin(accept!("Value", "outputBuf.data")); } - + private BigInt toBigInt(bool isNegative, string absValue) { auto num = BigInt(absValue); @@ -759,14 +759,14 @@ { if(!isDigit(ch)) error("Expected a digit 0-9."); - + auto spanStart = location.index; - + do { advanceChar(ErrorOnEOF.No); } while(!isEOF && isDigit(ch)); - + return source[spanStart..location.index]; } @@ -811,7 +811,7 @@ mixin(accept!("Value", "num.toLong()")); } - + // Float (32-bit signed)? else if(ch == 'F' || ch == 'f') { @@ -819,7 +819,7 @@ advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } - + // Double float (64-bit signed) with suffix? else if((ch == 'D' || ch == 'd') && !lookahead(':') ) @@ -828,7 +828,7 @@ advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } - + // Decimal (128+ bits signed)? else if( (ch == 'B' || ch == 'b') && @@ -840,15 +840,15 @@ advanceChar(ErrorOnEOF.No); mixin(accept!("Value", "value")); } - + // Some floating point? else if(ch == '.') lexFloatingPoint(firstFragment); - + // Some date? else if(ch == '/' && hasNextCh && isDigit(nextCh)) lexDate(isNegative, firstFragment); - + // Some time span? else if(ch == ':' || ch == 'd') lexTimeSpan(isNegative, firstFragment); @@ -867,15 +867,15 @@ else error("Invalid integer suffix."); } - + /// Lex any floating-point literal (after the initial numeric fragment was lexed) private void lexFloatingPoint(string firstPart) { assert(ch == '.'); advanceChar(ErrorOnEOF.No); - + auto secondPart = lexNumericFragment(); - + try { // Double float (64-bit signed) with suffix? @@ -928,7 +928,7 @@ private Date makeDate(bool isNegative, string yearStr, string monthStr, string dayStr) { BigInt biTmp; - + biTmp = BigInt(yearStr); if(isNegative) biTmp = -biTmp; @@ -940,15 +940,15 @@ if(biTmp < 1 || biTmp > 12) error(tokenStart, "Date's month is out of range."); auto month = biTmp.toInt(); - + biTmp = BigInt(dayStr); if(biTmp < 1 || biTmp > 31) error(tokenStart, "Date's month is out of range."); auto day = biTmp.toInt(); - + return Date(year, month, day); } - + private DateTimeFrac makeDateTimeFrac( bool isNegative, Date date, string hourStr, string minuteStr, string secondStr, string millisecondStr @@ -960,12 +960,12 @@ if(biTmp < int.min || biTmp > int.max) error(tokenStart, "Datetime's hour is out of range."); auto numHours = biTmp.toInt(); - + biTmp = BigInt(minuteStr); if(biTmp < 0 || biTmp > int.max) error(tokenStart, "Datetime's minute is out of range."); auto numMinutes = biTmp.toInt(); - + int numSeconds = 0; if(secondStr != "") { @@ -974,7 +974,7 @@ error(tokenStart, "Datetime's second is out of range."); numSeconds = biTmp.toInt(); } - + int millisecond = 0; if(millisecondStr != "") { @@ -990,7 +990,7 @@ } Duration fracSecs = millisecond.msecs; - + auto offset = hours(numHours) + minutes(numMinutes) + seconds(numSeconds); if(isNegative) @@ -998,7 +998,7 @@ offset = -offset; fracSecs = -fracSecs; } - + return DateTimeFrac(DateTime(date) + offset, fracSecs); } @@ -1047,7 +1047,7 @@ else if(millisecondStr.length == 2) millisecond *= 10; } - + auto duration = dur!"days" (day) + dur!"hours" (hour) + @@ -1057,7 +1057,7 @@ if(isNegative) duration = -duration; - + return duration; } @@ -1067,7 +1067,7 @@ { if(str.length < 2) return Nullable!Duration(); // Unknown timezone - + if(str[0] != '+' && str[0] != '-') return Nullable!Duration(); // Unknown timezone @@ -1085,7 +1085,7 @@ numMinutesStr = str.find(':'); numHoursStr = str[1 .. $-numMinutesStr.length]; } - + long numHours = 0; long numMinutes = 0; bool isUnknown = false; @@ -1133,7 +1133,7 @@ } catch(ConvException e) isUnknown = true; - + if(isUnknown) return Nullable!Duration(); // Unknown timezone @@ -1144,12 +1144,12 @@ // Timezone valid return Nullable!Duration(timeZoneOffset); } - + /// Lex date or datetime (after the initial numeric fragment was lexed) private void lexDate(bool isDateNegative, string yearStr) { assert(ch == '/'); - + // Lex months advanceChar(ErrorOnEOF.Yes); // Skip '/' auto monthStr = lexNumericFragment(); @@ -1159,18 +1159,18 @@ error("Invalid date format: Missing days."); advanceChar(ErrorOnEOF.Yes); // Skip '/' auto dayStr = lexNumericFragment(); - + auto date = makeDate(isDateNegative, yearStr, monthStr, dayStr); if(!isEndOfNumber() && ch != '/') error("Dates cannot have suffixes."); - + // Date? if(isEOF) mixin(accept!("Value", "date")); - + auto endOfDate = location; - + while( !isEOF && ( ch == '\\' || ch == '/' || (isWhite(ch) && !isNewline(ch)) ) @@ -1190,7 +1190,7 @@ // Date? if(isEOF || (!isDigit(ch) && ch != '-')) mixin(accept!("Value", "date", "", "endOfDate.index")); - + auto startOfTime = location; // Is time negative? @@ -1200,7 +1200,7 @@ // Lex hours auto hourStr = ch == '.'? "" : lexNumericFragment(); - + // Lex minutes if(ch != ':') { @@ -1214,7 +1214,7 @@ } advanceChar(ErrorOnEOF.Yes); // Skip ':' auto minuteStr = lexNumericFragment(); - + // Lex seconds, if exists string secondStr; if(ch == ':') @@ -1222,7 +1222,7 @@ advanceChar(ErrorOnEOF.Yes); // Skip ':' secondStr = lexNumericFragment(); } - + // Lex milliseconds, if exists string millisecondStr; if(ch == '.') @@ -1232,25 +1232,25 @@ } auto dateTimeFrac = makeDateTimeFrac(isTimeNegative, date, hourStr, minuteStr, secondStr, millisecondStr); - + // Lex zone, if exists if(ch == '-') { advanceChar(ErrorOnEOF.Yes); // Skip '-' auto timezoneStart = location; - + if(!isAlpha(ch)) error("Invalid timezone format."); - + while(!isEOF && !isWhite(ch)) advanceChar(ErrorOnEOF.No); - + auto timezoneStr = source[timezoneStart.index..location.index]; if(timezoneStr.startsWith("GMT")) { auto isoPart = timezoneStr["GMT".length..$]; auto offset = getTimeZoneOffset(isoPart); - + if(offset.isNull()) { // Unknown time zone @@ -1264,7 +1264,7 @@ mixin(accept!("Value", "SysTime(dateTimeFrac.dateTime, fsecs, timezone)")); } } - + try { auto timezone = PosixTimeZone.getTimeZone(timezoneStr); @@ -1293,7 +1293,7 @@ private void lexTimeSpan(bool isNegative, string firstPart) { assert(ch == ':' || ch == 'd'); - + string dayStr = ""; string hourStr; @@ -1324,7 +1324,7 @@ error("Invalid time span format: Missing seconds."); advanceChar(ErrorOnEOF.Yes); // Skip ':' auto secondStr = lexNumericFragment(); - + // Lex milliseconds, if exists string millisecondStr = ""; if(ch == '.') @@ -1335,7 +1335,7 @@ if(!isEndOfNumber()) error("Time spans cannot have suffixes."); - + auto duration = makeDuration(isNegative, dayStr, hourStr, minuteStr, secondStr, millisecondStr); mixin(accept!("Value", "duration")); } @@ -1354,7 +1354,7 @@ if(isEOF) return; - + Location commentStart; State state = State.normal; bool consumeNewlines = false; @@ -1427,12 +1427,12 @@ } break; - + case State.lineComment: if(lookahead(&isNewline)) state = State.normal; break; - + case State.blockComment: if(ch == '*' && lookahead('/')) { @@ -1441,7 +1441,7 @@ } break; } - + advanceChar(ErrorOnEOF.No); if(isEOF) { @@ -1494,7 +1494,7 @@ if (is_same && test_locations) { is_same = actual.map!(t => t.location).equal(expected.map!(t => t.location)); } - + if(!is_same) { numErrors++; @@ -1548,7 +1548,7 @@ { writeln("Unittesting sdlang lexer..."); stdout.flush(); - + testLex("", []); testLex(" ", []); testLex("\\\n", []); @@ -1604,7 +1604,7 @@ testLexThrows("<"); testLexThrows("*"); testLexThrows(`\`); - + // Integers testLex( "7", [ Token(symbol!"Value",loc,Value(cast( int) 7)) ]); testLex( "-7", [ Token(symbol!"Value",loc,Value(cast( int)-7)) ]); @@ -1624,12 +1624,12 @@ testLexThrows("7A"); testLexThrows("-A"); testLexThrows(`-""`); - + testLex("7;", [ Token(symbol!"Value",loc,Value(cast(int)7)), Token(symbol!"EOL",loc), ]); - + // Floats testLex("1.2F" , [ Token(symbol!"Value",loc,Value(cast( float)1.2)) ]); testLex("1.2f" , [ Token(symbol!"Value",loc,Value(cast( float)1.2)) ]); @@ -1751,7 +1751,7 @@ testLexThrows(`'\`); testLexThrows(`'\'`); testLexThrows("'"); - + // Unicode testLex("日本語", [ Token(symbol!"Ident",loc,Value(null), "日本語") ]); testLex("`おはよう、日本。`", [ Token(symbol!"Value",loc,Value(`おはよう、日本。`)) ]); @@ -1941,12 +1941,12 @@ Token(symbol!"Ident",loc,Value( null),"foo."), Token(symbol!"Value",loc,Value(cast(int)7)) ]); - + testLex(` namespace:person "foo" "bar" 1 23L name.first="ひとみ" name.last="Smith" { namespace:age 37; namespace:favorite_color "blue" // comment somedate 2013/2/22 07:53 -- comment - + inventory /* comment */ { socks } @@ -2000,7 +2000,7 @@ Token(symbol!"}", loc, Value(null), "}"), Token(symbol!"EOL", loc, Value(null), "\n"), ]); - + if(numErrors > 0) stderr.writeln(numErrors, " failed test(s)"); } @@ -2021,7 +2021,7 @@ { writeln("lexer: Regression test issue #11..."); stdout.flush(); - + void test(string input) { testLex( diff --git a/source/dub/internal/sdlang/package.d b/source/dub/internal/sdlang/package.d index c128a46..7f1c67a 100644 --- a/source/dub/internal/sdlang/package.d +++ b/source/dub/internal/sdlang/package.d @@ -68,7 +68,7 @@ stderr.writeln("Usage: sdlang [lex|parse|to-sdl] filename.sdl"); return 1; } - + auto filename = args[2]; try @@ -85,7 +85,7 @@ stderr.writeln(e.msg); return 1; } - + return 0; } @@ -93,28 +93,28 @@ { auto source = cast(string)read(filename); auto lexer = new Lexer(source, filename); - + foreach(tok; lexer) { // Value string value; if(tok.symbol == symbol!"Value") value = tok.value.hasValue? toString(tok.value.type) : "{null}"; - + value = value==""? "\t" : "("~value~":"~tok.value.toString()~") "; // Data auto data = tok.data.replace("\n", "").replace("\r", ""); if(data != "") data = "\t|"~tok.data~"|"; - + // Display writeln( tok.location.toString, ":\t", tok.symbol.name, value, data ); - + if(tok.symbol.name == "Error") break; } diff --git a/source/dub/internal/sdlang/parser.d b/source/dub/internal/sdlang/parser.d index 3e32690..8ccf119 100644 --- a/source/dub/internal/sdlang/parser.d +++ b/source/dub/internal/sdlang/parser.d @@ -173,13 +173,13 @@ private struct PullParser { private Lexer lexer; - + private struct IDFull { string namespace; string name; } - + private void error(string msg) { error(lexer.front.location, msg); @@ -189,20 +189,20 @@ { throw new SDLangParseException(loc, "Error: "~msg); } - + private InputVisitor!(PullParser, ParserEvent) v; - + void visit(InputVisitor!(PullParser, ParserEvent) v) { this.v = v; parseRoot(); } - + private void emit(Event)(Event event) { v.yield( ParserEvent(event) ); } - + /// ::= EOF (Lookaheads: Anything) private void parseRoot() { @@ -213,11 +213,11 @@ emit( FileStartEvent(startLocation) ); parseTags(); - + auto token = lexer.front; if(!token.matches!"EOF"()) error("Expected end-of-file, not " ~ token.symbol.name); - + emit( FileEndEvent(token.location) ); } @@ -283,7 +283,7 @@ parseAttributes(); parseOptChild(); parseTagTerminator(); - + emit( TagEndEvent() ); } @@ -365,7 +365,7 @@ auto value = token.value; //trace("In tag '", parent.fullName, "', found value: ", value); emit( ValueEvent(token.location, value) ); - + lexer.popFront(); } else @@ -401,21 +401,21 @@ auto token = lexer.front; if(!token.matches!"Ident"()) error("Expected attribute name, not "~token.symbol.name); - + auto id = parseIDFull(); - + token = lexer.front; if(!token.matches!"="()) error("Expected '=' after attribute name, not "~token.symbol.name); - + lexer.popFront(); token = lexer.front; if(!token.matches!"Value"()) error("Expected attribute value, not "~token.symbol.name); - + //trace("In tag '", parent.fullName, "', found attribute '", attr.fullName, "'"); emit( AttributeEvent(token.location, id.namespace, id.name, token.value) ); - + lexer.popFront(); } @@ -432,10 +432,10 @@ token = lexer.front; if(!token.matches!"EOL"()) error("Expected newline or semicolon after '{', not "~token.symbol.name); - + lexer.popFront(); parseTags(); - + token = lexer.front; if(!token.matches!"}"()) error("Expected '}' after child tags, not "~token.symbol.name); @@ -447,7 +447,7 @@ // Do nothing, no error. } } - + /// /// ::= EOL (Lookahead: EOL) /// | {empty} (Lookahead: EOF) @@ -472,12 +472,12 @@ private struct DOMParser { Lexer lexer; - + Tag parseRoot() { auto currTag = new Tag(null, null, "root"); currTag.location = Location(lexer.filename, 0, 0, 0); - + auto parser = PullParser(lexer); auto eventRange = inputVisitor!ParserEvent( parser ); foreach(event; eventRange) @@ -486,7 +486,7 @@ { auto newTag = new Tag(currTag, e.namespace, e.name); newTag.location = e.location; - + currTag = newTag; } else if(event.peek!TagEndEvent()) @@ -518,7 +518,7 @@ else parser.error("Internal Error: Received unknown parser event"); } - + return currTag; } } diff --git a/source/dub/internal/sdlang/symbol.d b/source/dub/internal/sdlang/symbol.d index 574d97f..04de244 100644 --- a/source/dub/internal/sdlang/symbol.d +++ b/source/dub/internal/sdlang/symbol.d @@ -50,7 +50,7 @@ { return _name; } - + @disable this(); private this(string name) { diff --git a/source/dub/internal/sdlang/util.d b/source/dub/internal/sdlang/util.d index d73b221..c2e2ac7 100644 --- a/source/dub/internal/sdlang/util.d +++ b/source/dub/internal/sdlang/util.d @@ -29,14 +29,14 @@ int line; /// Zero-indexed int col; /// Zero-indexed, Tab counts as 1 size_t index; /// Index into the source - + this(int line, int col, int index) { this.line = line; this.col = col; this.index = index; } - + this(string file, int line, int col, int index) { this.file = file; @@ -44,7 +44,7 @@ this.col = col; this.index = index; } - + string toString() { return "%s(%s:%s)".format(file, line+1, col+1); @@ -82,7 +82,7 @@ else if(ti == typeid( Duration )) return "Duration"; else if(ti == typeid( ubyte[] )) return "ubyte[]"; else if(ti == typeid( typeof(null) )) return "null"; - + return "{unknown}"; } diff --git a/source/dub/internal/vibecompat/data/json.d b/source/dub/internal/vibecompat/data/json.d index af9c591..4a9bc00 100644 --- a/source/dub/internal/vibecompat/data/json.d +++ b/source/dub/internal/vibecompat/data/json.d @@ -1743,12 +1743,12 @@ case Json.Type.null_: dst.put("null"); break; case Json.Type.bool_: dst.put(cast(bool)json ? "true" : "false"); break; case Json.Type.int_: formattedWrite(dst, "%d", json.get!long); break; - case Json.Type.float_: + case Json.Type.float_: auto d = json.get!double; - if (d != d) + if (d != d) dst.put("undefined"); // JSON has no NaN value so set null else - formattedWrite(dst, "%.16g", json.get!double); + formattedWrite(dst, "%.16g", json.get!double); break; case Json.Type.string: dst.put('\"'); diff --git a/source/dub/internal/vibecompat/data/serialization.d b/source/dub/internal/vibecompat/data/serialization.d index b351324..ccbb115 100644 --- a/source/dub/internal/vibecompat/data/serialization.d +++ b/source/dub/internal/vibecompat/data/serialization.d @@ -184,7 +184,7 @@ string toRepresentation(T value) { return to!string(value.x) ~ "x" ~ to!string(value.y); } - + T fromRepresentation(string value) { string[] fields = value.split('x'); alias fieldT = typeof(T.x); @@ -268,7 +268,7 @@ /// static if (__VERSION__ >= 2065) unittest { import dub.internal.vibecompat.data.json; - + static struct SizeI { int x; int y; @@ -278,7 +278,7 @@ SizeI sizeI = deserializeWithPolicy!(JsonSerializer, SizePol, SizeI)(serializedI); assert(sizeI.x == 1); assert(sizeI.y == 2); - + static struct SizeF { float x; float y; @@ -825,22 +825,22 @@ */ template isPolicySerializable(alias Policy, T) { - enum bool isPolicySerializable = is(typeof(Policy!T.toRepresentation(T.init))) && + enum bool isPolicySerializable = is(typeof(Policy!T.toRepresentation(T.init))) && is(typeof(Policy!T.fromRepresentation(Policy!T.toRepresentation(T.init))) == T); } /// unittest { import std.conv; - + // represented as a string when serialized static struct S { int value; - + // dummy example implementations string toString() const { return value.to!string(); } static S fromString(string s) { return S(s.to!int()); } } - + static assert(isStringSerializable!S); } @@ -865,7 +865,7 @@ /// unittest { import std.conv; - + // To be represented as the boxed value when serialized static struct Box(T) { T value; @@ -883,7 +883,7 @@ auto toRepresentation(S s) { return s.value; } - + S fromRepresentation(typeof(toRepresentation(S.init)) v) { return S(v); } @@ -893,7 +893,7 @@ auto toRepresentation(S s) { return s.get(); } - + S fromRepresentation(typeof(toRepresentation(S.init)) v) { S s; s.get() = v; diff --git a/source/dub/internal/vibecompat/data/utils.d b/source/dub/internal/vibecompat/data/utils.d index 7dbcf46..a967455 100644 --- a/source/dub/internal/vibecompat/data/utils.d +++ b/source/dub/internal/vibecompat/data/utils.d @@ -374,10 +374,10 @@ /** TypeTuple which does not auto-expand. - + Useful when you need to multiple several type tuples as different template argument - list parameters, without merging those. + list parameters, without merging those. */ template Group(T...) { @@ -407,10 +407,10 @@ version (unittest) // NOTE: GDC complains about template definitions in unittest blocks { import std.typetuple; - + alias group = Group!(int, double, string); alias group2 = Group!(); - + template Fake(T...) { int[] expand; diff --git a/source/dub/package_.d b/source/dub/package_.d index 5625088..c499c6e 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -156,7 +156,7 @@ if (recipe_file.empty) recipe_file = findPackageFile(root); - enforce(!recipe_file.empty, + enforce(!recipe_file.empty, "No package file found in %s, expected one of %s" .format(root.toNativeString(), packageInfoFiles.map!(f => cast(string)f.filename).join("/"))); diff --git a/source/dub/platform.d b/source/dub/platform.d index e1df8d6..830c1d4 100644 --- a/source/dub/platform.d +++ b/source/dub/platform.d @@ -144,7 +144,7 @@ So the following strings are valid specifications: `"-windows-x86-dmd"`, `"-dmd"`, `"-arm"`, `"-arm-dmd"`, `"-windows-dmd"` - + Params: platform = The build platform to match agains the platform specification specification = The specification being matched. It must either be an diff --git a/source/dub/project.d b/source/dub/project.d index 0590c24..b8f7813 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -119,7 +119,7 @@ If this function returns `false`, it may be necessary to add more entries to `selections`, or to use `Dub.upgrade` to automatically select all - missing dependencies. + missing dependencies. */ bool hasAllDependencies() const { return m_hasAllDependencies; } @@ -655,7 +655,7 @@ if (usedefflags) { BuildSettings btsettings; m_rootPackage.addBuildTypeSettings(btsettings, platform, build_type); - + if (!for_root_package) { // don't propagate unittest switch to dependencies, as dependent // unit tests aren't run anyway and the additional code may @@ -712,7 +712,7 @@ return listBuildSetting!attributeName(platform, getPackageConfigs(platform, config), projectDescription, compiler, disableEscaping); } - + private string[] listBuildSetting(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription, Compiler compiler, bool disableEscaping) { @@ -721,7 +721,7 @@ else return formatBuildSettingPlain!attributeName(platform, configs, projectDescription); } - + // Output a build setting formatted for a compiler private string[] formatBuildSettingCompiler(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription, Compiler compiler, bool disableEscaping) @@ -753,7 +753,7 @@ case "options": auto bs = buildSettings.dup; bs.dflags = null; - + // Ensure trailing slash on directory paths auto ensureTrailingSlash = (string path) => path.endsWith(dirSeparator) ? path : path ~ dirSeparator; static if (attributeName == "importPaths") @@ -771,9 +771,9 @@ bs.lflags = null; bs.sourceFiles = null; bs.targetType = TargetType.none; // Force Compiler to NOT omit dependency libs when package is a library. - + compiler.prepareBuildSettings(bs, BuildSetting.all & ~to!BuildSetting(attributeName)); - + if (bs.lflags) values = compiler.lflagsToDFlags( bs.lflags ); else if (bs.sourceFiles) @@ -785,7 +785,7 @@ default: assert(0); } - + // Escape filenames and paths if(!disableEscaping) { @@ -800,7 +800,7 @@ case "importPaths": case "stringImportPaths": return values.map!(escapeShellFileName).array(); - + default: return values; } @@ -808,7 +808,7 @@ return values; } - + // Output a build setting without formatting for any particular compiler private string[] formatBuildSettingPlain(string attributeName)(BuildPlatform platform, string[string] configs, ProjectDescription projectDescription) { @@ -819,21 +819,21 @@ enforce(attributeName == "targetType" || projectDescription.lookupRootPackage().targetType != TargetType.none, "Target type is 'none'. Cannot list build settings."); - + static if (attributeName == "targetType") if (projectDescription.rootPackage !in projectDescription.targetLookup) return ["none"]; auto targetDescription = projectDescription.lookupTarget(projectDescription.rootPackage); auto buildSettings = targetDescription.buildSettings; - + // Return any BuildSetting member attributeName as a range of strings. Don't attempt to fixup values. // allowEmptyString: When the value is a string (as opposed to string[]), // is empty string an actual permitted value instead of // a missing value? auto getRawBuildSetting(Package pack, bool allowEmptyString) { auto value = __traits(getMember, buildSettings, attributeName); - + static if( is(typeof(value) == string[]) ) return value; else static if( is(typeof(value) == string) ) @@ -858,7 +858,7 @@ else static assert(false, "Type of BuildSettings."~attributeName~" is unsupported."); } - + // Adjust BuildSetting member attributeName as needed. // Returns a range of strings. auto getFixedBuildSetting(Package pack) { @@ -872,16 +872,16 @@ attributeName == "sourceFiles" || attributeName == "linkerFiles" || attributeName == "importFiles" || attributeName == "stringImportFiles" || attributeName == "copyFiles" || attributeName == "mainSourceFile"; - + // For these, empty string means "main project directory", not "missing value" enum allowEmptyString = attributeName == "targetPath" || attributeName == "workingDirectory"; - + enum isEnumBitfield = attributeName == "requirements" || attributeName == "options"; enum isEnum = attributeName == "targetType"; - + auto values = getRawBuildSetting(pack, allowEmptyString); string fixRelativePath(string importPath) { return buildNormalizedPath(pack.path.toString(), importPath); } static string ensureTrailingSlash(string path) { return path.endsWith(dirSeparator) ? path : path ~ dirSeparator; } @@ -973,7 +973,7 @@ enforce(false, "--data="~requestedData~ " is not a valid option. See 'dub describe --help' for accepted --data= values."); } - + assert(0); } @@ -995,7 +995,7 @@ auto target = projectDescription.lookupTarget(projectDescription.rootPackage); foreach (file; target.buildSettings.sourceFiles.filter!(isLinkerFile)) target.buildSettings.addLinkerFiles(file); - + // Remove linker files from sourceFiles target.buildSettings.sourceFiles = target.buildSettings.sourceFiles diff --git a/source/dub/recipe/sdl.d b/source/dub/recipe/sdl.d index fc4c33f..0e2bab6 100644 --- a/source/dub/recipe/sdl.d +++ b/source/dub/recipe/sdl.d @@ -227,7 +227,7 @@ ret ~= m; return ret; } - + foreach (pack, d; bs.dependencies) { Attribute[] attribs; if (d.path.length) attribs ~= new Attribute(null, "path", Value(d.path.toString())); @@ -518,7 +518,7 @@ p.buildSettings.dflags["-windows"] = ["-a"]; p.buildSettings.lflags[""] = ["-b", "-c"]; auto sdl = toSDL(p).toSDLDocument(); - assert(sdl == + assert(sdl == `name "test" authors "foo" "bar" dflags "-a" platform="windows" diff --git a/source/dub/semver.d b/source/dub/semver.d index 448ac81..99aaad7 100644 --- a/source/dub/semver.d +++ b/source/dub/semver.d @@ -251,7 +251,7 @@ /** Takes a partial version and expands it to a valid SemVer version. - + This function corresponds to the semantivs of the "~>" comparison operator's lower bound. diff --git a/test/describe-dependency-1/otherdir/dummy.d b/test/describe-dependency-1/otherdir/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-1/otherdir/dummy.d +++ b/test/describe-dependency-1/otherdir/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-dependency-1/source/dummy.d b/test/describe-dependency-1/source/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-1/source/dummy.d +++ b/test/describe-dependency-1/source/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-dependency-2/some-extra-string-import-path/dummy.d b/test/describe-dependency-2/some-extra-string-import-path/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-2/some-extra-string-import-path/dummy.d +++ b/test/describe-dependency-2/some-extra-string-import-path/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-dependency-2/some-path/dummy.d b/test/describe-dependency-2/some-path/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-2/some-path/dummy.d +++ b/test/describe-dependency-2/some-path/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-dependency-3/dep3-source/dummy.d b/test/describe-dependency-3/dep3-source/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-3/dep3-source/dummy.d +++ b/test/describe-dependency-3/dep3-source/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-dependency-3/dep3-string-import-path/dummy.d b/test/describe-dependency-3/dep3-string-import-path/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-dependency-3/dep3-string-import-path/dummy.d +++ b/test/describe-dependency-3/dep3-string-import-path/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-project/src/dummy.d b/test/describe-project/src/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-project/src/dummy.d +++ b/test/describe-project/src/dummy.d @@ -1 +1 @@ - + diff --git a/test/describe-project/views/dummy.d b/test/describe-project/views/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/describe-project/views/dummy.d +++ b/test/describe-project/views/dummy.d @@ -1 +1 @@ - + diff --git a/test/issue613-dynlib-pic/source/app.d b/test/issue613-dynlib-pic/source/app.d index 26a3f4d..8b92d48 100644 --- a/test/issue613-dynlib-pic/source/app.d +++ b/test/issue613-dynlib-pic/source/app.d @@ -1,4 +1,4 @@ void test() { - + } \ No newline at end of file diff --git a/test/issue616-describe-vs-generate-commands/src/dummy.d b/test/issue616-describe-vs-generate-commands/src/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/issue616-describe-vs-generate-commands/src/dummy.d +++ b/test/issue616-describe-vs-generate-commands/src/dummy.d @@ -1 +1 @@ - + diff --git a/test/issue616-subpack/src/dummy.d b/test/issue616-subpack/src/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/issue616-subpack/src/dummy.d +++ b/test/issue616-subpack/src/dummy.d @@ -1 +1 @@ - + diff --git a/test/issue616-subsubpack/src/dummy.d b/test/issue616-subsubpack/src/dummy.d index 8d1c8b6..8b13789 100644 --- a/test/issue616-subsubpack/src/dummy.d +++ b/test/issue616-subsubpack/src/dummy.d @@ -1 +1 @@ - + diff --git a/test/issue813-fixed-dependency/main/src/app.d b/test/issue813-fixed-dependency/main/src/app.d index dde0c1e..0b416f0 100644 --- a/test/issue813-fixed-dependency/main/src/app.d +++ b/test/issue813-fixed-dependency/main/src/app.d @@ -3,4 +3,4 @@ void main() { foo(); -} +} diff --git a/test/issue813-pure-sub-dependency/main/src/app.d b/test/issue813-pure-sub-dependency/main/src/app.d index dde0c1e..0b416f0 100644 --- a/test/issue813-pure-sub-dependency/main/src/app.d +++ b/test/issue813-pure-sub-dependency/main/src/app.d @@ -3,4 +3,4 @@ void main() { foo(); -} +} diff --git a/travis-ci.sh b/travis-ci.sh index e2af598..7005767 100755 --- a/travis-ci.sh +++ b/travis-ci.sh @@ -21,3 +21,8 @@ dub fetch doveralls dub run doveralls --compiler=${DC} fi + +# check for trailing whitespace (needs to be done only once per build) +if [ "$COVERAGE" = true ]; then + find . -type f -name '*.d' -exec grep -Hn "[[:blank:]]$" {} \; +fi