<commit_before><!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../case-map.html">
<script>

  Polymer.Bind.addComputedPropertyEffect = function(model, name, expression) {
    var index = expression.indexOf('(');
    var method = expression.slice(0, index);
    var args = expression.slice(index + 1, -1).replace(/ /g, '').split(',');
    //console.log('%c on [%s] compute [%s] via [%s]', 'color: green', args[0], name, method);
    var methodArgs = 'this._data.' + args.join(', this._data.');
    var methodString = 'this.debounce(\'_' + expression + '\', function() {\n' +
      '\t\tthis.' + name + ' = this.' + method + '(' + methodArgs + ');\n' +
      '\t});';
    var effect = {
      property: name,
      args: args,
      methodName: method,
      methodString: methodString
    };
    for (var i=0; i<args.length; i++) {
      this.addPropertyEffect(model, args[i], 'compute', effect);
    }
  };

  Polymer.Base.extend(Polymer.Bind, {

    _shouldAddListener: function(info) {
      return info.name &&
             info.mode === '{' &&
             !info.negate &&
             info.kind != 'attribute'
             ;
    },

    annotationEffect: function(source, value, info) {
      var property = info.name || 'textContent';
      var node = this._nodes[info.index];
      var calc = info.negate ? !value : value;
      if (info.kind == 'attribute') {
        this.serializeValueToAttribute(calc, property, node);
      } else {
        return node[property] = calc;
      }
    },

    reflectEffect: function(source) {
      this.reflectPropertyToAttribute(source);
    },

    notifyEffect: function(source) {
      this._notifyChange(source);
    },

    observerEffect: function(source, value, info) {
      //console.log(value, info);
      if (info.property) {
        this[info.method](value);
      } else {
        var args = Polymer.Bind._marshalArgs(this._data, info.properties);
        if (args) {
          this[info.method].apply(this, args);
        }
      }
    },

    computeEffect: function(source, value, info) {
      var args = Polymer.Bind._marshalArgs(this._data, info.args);
      if (args) {
        this[info.property] = this[info.methodName].apply(this, args);
      }
    },

    annotatedComputationEffect: function(source, value, info) {
      var args = Polymer.Bind._marshalArgs(this._data, info.args);
      if (args) {
        var value = this[info.methodName].apply(this, args);
        var node = this._nodes[info.index];
        if (info.kind == 'attribute') {
          this.serializeValueToAttribute(value, info.property, node);
        } else {
          node[info.property || 'textContent'] = value;
        }
      }
    },

    _marshalArgs: function(model, properties) {
      var a=[];
      for (var i=0, l=properties.length, v; i<l; i++) {
        v = model[properties[i]];
        if (v === undefined) {
          return;
        }
        a[i] = v;
      }
      return a;
    }

  });

/*
  Polymer.Bind.addBuilders({

    compute: function(model, source, effect) {
      return effect.methodString;
    },

    computedAnnotation: function(model, source, effect) {
      return effect.methodString;
    },

    // implement effect directives from template annotations
    // _nodes[info.index][info.name] = {{info.value}}
    annotation: function(model, hostProperty, info) {
      if (Polymer.Bind._shouldAddListener(info)) {
        // <node>.on.<dash-case-property>-changed: <path> = e.detail.value
        Polymer.Bind._addAnnotatedListener(model, info.index,
          info.name, info.value, info.event);
      }
      //
      var property = info.name;
      if (!property) {
        property = 'textContent';
      }
      //
      // flow-down
      //
      // construct the effect to occur when [property] changes:
      // set nodes[index][name] to this[value]
      //
      //console.log('[_annotationEffectBuilder]: [%s] %=% [%s].[%s]', info.value, info.index, property);
      var parts = info.value.split('.');
      var value, setData;
      if (parts.length <= 1) {
        setData = '';
        value = 'this._data.' + info.value;
      } else {
        // Null check intermediate paths
        var last = parts.pop();
        var curr = 'this._data';
        parts = parts.map(function(s) {
          return curr += ('.' + s);
        });
        value = parts.join('!=null && ')
          + '!=null ? '
          + curr + '.' + last
          + ' : undefined'
          ;
        // TODO(kschaaf): Update private storage for this path, for dirty-checking
        // path notifications on their way up; could have been made separate PropertyEffect,
        // but is coupled to (required for) path listeners to function, which is already
        // bound to the annotation propertyEffect, so ROI is low
        setData =
          'var val = ' + value + ';\n' +
          'this._data[\'' + info.value + '\'] = val;\n'
          ;
        value = 'val';
      }
      // TODO(sjmiles): being able to express logic (negate) as actual JS is
      // convenient when code-generating. Remember to always process a custom
      // token stream (e.g. '!' below) instead of passing template code
      // directly to eval.
      value = (info.negate ? '!' : '') + value;
      var node = 'this._nodes[' + info.index + ']';
      if (info.kind == 'attribute') {
        return setData + 'this.serializeValueToAttribute(' + value + ',' +
          '\'' + property + '\',' + node + ');';
      } else {
        return setData + node + '.' + property + ' = ' + value + ';';
      }
    }

  });
*/

