11import 'dart:async' ;
22import 'package:flutter/material.dart' ;
33import '../models/lsp_types.dart' ;
4+ import '../lsp/python_completor.dart' ;
45import '../theme/editor_theme.dart' ;
56
67class CodeEditor extends StatefulWidget {
@@ -361,197 +362,3 @@ class _CodeEditorState extends State<CodeEditor> {
361362 );
362363 }
363364}
364-
365- class PythonCompletor {
366- static const Set <String > _keywords = {
367- 'False' , 'None' , 'True' , 'and' , 'as' , 'assert' , 'async' , 'await' ,
368- 'break' , 'class' , 'continue' , 'def' , 'del' , 'elif' , 'else' , 'except' ,
369- 'finally' , 'for' , 'from' , 'global' , 'if' , 'import' , 'in' , 'is' ,
370- 'lambda' , 'nonlocal' , 'not' , 'or' , 'pass' , 'raise' , 'return' , 'try' ,
371- 'while' , 'with' , 'yield' ,
372- };
373-
374- static const Set <String > _builtins = {
375- 'abs' , 'all' , 'any' , 'ascii' , 'bin' , 'bool' , 'bytearray' , 'bytes' ,
376- 'callable' , 'chr' , 'classmethod' , 'compile' , 'complex' , 'delattr' ,
377- 'dict' , 'dir' , 'divmod' , 'enumerate' , 'eval' , 'exec' , 'filter' ,
378- 'float' , 'format' , 'frozenset' , 'getattr' , 'globals' , 'hasattr' ,
379- 'hash' , 'help' , 'hex' , 'id' , 'input' , 'int' , 'isinstance' , 'issubclass' ,
380- 'iter' , 'len' , 'list' , 'locals' , 'map' , 'max' , 'memoryview' , 'min' ,
381- 'next' , 'object' , 'oct' , 'open' , 'ord' , 'pow' , 'print' , 'property' ,
382- 'range' , 'repr' , 'reversed' , 'round' , 'set' , 'setattr' , 'slice' ,
383- 'sorted' , 'staticmethod' , 'str' , 'sum' , 'super' , 'tuple' , 'type' ,
384- 'vars' , 'zip' ,
385- };
386-
387- static const Map <String , String > _builtinClasses = {
388- 'int' : 'Integer type' ,
389- 'str' : 'String type' ,
390- 'float' : 'Float type' ,
391- 'bool' : 'Boolean type' ,
392- 'list' : 'List type' ,
393- 'dict' : 'Dictionary type' ,
394- 'set' : 'Set type' ,
395- 'tuple' : 'Tuple type' ,
396- 'bytes' : 'Bytes type' ,
397- };
398-
399- final Map <String , List <CompletionItem >> _fileCompletions = {};
400-
401- void analyzeFile (String filePath, String content) {
402- final completions = < CompletionItem > [];
403-
404- completions.addAll (_keywords.map ((k) => CompletionItem (
405- label: k,
406- kind: CompletionKind .keyword,
407- insertText: k,
408- detail: 'Keyword' ,
409- )));
410-
411- completions.addAll (_builtins.map ((b) => CompletionItem (
412- label: b,
413- kind: CompletionKind .function,
414- insertText: b,
415- detail: 'Built-in function' ,
416- )));
417-
418- completions.addAll (_builtinClasses.entries.map ((e) => CompletionItem (
419- label: e.key,
420- kind: CompletionKind .class_,
421- insertText: e.key,
422- detail: e.value,
423- )));
424-
425- completions.addAll (_extractImports (content).map ((i) => CompletionItem (
426- label: i,
427- kind: CompletionKind .module,
428- insertText: i,
429- detail: 'Module' ,
430- )));
431-
432- completions.addAll (_extractFunctions (content).map ((f) => CompletionItem (
433- label: f['name' ]! ,
434- kind: CompletionKind .function,
435- insertText: f['name' ]! ,
436- detail: f['signature' ] ?? 'Function' ,
437- )));
438-
439- completions.addAll (_extractClasses (content).map ((c) => CompletionItem (
440- label: c['name' ]! ,
441- kind: CompletionKind .class_,
442- insertText: c['name' ]! ,
443- detail: c['signature' ] ?? 'Class' ,
444- )));
445-
446- _fileCompletions[filePath] = completions;
447- }
448-
449- Set <String > _extractImports (String content) {
450- final imports = < String > {};
451- final importRegex = RegExp (r'^(?:from\s+(\w+)|import\s+(\w+))' , multiLine: true );
452-
453- for (final match in importRegex.allMatches (content)) {
454- if (match.group (1 ) != null ) {
455- imports.add (match.group (1 )! );
456- } else if (match.group (2 ) != null ) {
457- imports.add (match.group (2 )! );
458- }
459- }
460-
461- return imports;
462- }
463-
464- List <Map <String , String >> _extractFunctions (String content) {
465- final functions = < Map <String , String >> [];
466- final funcRegex = RegExp (r'^def\s+(\w+)\s*\([^)]*\)' , multiLine: true );
467-
468- for (final match in funcRegex.allMatches (content)) {
469- functions.add ({
470- 'name' : match.group (1 )! ,
471- 'signature' : 'def ${match .group (1 )}()' ,
472- });
473- }
474-
475- return functions;
476- }
477-
478- List <Map <String , String >> _extractClasses (String content) {
479- final classes = < Map <String , String >> [];
480- final classRegex = RegExp (r'^class\s+(\w+)' , multiLine: true );
481-
482- for (final match in classRegex.allMatches (content)) {
483- classes.add ({
484- 'name' : match.group (1 )! ,
485- 'signature' : 'class ${match .group (1 )}' ,
486- });
487- }
488-
489- return classes;
490- }
491-
492- List <CompletionItem > getCompletions (String filePath, String prefix, int line, int column) {
493- final completions = _fileCompletions[filePath] ?? _getDefaultCompletions ();
494-
495- if (prefix.isEmpty) {
496- return completions.take (20 ).toList ();
497- }
498-
499- return completions
500- .where ((c) => c.label.toLowerCase ().startsWith (prefix.toLowerCase ()))
501- .take (20 )
502- .toList ();
503- }
504-
505- List <CompletionItem > _getDefaultCompletions () {
506- return _keywords.map ((k) => CompletionItem (
507- label: k,
508- kind: CompletionKind .keyword,
509- insertText: k,
510- detail: 'Keyword' ,
511- )).toList ();
512- }
513-
514- List <Diagnostic > analyzeErrors (String content) {
515- final diagnostics = < Diagnostic > [];
516- final lines = content.split ('\n ' );
517-
518- for (int i = 0 ; i < lines.length; i++ ) {
519- final line = lines[i];
520-
521- if (line.contains ('undefined' ) || RegExp (r'\w+\s+is\s+not\s+defined' ).hasMatch (line)) {
522- diagnostics.add (Diagnostic (
523- message: 'Undefined name' ,
524- line: i + 1 ,
525- column: 1 ,
526- endLine: i + 1 ,
527- endColumn: line.length,
528- severity: DiagnosticSeverity .error,
529- ));
530- }
531-
532- if (line.contains ('SyntaxError' )) {
533- diagnostics.add (Diagnostic (
534- message: 'Syntax error' ,
535- line: i + 1 ,
536- column: 1 ,
537- endLine: i + 1 ,
538- endColumn: line.length,
539- severity: DiagnosticSeverity .error,
540- ));
541- }
542-
543- if (line.contains ('IndentationError' )) {
544- diagnostics.add (Diagnostic (
545- message: 'Indentation error' ,
546- line: i + 1 ,
547- column: 1 ,
548- endLine: i + 1 ,
549- endColumn: line.length,
550- severity: DiagnosticSeverity .error,
551- ));
552- }
553- }
554-
555- return diagnostics;
556- }
557- }
0 commit comments