angelozerr / tern-eslint

Tern Plugin to validate JS files with ESLint
https://github.com/eslint/eslint
MIT License
10 stars 6 forks source link

Error "Unexpected reserved word" #3

Closed letmaik closed 9 years ago

letmaik commented 9 years ago

I'm getting the following error:

-----------------------------------
Tern request#eslint:
{"query":{"type":"eslint","file":"leaflet-coverage/controls/ParameterSync.js"},"files":[{"name":"leaflet-coverage/controls/ParameterSync.js","text":"import L from 'leaflet'\r\nimport wu from 'wu'\r\n\r\n/**\r\n * Default function that checks if two Parameter objects describe\r\n * the same thing. No magic is applied here. Exact match or nothing.\r\n */\r\nfunction defaultMatch (p1, p2) {\r\n  if (!p1.observedProperty.id || !p2.observedProperty.id) {\r\n    return false\r\n  }\r\n  if (p1.observedProperty.id !== p2.observedProperty.id) {\r\n    return false\r\n  }\r\n  if (p1.unit && p2.unit) {\r\n    if (p1.unit.id && p2.unit.id && p1.unit.id !== p2.unit.id) {\r\n      return false\r\n    }\r\n    if (p1.unit.symbol && p2.unit.symbol && p1.unit.symbol !== p2.unit.symbol) {\r\n      return false\r\n    }\r\n  } else if (p1.unit || p2.unit) { // only one of both has units\r\n    return false\r\n  }\r\n  if (p1.categories && p2.categories) {\r\n    if (p1.categories.length !== p2.categories.length) {\r\n      return false\r\n    }\r\n    let idMissing = cat => !cat.id\r\n    if (p1.categories.some(idMissing) || p2.categories.some(idMissing)) {\r\n      return false\r\n    }\r\n    for (let cat1 of p1.categories) {\r\n      if (!p2.categories.some(cat2 => cat1.id === cat2.id)) {\r\n        return false\r\n      }\r\n    }\r\n  } else if (p1.categories || p2.categories) { // only one of both has categories\r\n    return false\r\n  }\r\n  return true\r\n}\r\n\r\n/**\r\n * Synchronizes visualization options of multiple layers with matching Parameter\r\n * and exposes a combined view of those options in form of a virtual layer.\r\n * \r\n * A common use case for this is to have equal palettes and only a single legend\r\n * for multiple layers describing the same parameter.\r\n * \r\n * Synchronizing visualization options means synchronizing certain common properties\r\n * of the layer instances. For example, the palette extents of two layers can be\r\n * synchronized by merging the extents of both. The logic for doing that has to\r\n * be specified in terms of binary functions supplied in the constructor.\r\n * \r\n * By default, a simple algorithm determines if two Parameter objects are equivalent\r\n * by checking whether things like observedPropery have the same ID, units are the same,\r\n * etc. This default algorithm can be replaced with a custom one. Such a custom\r\n * algorithm could relate different vocabularies with each other or perform other checks.\r\n * \r\n * @example <caption>Common palettes</caption>\r\n * let paramSync = new ParameterSync({\r\n *   syncProperties: {\r\n *     palette: (p1, p2) => p1,\r\n *     paletteExtent: (e1, e2) => e1 && e2 ? [Math.min(e1[0], e2[0]), Math.max(e1[1], e2[1])] : null\r\n *   }\r\n * }).on('parameterAdd', e => {\r\n *   // The virtual sync layer proxies the synced palette, paletteExtent, and parameter.\r\n *   // The sync layer will fire a 'remove' event once all real layers for that parameter were removed.\r\n *   let layer = e.syncLayer\r\n *   if (layer.palette) { // \r\n *     new Legend(layer, {\r\n *       position: 'bottomright'\r\n *     }).addTo(map)\r\n *   } \r\n * })\r\n * \r\n */\r\nclass ParameterSync extends L.Class {\r\n  constructor (options) {\r\n    super()\r\n    this._syncProps = options.syncProperties || {}\r\n    this._match = options.match || defaultMatch\r\n    this._paramLayers = new Map() // Map (Parameter -> Set(Layer))\r\n    this._layerListeners = new Map() // Map (Layer -> Map(type -> listener))\r\n    this._propSyncing = new Set() // Set (property name) \r\n  }\r\n  \r\n  addLayer (layer) {\r\n    if (!layer.parameter) {\r\n      return   \r\n    }\r\n    let params = Array.from(this._paramLayers.keys())\r\n    let match = params.find(p => this._match(p, layer.parameter))\r\n    \r\n    let param\r\n    if (!match) {\r\n      param = layer.parameter\r\n      this._paramLayers.set(param, new Set([layer]))\r\n    } else {\r\n      param = match\r\n      this._paramLayers.get(param).add(layer)\r\n      this._syncProperties(param)\r\n    }\r\n    \r\n    this._registerLayerListeners(layer, param)\r\n    \r\n    if (!match) {\r\n      this.fire('parameterAdd', {syncLayer: new SyncLayer(param, this)})\r\n    }\r\n  }\r\n  \r\n  _removeLayer (layer, param) {\r\n    for (let [type, fn] of this._layerListeners.get(layer)) {\r\n      layer.off(type, fn)\r\n    }\r\n    this._layerListeners.delete(layer)\r\n    this._paramLayers.get(param).delete(layer)\r\n    if (this._paramLayers.get(param).size === 0) {\r\n      this._paramLayers.delete(param)\r\n      // underscore since the 'remove' event of the syncLayer should be used\r\n      // from the outside\r\n      this.fire('_parameterRemove', {param: param})\r\n    }\r\n  }\r\n  \r\n  _registerLayerListeners (layer, param) {\r\n    let listeners = new Map([\r\n      ['remove', () => this._removeLayer(layer, param)]\r\n    ])\r\n    for (let prop of Object.keys(this._syncProps)) {\r\n      let type = prop + 'Change' // our convention is camel case\r\n      // TODO does it make sense to unify again, or should it just propagate unchanged?\r\n      listeners.set(type, () => this._syncProperty(param, prop))\r\n    }\r\n    for (let [type, fn] of listeners) {\r\n      layer.on(type, fn)\r\n    }\r\n    this._layerListeners.set(param, listeners)\r\n  }\r\n  \r\n  _syncProperties (param) {\r\n    for (let prop of Object.keys(this._syncProps)) {\r\n      this._syncProperty(param, prop)\r\n    }\r\n  }\r\n  \r\n  _syncProperty (param, prop) {\r\n    if (this._propSyncing.has(prop)) {\r\n      return\r\n    }\r\n    let propreduce = this._syncProps[prop]\r\n    let unified = wu(this._paramLayers.get(param)).map(l => l[prop]).reduce(propreduce)\r\n    // While we unify properties, stop listening for changes to prevent a cycle.\r\n    this._propSyncing.add(prop)\r\n    for (let layer_ of this._paramLayers.get(param)) {\r\n      layer_[prop] = unified\r\n    }\r\n    this._propSyncing.delete(prop)\r\n  }\r\n}\r\n\r\nParameterSync.include(L.Mixin.Events)\r\n\r\nclass SyncLayer extends L.Class {\r\n  constructor (param, paramSync) {\r\n    super()\r\n    this._param = param\r\n    paramSync.on('_parameterRemove', e => {\r\n      if (e.param === param) {\r\n        this.fire('remove')\r\n      }\r\n    })\r\n    let layers = () => paramSync._paramLayers.get(param)\r\n    for (let prop of Object.keys(paramSync._syncProps)) {\r\n      Object.defineProperty(this, prop, {\r\n        get: () => layers().values().next().value[prop],\r\n        set: v => {\r\n          paramSync._propSyncing.add(prop)\r\n          for (let layer of layers()) {\r\n            layer[prop] = v\r\n          }\r\n          paramSync._propSyncing.delete(prop)\r\n          this.fire(prop + 'Change')\r\n        },\r\n        enumerable: true\r\n      })\r\n    }\r\n  }\r\n  \r\n  get parameter () {\r\n    return this._param\r\n  }\r\n}\r\n\r\nSyncLayer.include(L.Mixin.Events)\r\n\r\n// work-around for Babel bug, otherwise ParameterSync cannot be referenced here\r\nexport { ParameterSync as default }\r\n","type":"full"}]}

Tern response#eslint with 34ms:
{"messages":[{"message":"Unexpected reserved word","severity":"error","from":-1,"to":0,"file":"leaflet-coverage/controls/ParameterSync.js"}]}
-----------------------------------

The project is here: https://github.com/Reading-eScience-Centre/leaflet-coverage

Originally reported at: https://github.com/angelozerr/tern.java/issues/234

angelozerr commented 9 years ago

I have switched to eslint 1.6.0 and now message is "Parsing error: Illegal import declaration" instead of "Unexpected reserved word" and position is correct. See test at https://github.com/angelozerr/tern-eslint/blob/master/test/issues.js#L6