mutator 0.0.4

  • README.md
  • CHANGELOG.md
  • Installing
  • Versions
  • 0

mutator

A dart language helper tool for pre-compile/transform time refactoring. A potential alternative for Macro or inline function in desperate times.

##Status: Alpha Type detection currently relies on a solution I improvised without a proper design or abstraction and it is neither fast or exhaustively tested. Skip type detection by passing skip_type_check:true to mutate_t method for safety and speed if possible;see usage example1 for more details.

Usage

A simple usage example: Refactoring math.max(5,9) into (){int t = 5;t = t<9?9:t;return t;}();.

import 'package:mutator/mutator.dart';
String alias = 'math';
String pattern = 'math\\.max\\([0-9,\\w\\s_]+\\)';
//path needs to be set properly if there are relative file imports or part files.
String file_path = '';//leaving empty as neither is the case.

String src = """
      import 'dart:math' as math;
      main() async{
        int m = math.max(5,94,8,3,5,7,4);
      }
      """;

///main  should transform the value of
///src into the code below.
///
///   import 'dart:math' as math;
///   main() async{
///     int m = () {
///       int t = 5;
///       t = t < 94 ? 94 : t;
///       t = t < 8 ? 8 : t;
///       t = t < 3 ? 3 : t;
///       t = t < 5 ? 5 : t;
///       t = t < 7 ? 7 : t;
///       t = t < 4 ? 4 : t;
///       return t;
///     }();
///}
main() async{
  replacer(MethodInvocation e){
    String generate_code_for_getting_larger(
        String variable_name,
        String value1,
        String value2){
      return '${variable_name} = '
          '${value1.trim()}<${value2.trim()}?'
          '${value2.trim()}:${value1.trim()};';
    }
    String s = e.toString();
    s = s.substring(9,s.length-1);//removing `math.max(` and `)`
    var l = s.split(',');

    List f = ['(){int t = ${l[0]};'];

    for(String v in l.sublist(1))
      f.add(generate_code_for_getting_larger('t','t',v));

    f.add('return t;}()');
    return f.join();
  }
  var m = new Mutator<MethodInvocation>(
      '', pattern, replacer,alias_name: alias);
  print(await m.mutate_t(file_path,code:src,skip_type_check:true));
}

Refactoring r.nextInt(5) into a random number. Leaving r2.nextInt(5) unchanged as r2 is not an instance of math.Random.

import 'dart:math' as math;
import 'package:mutator/mutator.dart';

String pattern = '[\\w0-9_]+\\.nextInt\\([0-9]+\\)';
String klass_name = 'Random';
String path = '';//dummy path
String src = """
    import 'dart:math' as math;
    main() async{
    var r = new math.Random(5);
    print(r.nextInt(600));
    var r2 = new Random();
    print(r2.nextInt(600));
    }
    class Random{
        nextInt(int n){
          return n +5;
        }
    }
    """;
/// main should transform the value of src into
/// the code below and print it:
///
///import 'dart:math' as math;
///
///main() async{
///  var r = new math.Random(5);
///  print(88);//Changed
///  var r2 = new Random();
///  print(r2.nextInt(600));//Not changed
///}
///
///class Random {
///  nextInt(int n) {
///    return n + 5;
///  }
///}
///
main() async{
  int random_num;
  var r = new math.Random(5);
  replacer(MethodInvocation e){
    String s = e.toString();
    random_num = r.nextInt( int.parse(new RegExp('[0-9]+')
        .firstMatch(s).group(0)));
    return random_num.toString();
  }
  var m = new Mutator<MethodInvocation>(
      klass_name, pattern, replacer,alias_name: 'math');
  print(await m.mutate_t(path,code:src));
}

Refactoring d.on(o).hi = ()=>print('hi'); into d.on(o).set('hi',()=>print('hi'));

import 'package:mutator/mutator.dart';
String code = """
import 'package:mistletoe';
var d = new Dynamism(expert:true);
main() async{
    var o = new Object();
    d.on(o).hi = ()=>print('hi');
}
""";
const String klass_name = 'Dynamism';
const String pattern =
    '^[a-z.A-Z_0-9]+\\.on\\'
    '([a-z.A-Z_0-9]+\\)\\.[a-z.A-Z_0-9]+';
