diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html index c3214a9c54a..0e594504353 100644 --- a/pkg/analysis_server/doc/api.html +++ b/pkg/analysis_server/doc/api.html @@ -173,6 +173,22 @@ dt.typeDefinition { errors produced for all files in the actual analysis roots. +
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart index bf5453ea150..644435888d3 100644 --- a/pkg/analysis_server/lib/src/analysis_server.dart +++ b/pkg/analysis_server/lib/src/analysis_server.dart @@ -951,6 +951,7 @@ class AnalysisServerOptions { bool enableIncrementalResolutionApi = false; bool enableIncrementalResolutionValidation = false; bool noErrorNotification = false; + String fileReadMode = 'as-is'; } /** diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart index dc275175add..62d875847a7 100644 --- a/pkg/analysis_server/lib/src/server/driver.dart +++ b/pkg/analysis_server/lib/src/server/driver.dart @@ -122,10 +122,15 @@ class Driver implements ServerStarter { static const String SDK_OPTION = "sdk"; /** - * The name of the option used to disable error notifications. + * The name of the flag used to disable error notifications. */ static const String NO_ERROR_NOTIFICATION = "no-error-notification"; + /** + * The name of the option used to set the file read mode. + */ + static const String FILE_READ_MODE = "file-read-mode"; + /** * The instrumentation server that is to be used by the analysis server. */ @@ -201,6 +206,7 @@ class Driver implements ServerStarter { analysisServerOptions.enableIncrementalResolutionValidation = results[INCREMENTAL_RESOLUTION_VALIDATION]; analysisServerOptions.noErrorNotification = results[NO_ERROR_NOTIFICATION]; + analysisServerOptions.fileReadMode = results[FILE_READ_MODE]; _initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]); @@ -328,6 +334,17 @@ class Driver implements ServerStarter { help: "disable sending all analysis error notifications to the server", defaultsTo: false, negatable: false); + parser.addOption( + FILE_READ_MODE, + help: "an option of the ways files can be read from disk, " + + "some clients normalize end of line characters which would make " + + "the file offset and range information incorrect.", + allowed: ["as-is", "normalize-eol-always"], + allowedHelp: { + "as-is": "file contents are read as-is, no file changes occur", + "normalize-eol-always": + "file contents normalize the end of line characters to the single character new line `\n`" + }, defaultsTo: "as-is"); return parser; } diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart index f2038ecf283..cdc873aad80 100644 --- a/pkg/analysis_server/lib/src/socket_server.dart +++ b/pkg/analysis_server/lib/src/socket_server.dart @@ -62,8 +62,17 @@ class SocketServer { }); return; } - PhysicalResourceProvider resourceProvider = - PhysicalResourceProvider.INSTANCE; + PhysicalResourceProvider resourceProvider; + if (analysisServerOptions.fileReadMode == 'as-is') { + resourceProvider = PhysicalResourceProvider.INSTANCE; + } else if (analysisServerOptions.fileReadMode == 'normalize-eol-always') { + resourceProvider = + new PhysicalResourceProvider(PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS); + } else { + throw new Exception( + 'File read mode was set to the unknown mode: $analysisServerOptions.fileReadMode'); + } + analysisServer = new AnalysisServer( serverChannel, resourceProvider, diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html index aa86cb65d86..ec4e6085703 100644 --- a/pkg/analysis_server/tool/spec/spec_input.html +++ b/pkg/analysis_server/tool/spec/spec_input.html @@ -135,6 +135,22 @@ errors produced for all files in the actual analysis roots. +
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 431e92ca25a..3f3e452a4af 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -19,8 +19,12 @@ import 'file_system.dart';
* A `dart:io` based implementation of [ResourceProvider].
*/
class PhysicalResourceProvider implements ResourceProvider {
+
+ static final NORMALIZE_EOL_ALWAYS =
+ (String string) => string.replaceAll(new RegExp('\r\n?'), '\n');
+
static final PhysicalResourceProvider INSTANCE =
- new PhysicalResourceProvider._();
+ new PhysicalResourceProvider(null);
/**
* The name of the directory containing plugin specific subfolders used to
@@ -28,7 +32,11 @@ class PhysicalResourceProvider implements ResourceProvider {
*/
static final String SERVER_DIR = ".dartServer";
- PhysicalResourceProvider._();
+ PhysicalResourceProvider(String fileReadMode(String s)) {
+ if (fileReadMode != null) {
+ FileBasedSource.fileReadMode = fileReadMode;
+ }
+ }
@override
Context get pathContext => io.Platform.isWindows ? windows : posix;
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 58aee2498df..ba147e3a611 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -87,6 +87,12 @@ class DirectoryBasedSourceContainer implements SourceContainer {
* Instances of the class `FileBasedSource` implement a source that represents a file.
*/
class FileBasedSource implements Source {
+
+ /**
+ * A function that changes the way that files are read off of disk.
+ */
+ static Function fileReadMode = (String s) => s;
+
/**
* The URI from which this source was originally derived.
*/
@@ -146,7 +152,7 @@ class FileBasedSource implements Source {
TimestampedData