<commit_before>library calzone.visitor_typescript;

import "package:analyzer/analyzer.dart" show ParameterKind;

import "package:calzone/compiler.dart";
import "package:calzone/util.dart";

final Map<dynamic, String> _baseTypes = <String, String>{
  null: "void",
  "dynamic": "any",
  "String": "string",
  "bool": "boolean",
  "int": "number",
  "num": "number",
  "Map": "any",
  "LinkedHashMap": "any",
  "Function": "any"
};

class _ClassStringBuffer {
  final String name;
  
  StringBuffer prefix = new StringBuffer();
  
  StringBuffer variables = new StringBuffer();
  StringBuffer constructor = new StringBuffer();
  StringBuffer content = new StringBuffer();
  
  _ClassStringBuffer(this.name);
  
  writelnPrefix(String text) => prefix.writeln(text);
  
  writelnVariables(String text) => variables.writeln(text);
  writelnConstructor(String text) => constructor.writeln(text);
  writeln(String text) => content.writeln(text);
  
  String toString() {
    StringBuffer output = new StringBuffer();
    
    if (!prefix.isEmpty) {
      output.writeln(prefix);
    }
    
    output.write("\n\tclass $name {");
    
    if (!variables.isEmpty) {
      output.write("\n$variables");
    }
    
    if (!constructor.isEmpty) {
      output.write("\n$constructor");
    }
    
    if (!content.isEmpty) {
      output.write("\n$content");
    }
    
    output.write("\t}");
    return output.toString();
  }
}

class TypeScriptCompilerVisitor extends CompilerVisitor {
  final String moduleName;
  
  String _output;
  String get output => _output;
  bool get hasOutput => _output != null;
    
  StringBuffer _buffer;
  
  _ClassStringBuffer _classBuffer;
  
  Map<dynamic, String> _types; 
  
  TypeScriptCompilerVisitor(this.moduleName);
  
  startCompilation(Compiler compiler) {
    _buffer = new StringBuffer();
    _buffer.writeln("declare namespace __$moduleName {");
    
    _types = new Map.from(_baseTypes);
    
    for (TypeTransformer transformer in compiler.typeTransformers) {
      if (transformer is! NamedTypeTransformer)
        continue;

      var n = transformer as NamedTypeTransformer;
      for (var input in n.types) {
          _types[input] = n.output;
      }
    }
  }
  
  stopCompilation() {
    _buffer.writeln("""
}
      
declare module "$moduleName" {
\texport = __$moduleName;
}
    """);
    
    _output = _buffer.toString();
    _buffer = null;
  }
  
  String _handleType(String type) {
    var tree = getTypeTree(type);

    if (_types.containsKey(tree[0])) {
      return _types[tree[0]];
    }
        
    if (tree[0] == "List" || tree[0] == "Iterable") {
      if (tree.length > 1) {
        return "${_handleType(tree[1])}[]";
      } else {
        return "any[]";
      }
    }
    
    return tree[0];
  }
  
  String _handleParams(List<Parameter> parameters) =>
    parameters
      .map((Parameter param) {
        var suffix = param.kind == ParameterKind.POSITIONAL ? "?" : "";      
        
        return "${param.name}$suffix: ${_handleType(param.type)}";
      })
      .join(", ");
  
  String _makeFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType,
      [String subName]) {
    var name = subName != null ? subName : data["name"];
    
    returnType = _handleType(returnType);
    var paramStr = _handleParams(parameters);
    
    return "$name($paramStr): $returnType;";
  }
  
  addTopLevelFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {   
    final str = _makeFunction(data, parameters, returnType); 
    _buffer.writeln("\tfunction $str");
  }
  
  startClass(Map<String, dynamic> data) {
    _classBuffer = new _ClassStringBuffer(data["name"]);
  }
  
  stopClass() {    
    _buffer.writeln(_classBuffer);
    _classBuffer = null;
  }
  
  addClassConstructor(Map<String, dynamic> data, List<Parameter> parameters) {
    _classBuffer.writelnConstructor("\t\tconstructor(${_handleParams(parameters)});");
  }
  
  addClassStaticFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {
    var name = data["name"].contains(_classBuffer.name + ".") ?
      (data["name"] as String).substring(_classBuffer.name.length + 1) :
      data["name"];
    final str = _makeFunction(data, parameters, returnType, name); 
    _classBuffer.writelnConstructor("\t\tstatic $str");
  }
  
  addClassFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {
    final str = _makeFunction(data, parameters, returnType); 
    _classBuffer.writeln("\t\t$str");
  }
  
  addClassStaticMember(Map<String, dynamic> data) {
    final name = data["name"];
    final type = data["type"];
    
    _classBuffer.writelnVariables("\t\tstatic $name: ${_handleType(type)};");
  }
  
  addClassMember(Map<String, dynamic> data) {
    final name = data["name"];
    final type = data["type"];
    
    _classBuffer.writelnVariables("\t\t$name: ${_handleType(type)};");
  }
}<commit_msg>TypeScript add support for named parameters.<commit_after>library calzone.visitor_typescript;

import "package:analyzer/analyzer.dart" show ParameterKind;

import "package:calzone/compiler.dart";
import "package:calzone/util.dart";

final Map<dynamic, String> _baseTypes = <String, String>{
  null: "void",
  "dynamic": "any",
  "String": "string",
  "bool": "boolean",
  "int": "number",
  "num": "number",
  "Map": "any",
  "LinkedHashMap": "any",
  "Function": "any"
};

class _ClassStringBuffer {
  final String name;
  
  StringBuffer prefix = new StringBuffer();
  
