Как я могу получить все свойства класса в исходном коде дротика с помощью Analyzer для make code patch - PullRequest
0 голосов
/ 18 февраля 2020

Как я могу просмотреть или получить доступ через свойства класса publi c, я хочу сделать патч кода, который реализует метод to Json, отсканировав каждое свойство класса модели и создав карту из это.

на данный момент у меня что-то работает, только это работает правильно, если я запускаю это в каталоге, содержащем только один файл с одним классом, если там больше, все не так.

import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:args/args.dart';
import 'package:codemod/codemod.dart';
import 'package:essential_codemod/suggestors/scan_class_models.dart';
import 'package:essential_codemod/suggestors/implements_json_serialization.dart';

bool isFileSelected(String filePath) {
  return path.extension(filePath) == '.dart';
}

void main(List<String> args) {
  const recursive = 'recursive';
  const modelsDir = 'modelsdir';
  const help = 'help';

  final parser = ArgParser()
    ..addFlag(
      recursive,
      help: 'Apply updates to Dart files in the current directory recursive',
      defaultsTo: false,
    )
    ..addFlag(
      modelsDir,
      help: 'Set directory of models class files',
      defaultsTo: false,
    )
    ..addFlag(
      help,
      abbr: 'h',
      help: 'Prints the help menu',
      defaultsTo: false,
      negatable: false,
    );

  final parsed = parser.parse(args);

  if (parsed[help]) {
    print('''This script will update code''');
    return print(parser.usage);
  }

  final useModelsDir = parsed[modelsDir];
  //print(useModelsDir);
  var currentDir = '${Directory.current.path}';

  var visitor = ModelClassVisitor();
  var jsonSeriali = ImplementsJsonSerialization();
  jsonSeriali.modelVisitor = visitor;

  exitCode = runInteractiveCodemodSequence(
    FileQuery.dir(
      path: currentDir,
      pathFilter: isFileSelected,
      recursive: parsed[recursive],
    ),
    [visitor, jsonSeriali],
    args: args
        .where((name) => !name.contains(help) && !name.contains(useModelsDir) && !name.contains(recursive))
        .toList(),
  );
}

// ignore: deprecated_member_use
import 'package:analyzer/analyzer.dart';
import 'package:codemod/codemod.dart';
import 'package:source_span/source_span.dart';
import 'scan_class_models.dart';
import 'code_template.dart';
import '../type_definictions/core_types.dart';

class ImplementsJsonSerialization implements Suggestor {
  ModelClassVisitor modelVisitor;
  @override
  bool shouldSkip(String sourceFileContents) {
    return false;
  }

  @override
  Iterable<Patch> generatePatches(SourceFile sourceFile) sync* {
    final contents = sourceFile.getText(0);

    var patternStr = modelVisitor.classDeclarationLine;
    final regex = RegExp(
      patternStr,
      multiLine: true,
    );

    final target = StringBuffer();
    target.writeln(patternStr);
    target.writeln(CodeTemplate.getInstance().genFromJson(modelVisitor.listProperties, modelVisitor.className));
    target.writeln(CodeTemplate.getInstance().genToJson(modelVisitor.listProperties));

    for (final match in regex.allMatches(contents)) {
      final line = match.group(0);
      //print('isaque group 0 ${match.group(0)}');

      final updated = line.replaceFirst(patternStr, target.toString()) + '\n';
      //print('isaque updated ${updated}');

      yield Patch(
        sourceFile,
        sourceFile.span(match.start, match.end), //match.start, match.end
        updated,
      );
    }
  }
}

class ModelClassVisitor extends GeneralizingAstVisitor with AstVisitingSuggestorMixin {
  bool isConstruct = false;
  bool isMethod = false;
  bool isClassDeclaration = false;
  String classDeclarationLine = '';
  String className = '';
  List<ClassProperty> listProperties = [];
  int offset;
  int end;

