Ignore all trailing separators in path.extension.

BUG=https://code.google.com/p/dart/issues/detail?id=10235
R=nweiz@google.com

Review URL: https://codereview.chromium.org//20372002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/path@25509 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/path.dart b/lib/path.dart
index bb88953..4b87cde 100644
--- a/lib/path.dart
+++ b/lib/path.dart
@@ -1043,7 +1043,8 @@
   /// path ends with a trailing separator.
   List<String> separators;
 
-  /// The file extension of the last part, or "" if it doesn't have one.
+  /// The file extension of the last non-empty part, or "" if it doesn't have
+  /// one.
   String get extension => _splitExtension()[1];
 
   /// `true` if this is an absolute path.
@@ -1059,12 +1060,7 @@
     return copy.parts.last;
   }
 
-  String get basenameWithoutExtension {
-    var copy = this.clone();
-    copy.removeTrailingSeparators();
-    if (copy.parts.isEmpty) return root == null ? '' : root;
-    return copy._splitExtension()[0];
-  }
+  String get basenameWithoutExtension => _splitExtension()[0];
 
   bool get hasTrailingSeparator =>
       !parts.isEmpty && (parts.last == '' || separators.last != '');
@@ -1137,13 +1133,15 @@
     return builder.toString();
   }
 
-  /// Splits the last part of the path into a two-element list. The first is
-  /// the name of the file without any extension. The second is the extension
-  /// or "" if it has none.
+  /// Splits the last non-empty part of the path into a `[basename, extension`]
+  /// pair.
+  ///
+  /// Returns a two-element list. The first is the name of the file without any
+  /// extension. The second is the extension or "" if it has none.
   List<String> _splitExtension() {
-    if (parts.isEmpty) return ['', ''];
+    var file = parts.lastWhere((p) => p != '', orElse: () => null);
 
-    var file = parts.last;
+    if (file == null) return ['', ''];
     if (file == '..') return ['..', ''];
 
     var lastDot = file.lastIndexOf('.');
diff --git a/test/posix_test.dart b/test/posix_test.dart
index 3afb3bb..2036393 100644
--- a/test/posix_test.dart
+++ b/test/posix_test.dart
@@ -31,6 +31,8 @@
     expect(builder.extension('a.b/c.d'), '.d');
     expect(builder.extension('~/.bashrc'), '');
     expect(builder.extension(r'a.b\c'), r'.b\c');
+    expect(builder.extension('foo.dart/'), '.dart');
+    expect(builder.extension('foo.dart//'), '.dart');
   });
 
   test('rootPrefix', () {
diff --git a/test/url_test.dart b/test/url_test.dart
index 1cd256d..f1dfcde 100644
--- a/test/url_test.dart
+++ b/test/url_test.dart
@@ -20,6 +20,8 @@
     expect(builder.extension('a.b/c'), '');
     expect(builder.extension('a.b/c.d'), '.d');
     expect(builder.extension(r'a.b\c'), r'.b\c');
+    expect(builder.extension('foo.dart/'), '.dart');
+    expect(builder.extension('foo.dart//'), '.dart');
   });
 
   test('rootPrefix', () {
diff --git a/test/windows_test.dart b/test/windows_test.dart
index 1966b7f..4d830ed 100644
--- a/test/windows_test.dart
+++ b/test/windows_test.dart
@@ -35,6 +35,8 @@
     expect(builder.extension('a.b/c.d'), '.d');
     expect(builder.extension(r'~\.bashrc'), '');
     expect(builder.extension(r'a.b/c'), r'');
+    expect(builder.extension(r'foo.dart\'), '.dart');
+    expect(builder.extension(r'foo.dart\\'), '.dart');
   });
 
   test('rootPrefix', () {