String file_path = '';
main() async{
    replacer(e){
        String s = e.toString();
        List l  = s.split('=');
        var invocation = l.removeAt(0).split('.');
        String name = invocation.removeLast().trim();
        invocation = invocation.join('.') +
            '.set(\'${name}\', ${l.join('=').trim()})';
        return invocation;
    }
    var m = new Mutator<AssignmentExpression>(
      klass_name, pattern, replacer);
    print(await m.mutate_t(file_path,code:code));
}

Features and bugs

Please file feature requests and bugs at the https://github.com/TastyCatFood/mutator/issues.

Limitations

  • No type detection available when the type is not statically defined. e.g.

      f(e){ return e.nextInt(4);}
    
  • Function's return type is ignored. e.g.

     math.Random f(){new math.Random(501);}
     main(){
         f().nextInt(7);
     }
    
  • Type information within conditional statement are ignored. e.g.

      f(e){
         if(e is math.Random){
          return e.nextInt(2);
         }
      }
    

Does not detect the type of variables defined in a file that has been imported as a package or a part of dart-sdk.

e.g.

    import 'package:example_code.dart' as eg;
    main(){
    // Mutator does not look into the package to find the type of [a].
        print(eg.a);
    }

The type of [a] is available when example_code.dart is imported relatively; import './example_code.dart'; or as a part file.

Changelog

0.0.1

  • Initial version

0.0.2

  • A bug fixed

0.0.3

  • mutate and mutate_t are now async methods. This change has been made as sometimes barback attempts to transform a part file before library's main file. Now, mutate_t only completes when dependencies are resolved.

0.0.4

  • time_out_in_seconds option added to mutate_t and mutate. mutator function hangs when a part file is passed to mutate never its main library file is never passed; dependencies cannot be resolved. time_out_in_seconds is added to throw a warning when such occurs.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  mutator: "^0.0.4"

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


      import 'package:mutator/mutator.dart';
  
Version Uploaded Documentation Archive
0.0.4 Apr 28, 2016 Go to the documentation of mutator 0.0.4 Download mutator 0.0.4 archive
0.0.3 Apr 26, 2016 Go to the documentation of mutator 0.0.3 Download mutator 0.0.3 archive
0.0.2 Apr 16, 2016 Go to the documentation of mutator 0.0.2 Download mutator 0.0.2 archive
0.0.1 Apr 16, 2016 Go to the documentation of mutator 0.0.1 Download mutator 0.0.1 archive

Analysis

We analyzed this package on Jul 17, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.0.0-dev.63.0
  • pana: 0.11.3

Scores

Popularity:
Describes how popular the package is relative to other packages. [more]
0 / 100
Health:
Code health derived from static analysis. [more]
0 / 100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
0 / 100
Overall score:
Weighted score of the above. [more]
0
Learn more about scoring.

Platforms

Detected platforms: unsure

Error(s) prevent platform classification:

Error(s) in lib/mutator.dart: Target of URI doesn't exist: 'package:analyzer/analyzer.dart'.

Suggestions

  • Fix platform conflicts.

    Error(s) prevent platform classification:

    Error(s) in lib/mutator.dart: Target of URI doesn't exist: 'package:analyzer/analyzer.dart'.

  • Running dartdoc failed.

    Make sure dartdoc runs without any issues.

  • Package is too old.

    The package was released more than two years ago.

  • Fix analysis and formatting issues.

    Analysis or formatting checks reported 170 errors 10 hints.

    Make sure that the imported libraries are not in conflict. Error(s) in lib/mutator.dart: Target of URI doesn't exist: 'package:analyzer/analyzer.dart'.

    Strong-mode analysis of lib/src/custom_resolver.dart failed with the following error:

    line: 288 col: 15
    The name 'ConstructorName' isn't defined, so it can't be used in an 'is' expression.

    Similar analysis of the following files failed:

    • lib/src/custom_resolver_functions.dart (error)
    • lib/src/dep_resolver.dart (error)
  • Package is pre-v1 release.

    While there is nothing inherently wrong with versions of 0.*.*, it usually means that the author is still experimenting with the general direction API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.0.0 <2.0.0
Dev dependencies
barback any
browser any
mistletoe >=1.0.0
test >=0.12.0 <0.13.0