  @override
  visitMethodInvocation(MethodInvocation node) {
    final methodName = node.methodName.name;
    final source = node.toSource();
    /*if (node.methodName.name == 'asObservable') {
      yieldPatch(
        node.methodName.offset,
        node.methodName.end,
        'asStream',
      );
    }*/
    //print('visitMethodInvocation $methodName');
    return super.visitMethodInvocation(node);
  }

  @override
  visitArgumentList(ArgumentList node) {
    final propertyName = node.arguments;
    //print('visitArgumentList $propertyName');
    return super.visitArgumentList(node);
  }

  @override
  visitComment(Comment node) {
    //print('visitComment $node');
    return super.visitComment(node);
  }

  @override
  visitAnnotation(Annotation node) {
    //print('visitAnnotation $node');
    return super.visitAnnotation(node);
  }

  @override
  visitAnnotatedNode(AnnotatedNode node) {
    //print('visitAnnotatedNode $node');
    return super.visitAnnotatedNode(node);
  }

  //visita os blocos de fução {}
  @override
  visitBlock(Block node) {
    //print('visitBlock $node');
    return super.visitBlock(node);
  }

  @override
  visitDeclaration(Declaration node) {
    /*if (isClassDeclaration) {
      //yieldPatch(node.offset, node.end, '');
      print(classDeclarationLine);
      print(node.offset);
      print(node.end);
      print(node);
      isClassDeclaration = false;
    }*/
    return super.visitDeclaration(node);
  }

  @override
  visitClassDeclaration(ClassDeclaration node) {
    //listProperties = [];
    print('visitClassDeclaration listProperties $listProperties');

    className = node.name.name;
    var isExistToJson = node.getMethod('toJson');
    isClassDeclaration = true;

    classDeclarationLine = 'class $className';
    if (node.extendsClause != null) {
      classDeclarationLine = '$classDeclarationLine ${node.extendsClause}';
    }
    if (node.withClause != null) {
      classDeclarationLine = '$classDeclarationLine ${node.withClause}';
    }
    if (node.implementsClause != null) {
      classDeclarationLine = '$classDeclarationLine ${node.implementsClause}';
    }

    classDeclarationLine = classDeclarationLine + ' {';

    offset = node.name.offset;
    end = node.name.end;

    /*print('node $node');
    print('className $className');
    print('isExistToJson $isExistToJson');
    print('offset ${node.name.offset}');
    print('end ${node.name.end}');
    print('extendsClause ${node.extendsClause}');
    print('implementsClause ${node.implementsClause}');
    print('withClause ${node.withClause}');*/
    //print('length ${node.length}');
    //print('root ${node.root}');
    //print('parent ${node.parent}');
    //print('findPrevious ${node.findPrevious(node.beginToken)}');

    /*yieldPatch(
        node.name.offset,       
        node.name.end,       
        'test as asdjhasjd',
      );*/
    return super.visitClassDeclaration(node);
  }

  ///get class properties
  @override
  visitClassMember(ClassMember node) {
    //print('visitClassMember $node');
    if (!isConstruct && !isMethod) {
      //remove type anoted
      var name = node.toSource();
      name = name.substring(name.lastIndexOf(RegExp(r'\s+')) + 1);
      name = name.replaceAll(';', '');
      name = name.trim();
      //print('is property ${listProperties}');

      var type = node.toSource().replaceAll('final', '').replaceAll('static', '');
      type = type.substring(0, type.lastIndexOf(RegExp(r'\s+')));
      type = type.trim();
      type = type == '' ? 'dynamic' : type;
      //print("ScanClassModels type: $type:4");

      listProperties.add(ClassProperty(type: type, name: name));

      print('visitClassMember listProperties $listProperties');
    }
    return super.visitClassMember(node);
  }

  @override
  visitConstructorDeclaration(ConstructorDeclaration node) {
    //print('visitConstructorDeclaration $node');
    isConstruct = true;
    return super.visitConstructorDeclaration(node);
  }

  @override
  visitMethodDeclaration(MethodDeclaration node) {
    //print('visitMethodDeclaration $node');
    isMethod = true;
    return super.visitMethodDeclaration(node);
  }
}

https://github.com/insinfo/essential_codemod

...