-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Mateus Felipe C. C. Pinto <mateusfccp@gmail.com>
- Loading branch information
1 parent
e779f3c
commit 5281d46
Showing
17 changed files
with
539 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:lsp_server/lsp_server.dart'; | ||
|
||
import 'src/analyzer.dart'; | ||
|
||
void main() async { | ||
final connection = Connection(stdin, stdout); | ||
final analyzer = Analyzer(); | ||
|
||
connection.onInitialize((params) async { | ||
if (params.workspaceFolders case final worksPaceFolders?) { | ||
for (final folder in worksPaceFolders) { | ||
final directory = Directory.fromUri(folder.uri); | ||
analyzer.addFileSystemEntity(directory); | ||
} | ||
} else if (params.rootUri case final uri?) { | ||
final directory = Directory.fromUri(uri); | ||
analyzer.addFileSystemEntity(directory); | ||
} else if (params.rootPath case final path?) { | ||
final directory = Directory(path); | ||
analyzer.addFileSystemEntity(directory); | ||
} | ||
|
||
return InitializeResult( | ||
capabilities: ServerCapabilities( | ||
textDocumentSync: const Either2.t1(TextDocumentSyncKind.Full), | ||
), | ||
); | ||
}); | ||
|
||
// Register a listener for when the client sends a notification when a text | ||
// document was opened. | ||
connection.onDidOpenTextDocument((parameters) async { | ||
final file = File.fromUri(parameters.textDocument.uri); | ||
analyzer.addFileSystemEntity(file); | ||
|
||
final diagnostics = await analyzer.analyze( | ||
parameters.textDocument.uri.path, | ||
parameters.textDocument.text, | ||
); | ||
|
||
// Send back an event notifying the client of issues we want them to render. | ||
// To clear issues the server is responsible for sending an empty list. | ||
connection.sendDiagnostics( | ||
PublishDiagnosticsParams( | ||
diagnostics: diagnostics, | ||
uri: parameters.textDocument.uri, | ||
), | ||
); | ||
}); | ||
|
||
// Register a listener for when the client sends a notification when a text | ||
// document was changed. | ||
connection.onDidChangeTextDocument((parameters) async { | ||
final contentChanges = parameters.contentChanges; | ||
final contentChange = TextDocumentContentChangeEvent2.fromJson( | ||
contentChanges[contentChanges.length - 1].toJson() as Map<String, Object?>, | ||
); | ||
|
||
final diagnostics = await analyzer.analyze( | ||
parameters.textDocument.uri.path, | ||
contentChange.text, | ||
); | ||
|
||
// Send back an event notifying the client of issues we want them to render. | ||
// To clear issues the server is responsible for sending an empty list. | ||
connection.sendDiagnostics( | ||
PublishDiagnosticsParams( | ||
diagnostics: diagnostics, | ||
uri: parameters.textDocument.uri, | ||
), | ||
); | ||
}); | ||
|
||
await connection.listen(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import 'dart:collection'; | ||
import 'dart:io'; | ||
|
||
import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; | ||
import 'package:analyzer/file_system/physical_file_system.dart'; | ||
import 'package:analyzer/src/dart/sdk/sdk.dart'; | ||
import 'package:analyzer/src/util/sdk.dart'; | ||
import 'package:lsp_server/lsp_server.dart'; | ||
import 'package:pinto/ast.dart'; | ||
import 'package:pinto/error.dart'; | ||
import 'package:pinto/localization.dart'; | ||
import 'package:pinto/semantic.dart'; | ||
import 'package:quiver/collection.dart'; | ||
|
||
final _resourceProvider = PhysicalResourceProvider.INSTANCE; | ||
|
||
final class Analyzer { | ||
final _analysisEntities = SplayTreeSet<String>(); | ||
final _analysisCache = <String, List<Diagnostic>>{}; | ||
|
||
late AnalysisContextCollection _analysisContextCollection; | ||
late AbstractDartSdk _sdk; | ||
|
||
Analyzer() { | ||
_analysisContextCollection = AnalysisContextCollection( | ||
includedPaths: [], | ||
resourceProvider: _resourceProvider, | ||
); | ||
|
||
_sdk = FolderBasedDartSdk( | ||
_resourceProvider, | ||
_resourceProvider.getFolder(getSdkPath()), | ||
); | ||
} | ||
|
||
void addFileSystemEntity(FileSystemEntity entity) { | ||
final path = entity.absolute.path; | ||
final analysisEntities = [..._analysisEntities]; | ||
|
||
for (final folder in analysisEntities) { | ||
if (path.startsWith(folder)) { | ||
return; | ||
} else if (folder.startsWith(path)) { | ||
_analysisEntities.remove(folder); | ||
} | ||
} | ||
|
||
_analysisEntities.add(path); | ||
|
||
if (!listsEqual([..._analysisEntities], analysisEntities)) { | ||
_rebuildAnalysisContext(); | ||
} | ||
} | ||
|
||
void _rebuildAnalysisContext() { | ||
_analysisContextCollection.dispose(); | ||
|
||
_analysisContextCollection = AnalysisContextCollection( | ||
includedPaths: [..._analysisEntities], | ||
resourceProvider: _resourceProvider, | ||
); | ||
} | ||
|
||
Future<List<Diagnostic>> analyze(String path, String text) async { | ||
final errorHandler = ErrorHandler(); | ||
|
||
final scanner = Scanner( | ||
source: text, | ||
errorHandler: errorHandler, | ||
); | ||
|
||
final tokens = scanner.scanTokens(); | ||
|
||
final parser = Parser( | ||
tokens: tokens, | ||
errorHandler: errorHandler, | ||
); | ||
|
||
final program = parser.parse(); | ||
|
||
final symbolsResolver = SymbolsResolver( | ||
resourceProvider: _resourceProvider, | ||
analysisContextCollection: _analysisContextCollection, | ||
sdk: _sdk, | ||
); | ||
|
||
final resolver = Resolver( | ||
program: program, | ||
symbolsResolver: symbolsResolver, | ||
errorHandler: errorHandler, | ||
); | ||
|
||
await resolver.resolve(); | ||
|
||
final diagnostics = [ | ||
for (final error in errorHandler.errors) _diagnosticFromError(error), | ||
]; | ||
|
||
_analysisCache[path] = diagnostics; | ||
|
||
return diagnostics; | ||
} | ||
} | ||
|
||
Diagnostic _diagnosticFromError(PintoError error) { | ||
final start = switch (error) { | ||
ScanError(:final location) => Position( | ||
character: location.column - 1, | ||
line: location.line - 1, | ||
), | ||
ParseError(:final token) || ResolveError(:final token) => Position( | ||
character: token.column - token.lexeme.length, | ||
line: token.line - 1, | ||
), | ||
}; | ||
|
||
final end = switch (error) { | ||
ScanError(:final location) => Position( | ||
character: location.column, | ||
line: location.line - 1, | ||
), | ||
ParseError(:final token) || ResolveError(:final token) => Position( | ||
character: token.column, | ||
line: token.line - 1, | ||
), | ||
}; | ||
|
||
final range = Range(start: start, end: end); | ||
|
||
final message = messageFromError(error); | ||
|
||
return Diagnostic( | ||
message: message, | ||
range: range, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
library; | ||
|
||
export 'src/localization.dart'; |
Oops, something went wrong.