  StringBuffer variables = new StringBuffer();
  StringBuffer constructor = new StringBuffer();
  StringBuffer content = new StringBuffer();
  
  _ClassStringBuffer(this.name);
  
  writelnPrefix(String text) => prefix.writeln(text);
  
  writelnVariables(String text) => variables.writeln(text);
  writelnConstructor(String text) => constructor.writeln(text);
  writeln(String text) => content.writeln(text);
  
  String toString() {
    StringBuffer output = new StringBuffer();
    
    if (!prefix.isEmpty) {
      output.write("\n$prefix");
    }
    
    output.write("\n\tclass $name {");
    
    if (!variables.isEmpty) {
      output.write("\n$variables");
    }
    
    if (!constructor.isEmpty) {
      output.write("\n$constructor");
    }
    
    if (!content.isEmpty) {
      output.write("\n$content");
    }
    
    output.write("\t}");
    return output.toString();
  }
}

class TypeScriptCompilerVisitor extends CompilerVisitor {
  final String moduleName;
  
  String _output;
  String get output => _output;
  bool get hasOutput => _output != null;
    
  StringBuffer _buffer;
  
  _ClassStringBuffer _classBuffer;
  
  Map<dynamic, String> _types; 
  
  TypeScriptCompilerVisitor(this.moduleName);
  
  startCompilation(Compiler compiler) {
    _buffer = new StringBuffer();
    _buffer.writeln("declare namespace __$moduleName {");
    
    _types = new Map.from(_baseTypes);
    
    for (TypeTransformer transformer in compiler.typeTransformers) {
      if (transformer is! NamedTypeTransformer)
        continue;

      var n = transformer as NamedTypeTransformer;
      for (var input in n.types) {
          _types[input] = n.output;
      }
    }
  }
  
  stopCompilation() {
    _buffer.writeln("""
}
      
declare module "$moduleName" {
\texport = __$moduleName;
}
    """);
    
    _output = _buffer.toString();
    _buffer = null;
  }
  
  String _handleType(String type) {
    var tree = getTypeTree(type);

    if (_types.containsKey(tree[0])) {
      return _types[tree[0]];
    }
        
    if (tree[0] == "List" || tree[0] == "Iterable") {
      if (tree.length > 1) {
        return "${_handleType(tree[1])}[]";
      } else {
        return "any[]";
      }
    }
    
    return tree[0];
  }
  
  String _handleParams(List<Parameter> parameters,
      String optName, StringBuffer optBuffer) {
    List<String> paramList = [];
    
    StringBuffer options = new StringBuffer();
    
    for (var param in parameters) {
      if (param.kind == ParameterKind.NAMED) {
        if (options.isEmpty) {
          options.writeln("\tinterface $optName {");
        }
        
        options.writeln("\t\t${param.name}?: ${_handleType(param.type)};");
        continue;
      }
      
      var suffix = param.kind == ParameterKind.POSITIONAL ? "?" : "";      
      
      paramList.add("${param.name}$suffix: ${_handleType(param.type)}");
    }
    
    if (!options.isEmpty) {
      paramList.add("_opt?: $optName");
      options.write("\t}");
      
      optBuffer.writeln(options);
    }

    return paramList.join(", ");
  }
  
  String _makeFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType,
      String optName, StringBuffer optBuffer, { String subName }) {
    var name = subName != null ? subName : data["name"];
    
    returnType = _handleType(returnType);
    var paramStr = _handleParams(parameters, optName, optBuffer);
    
    return "$name($paramStr): $returnType;";
  }
  
  addTopLevelFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {   
    final str = _makeFunction(data, parameters, returnType, "_${data["name"]}_options", _buffer); 
    _buffer.writeln("\tfunction $str");
  }
  
  startClass(Map<String, dynamic> data) {
    _classBuffer = new _ClassStringBuffer(data["name"]);
  }
  
  stopClass() {    
    _buffer.writeln(_classBuffer);
    _classBuffer = null;
  }
  
  addClassConstructor(Map<String, dynamic> data, List<Parameter> parameters) {
    final paramList = _handleParams(parameters, "_${_classBuffer.name}_options", _classBuffer.prefix);
    _classBuffer.writelnConstructor("\t\tconstructor($paramList);");
  }
  
  addClassStaticFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {
    var name = data["name"].contains(_classBuffer.name + ".") ?
      (data["name"] as String).substring(_classBuffer.name.length + 1) :
      data["name"];
    final str = _makeFunction(data, parameters, returnType, "_${_classBuffer.name}_${name}_options", _classBuffer.prefix, subName: name); 
    _classBuffer.writelnConstructor("\t\tstatic $str");
  }
  
  addClassFunction(Map<String, dynamic> data, List<Parameter> parameters, String returnType) {
    final str = _makeFunction(data, parameters, returnType, "_${_classBuffer.name}_${data["name"]}_options", _classBuffer.prefix); 
    _classBuffer.writeln("\t\t$str");
  }
  
  addClassStaticMember(Map<String, dynamic> data) {
    final name = data["name"];
    final type = data["type"];
    
    _classBuffer.writelnVariables("\t\tstatic $name: ${_handleType(type)};");
  }
  
  addClassMember(Map<String, dynamic> data) {
    final name = data["name"];
    final type = data["type"];
    
    _classBuffer.writelnVariables("\t\t$name: ${_handleType(type)};");
  }
}
{'fraction_non_alphanumeric': 0.14330592257229974, 'fraction_numerical': 0.0014783331793402938, 'mean_word_length': 3.3072025467568644, 'pattern_counts': {'":': 16, '<': 38, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4122290', 'n_tokens_mistral': 3388, 'n_tokens_neox': 3353, 'n_words': 677}