{"action":"created","issue":{"url":"https://api.github.com/repos/eslint/eslint/issues/2610","labels_url":"https://api.github.com/repos/eslint/eslint/issues/2610/labels{/name}","comments_url":"https://api.github.com/repos/eslint/eslint/issues/2610/comments","events_url":"https://api.github.com/repos/eslint/eslint/issues/2610/events","html_url":"https://github.com/eslint/eslint/issues/2610","id":80500849,"number":2610,"title":"Allow preprocessor plugins to work with the AST","user":{"login":"tqc","id":543305,"avatar_url":"https://avatars.githubusercontent.com/u/543305?v=3","gravatar_id":"","url":"https://api.github.com/users/tqc","html_url":"https://github.com/tqc","followers_url":"https://api.github.com/users/tqc/followers","following_url":"https://api.github.com/users/tqc/following{/other_user}","gists_url":"https://api.github.com/users/tqc/gists{/gist_id}","starred_url":"https://api.github.com/users/tqc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tqc/subscriptions","organizations_url":"https://api.github.com/users/tqc/orgs","repos_url":"https://api.github.com/users/tqc/repos","events_url":"https://api.github.com/users/tqc/events{/privacy}","received_events_url":"https://api.github.com/users/tqc/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/eslint/eslint/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2015-05-25T11:14:42Z","updated_at":"2015-05-29T02:54:29Z","closed_at":null,"body":"A preprocessor plugin should be able to produce an AST directly rather than just stripping out anything that isn't javascript.\r\n\r\nMy initial use case for this is linting of angular templates. It should be fairly easy to convert \r\n\r\n    Text content {{variable}} more text\r\n\r\ninto the AST for\r\n\r\n    \"Text content \" + ngbind(variable) + \" more text\"\r\n\r\nFrom there, writing rules for things like disallowing calculations in bound expressions is standard ESLint - all I need is something to connect it to. \r\n\r\nChanges required:\r\n\r\n1. Split api.verify. See #1025, but I think this is simpler than setting up a custom parameter type.\r\n - api.verify(text, ...) same as existing function\r\n - api.verifyAST(ast, text, ...) called by api.verify after parse step\r\n\r\n2. In cli-engine processFile, choose the appropriate variation of verify to call based on whether the preprocessor returned strings or an AST. Most of the concerns on #1025 seem to be around verifying that the AST is valid when it can come from anywhere. I'm not sure if verifyAST could be exposed to processFile without being fully public, but if it is for internal use only through the plugin system, anything wrong with the AST is a bug in the plugin, not core, and the validation requirement goes away.\r\n\r\n3. Pass additional parameters to processor.preprocess exposing the default parser. This could be as a reference to the linter instance or just wrapping parse(text, config) so that it doesn't require the config parameter. This would allow the output of the preprocessor to be something like \r\n\r\n```\r\n     CustomHtmlParser(\"<p>Text content</p>\")\r\n     + parse(\"< script>x=1;</script>\".replace(\"< script>\",\"\"))\r\n     + CustomHtmlParser(\"<p>More text content</p>\")'\r\n```\r\n\r\nwithout the plugin needing to know anything about the default js parser or its options."},"comment":{"url":"https://api.github.com/repos/eslint/eslint/issues/comments/106665732","html_url":"https://github.com/eslint/eslint/issues/2610#issuecomment-106665732","issue_url":"https://api.github.com/repos/eslint/eslint/issues/2610","id":106665732,"user":{"login":"tqc","id":543305,"avatar_url":"https://avatars.githubusercontent.com/u/543305?v=3","gravatar_id":"","url":"https://api.github.com/users/tqc","html_url":"https://github.com/tqc","followers_url":"https://api.github.com/users/tqc/followers","following_url":"https://api.github.com/users/tqc/following{/other_user}","gists_url":"https://api.github.com/users/tqc/gists{/gist_id}","starred_url":"https://api.github.com/users/tqc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tqc/subscriptions","organizations_url":"https://api.github.com/users/tqc/orgs","repos_url":"https://api.github.com/users/tqc/repos","events_url":"https://api.github.com/users/tqc/events{/privacy}","received_events_url":"https://api.github.com/users/tqc/received_events","type":"User","site_admin":false},"created_at":"2015-05-29T02:54:29Z","updated_at":"2015-05-29T02:54:29Z","body":"Ok, I think the initial idea can be simplified a bit. 1 goes away if #1025 is handled first, which looks like being easier to do than I initially thought. 3 can probably be handled separately - it would definitely be nice to have access to the context/config from a processor, and it ties into some of my ideas around multiple configuration, but it doesn't directly block the others.\r\n\r\nThat leaves just the processor/verify call itself, which is suitably isolated.\r\n\r\nHaving direct access to the AST should make the plugin code needed for some of my more advanced ideas a lot simpler. \r\n\r\n```\r\ncustom parser -> verify -> print messages \r\n```\r\n\r\nis a lot simpler and less error-prone than\r\n\r\n```\r\ncustom parser -> complex mapping -> generated js -> default parser -> verify -> messages -> complex mapping -> print messages\r\n```\r\n\r\n\r\n"}}