</script>
<commit_msg>Support paths in annotation effect.<commit_after><!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../case-map.html">
<script>

  Polymer.Bind.addComputedPropertyEffect = function(model, name, expression) {
    var index = expression.indexOf('(');
    var method = expression.slice(0, index);
    var args = expression.slice(index + 1, -1).replace(/ /g, '').split(',');
    //console.log('%c on [%s] compute [%s] via [%s]', 'color: green', args[0], name, method);
    var methodArgs = 'this._data.' + args.join(', this._data.');
    var methodString = 'this.debounce(\'_' + expression + '\', function() {\n' +
      '\t\tthis.' + name + ' = this.' + method + '(' + methodArgs + ');\n' +
      '\t});';
    var effect = {
      property: name,
      args: args,
      methodName: method,
      methodString: methodString
    };
    for (var i=0; i<args.length; i++) {
      this.addPropertyEffect(model, args[i], 'compute', effect);
    }
  };

  Polymer.Base.extend(Polymer.Bind, {

    _shouldAddListener: function(info) {
      return info.name &&
             info.mode === '{' &&
             !info.negate &&
             info.kind != 'attribute'
             ;
    },

    annotationEffect: function(source, value, info) {
      var property = info.name || 'textContent';
      var node = this._nodes[info.index];
      if (source != info.value) {
        value = this.getPathValue(info.value);
      }
      var calc = info.negate ? !value : value;
      if (info.kind == 'attribute') {
        this.serializeValueToAttribute(calc, property, node);
      } else {
        return node[property] = calc;
      }
    },

    reflectEffect: function(source) {
      this.reflectPropertyToAttribute(source);
    },

    notifyEffect: function(source) {
      this._notifyChange(source);
    },

    observerEffect: function(source, value, info) {
      //console.log(value, info);
      if (info.property) {
        this[info.method](value);
      } else {
        var args = Polymer.Bind._marshalArgs(this._data, info.properties);
        if (args) {
          this[info.method].apply(this, args);
        }
      }
    },

    computeEffect: function(source, value, info) {
      var args = Polymer.Bind._marshalArgs(this._data, info.args);
      if (args) {
        this[info.property] = this[info.methodName].apply(this, args);
      }
    },

    annotatedComputationEffect: function(source, value, info) {
      var args = Polymer.Bind._marshalArgs(this._data, info.args);
      if (args) {
        var value = this[info.methodName].apply(this, args);
        var node = this._nodes[info.index];
        if (info.kind == 'attribute') {
          this.serializeValueToAttribute(value, info.property, node);
        } else {
          node[info.property || 'textContent'] = value;
        }
      }
    },

    _marshalArgs: function(model, properties) {
      var a=[];
      for (var i=0, l=properties.length, v; i<l; i++) {
        v = model[properties[i]];
        if (v === undefined) {
          return;
        }
        a[i] = v;
      }
      return a;
    }

  });

/*
  Polymer.Bind.addBuilders({

    compute: function(model, source, effect) {
      return effect.methodString;
    },

    computedAnnotation: function(model, source, effect) {
      return effect.methodString;
    },

    // implement effect directives from template annotations
    // _nodes[info.index][info.name] = {{info.value}}
    annotation: function(model, hostProperty, info) {
      if (Polymer.Bind._shouldAddListener(info)) {
        // <node>.on.<dash-case-property>-changed: <path> = e.detail.value
        Polymer.Bind._addAnnotatedListener(model, info.index,
          info.name, info.value, info.event);
      }
      //
      var property = info.name;
      if (!property) {
        property = 'textContent';
      }
      //
      // flow-down
      //
      // construct the effect to occur when [property] changes:
      // set nodes[index][name] to this[value]
      //
      //console.log('[_annotationEffectBuilder]: [%s] %=% [%s].[%s]', info.value, info.index, property);
      var parts = info.value.split('.');
      var value, setData;
      if (parts.length <= 1) {
        setData = '';
        value = 'this._data.' + info.value;
      } else {
        // Null check intermediate paths
        var last = parts.pop();
        var curr = 'this._data';
        parts = parts.map(function(s) {
          return curr += ('.' + s);
        });
        value = parts.join('!=null && ')
          + '!=null ? '
          + curr + '.' + last
          + ' : undefined'
          ;
        // TODO(kschaaf): Update private storage for this path, for dirty-checking
        // path notifications on their way up; could have been made separate PropertyEffect,
        // but is coupled to (required for) path listeners to function, which is already
        // bound to the annotation propertyEffect, so ROI is low
        setData =
          'var val = ' + value + ';\n' +
          'this._data[\'' + info.value + '\'] = val;\n'
          ;
        value = 'val';
      }
      // TODO(sjmiles): being able to express logic (negate) as actual JS is
      // convenient when code-generating. Remember to always process a custom
      // token stream (e.g. '!' below) instead of passing template code
      // directly to eval.
      value = (info.negate ? '!' : '') + value;
      var node = 'this._nodes[' + info.index + ']';
      if (info.kind == 'attribute') {
        return setData + 'this.serializeValueToAttribute(' + value + ',' +
          '\'' + property + '\',' + node + ');';
      } else {
        return setData + node + '.' + property + ' = ' + value + ';';
      }
    }

  });
*/

</script>

{'fraction_non_alphanumeric': 0.15198112439996744, 'fraction_numerical': 0.0017899275892929785, 'mean_word_length': 2.2245540398740817, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 17, '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': '3188446', 'n_tokens_mistral': 3708, 'n_tokens_neox': 3620, 'n_words': 937}