├── .gitignore ├── .editorconfig ├── LICENSE ├── package.json ├── README.md ├── lib ├── Config.coffee ├── AtomConfig.coffee ├── Main.coffee └── SemanticLintProvider.coffee └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | indent_style = space 8 | indent_size = 4 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This program is free software: you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation, either version 3 of the License, or 4 | (at your option) any later version. 5 | 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License 12 | along with this program. If not, see . 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-integrator-linter-legacy-php56", 3 | "main": "./lib/Main", 4 | "version": "1.3.1", 5 | "description": "Lints your PHP source code to indicate various problems such as missing methods.", 6 | "repository": "https://github.com/php-integrator/atom-linter-legacy-php56.git", 7 | "license": "GPL-3.0", 8 | "engines": { 9 | "atom": ">=1.8.0 <2.0.0" 10 | }, 11 | "providedServices": { 12 | "linter": { 13 | "versions": { 14 | "1.0.0": "getProviders" 15 | } 16 | } 17 | }, 18 | "consumedServices": { 19 | "php-integrator.service": { 20 | "versions": { 21 | "^2.0": "setService" 22 | } 23 | }, 24 | "linter-indie": { 25 | "versions": { 26 | "1.0.0": "setLinterIndieService" 27 | } 28 | } 29 | }, 30 | "dependencies": { 31 | "jquery": "~2.1.4" 32 | }, 33 | "keywords": [ 34 | "php", 35 | "linter", 36 | "linting", 37 | "integrator", 38 | "integration", 39 | "php-integrator" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-integrator/atom-linter-legacy-php56 2 | ## Legacy 3 | This is a legacy version that requires PHP >= 5.6. Users that are on PHP 7.1 can and should use [the newer version](https://github.com/php-integrator/atom-base). 4 | 5 | This package only exists to cater towards users that are not in any position to upgrade their host PHP version. As a result, any issues that appear in this package will not be fixed, no new features will be added and no enhancements will be done. 6 | 7 | ## About 8 | This package provides linting for your PHP source code using [PHP Integrator](https://github.com/php-integrator/atom-base) as well as [linter](https://github.com/atom-community/linter). 9 | 10 | **Note that the [php-integrator-base](https://github.com/php-integrator/atom-base) package is required and needs to be set up correctly for this package to function correctly.** 11 | 12 | This package is not meant to be a replacement for existing PHP linters, but more as a complementary package that will indicate additional issues that the existing linters can't detect. 13 | 14 | What is included? 15 | * Shows docblock issues. 16 | * Shows usage of unknown class members. 17 | * Shows usage of unknown global functions. 18 | * Shows usage of unknown global constants. 19 | * Shows warnings about unused use statements. 20 | * Shows erroneous class names that can't be resolved. 21 | * Shows errors returned by the base service's indexing process. 22 | 23 | ![GPLv3 Logo](http://gplv3.fsf.org/gplv3-127x51.png) 24 | -------------------------------------------------------------------------------- /lib/Config.coffee: -------------------------------------------------------------------------------- 1 | 2 | module.exports = 3 | 4 | ##* 5 | # Abstract base class for managing configurations. 6 | ## 7 | class Config 8 | ###* 9 | * Raw configuration object. 10 | ### 11 | data: null 12 | 13 | ###* 14 | * Array of change listeners. 15 | ### 16 | listeners: null 17 | 18 | ###* 19 | * Constructor. 20 | ### 21 | constructor: () -> 22 | @listeners = {} 23 | 24 | @data = 25 | showUnknownClasses : true 26 | showUnknownMembers : true 27 | showUnknownGlobalFunctions : true 28 | showUnknownGlobalConstants : true 29 | showUnusedUseStatements : true 30 | showMissingDocs : true 31 | validateDocblockCorrectness : true 32 | 33 | @load() 34 | 35 | ###* 36 | * Loads the configuration. 37 | ### 38 | load: () -> 39 | throw new Error("This method is abstract and must be implemented!") 40 | 41 | ###* 42 | * Registers a listener that is invoked when the specified property is changed. 43 | ### 44 | onDidChange: (name, callback) -> 45 | if name not of @listeners 46 | @listeners[name] = [] 47 | 48 | @listeners[name].push(callback) 49 | 50 | ###* 51 | * Retrieves the config setting with the specified name. 52 | * 53 | * @return {mixed} 54 | ### 55 | get: (name) -> 56 | return @data[name] 57 | 58 | ###* 59 | * Retrieves the config setting with the specified name. 60 | * 61 | * @param {string} name 62 | * @param {mixed} value 63 | ### 64 | set: (name, value) -> 65 | @data[name] = value 66 | 67 | if name of @listeners 68 | for listener in @listeners[name] 69 | listener(value, name) 70 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.3.1 2 | * Rename package to demarcate legacy status. 3 | 4 | ## 1.3.0 (base 2.0.0) 5 | * Mark `show unknown members` as experimental. 6 | 7 | ## 1.2.1 8 | * Rename the package and repository. 9 | 10 | ## 1.2.0 11 | * It is now possible to disable warnings about missing documentation (thanks to [@hultberg](https://github.com/hultberg)). 12 | 13 | ## 1.1.0 (base 1.1.0) 14 | * Unknown global functions are now displayed. 15 | * Unknown global constants are now displayed. 16 | * Unknown class members are now displayed (disabled by default). 17 | * Linting will now less aggressively respond to every index. This prevents a flood of linting processes being spawned if the file being linted is long and many edits are being made (subsequently causing quick successive reindexes). 18 | 19 | ## 1.0.1 20 | * Fixed warning and error offsets when using Unicode characters. 21 | 22 | ## 1.0.0 (base 1.0.0) 23 | * Don't show unused use statements when there are syntax errors. 24 | * Sometimes a syntax error results in a statement being ignored, in turn causing the linter to mark a use statement incorrectly as unused. This mitigates that behavior. 25 | 26 | ## 0.3.0 (base 0.9.0) 27 | * There is now a settings screen to disable certain aspects of the linting process. 28 | * The linter can now utilize the new functionality of the base service to lint docblock correctness (enabled by default). 29 | * Due to changes in the base service, multiple syntax errors can now be shown at the same time in some cases (instead of the next popping up after correcting the first). 30 | 31 | ## 0.2.2 (base 0.8.0) 32 | * Update to use the most recent version of the base service. 33 | 34 | ## 0.2.1 35 | * Catch errors when no linter is set. 36 | 37 | ## 0.2.0 (base 0.7.0) 38 | * Show warnings about unused use statements. 39 | * Show erroneous class names that can't be resolved. 40 | 41 | ## 0.1.0 42 | * Initial release. 43 | -------------------------------------------------------------------------------- /lib/AtomConfig.coffee: -------------------------------------------------------------------------------- 1 | Config = require './Config' 2 | 3 | module.exports = 4 | 5 | ##* 6 | # Config that retrieves its settings from Atom's config. 7 | ## 8 | class AtomConfig extends Config 9 | ###* 10 | * The name of the package to use when searching for settings. 11 | ### 12 | packageName: null 13 | 14 | ###* 15 | * @inheritdoc 16 | ### 17 | constructor: (@packageName) -> 18 | super() 19 | 20 | @attachListeners() 21 | 22 | ###* 23 | * @inheritdoc 24 | ### 25 | load: () -> 26 | @set('showUnknownClasses', atom.config.get("#{@packageName}.showUnknownClasses")) 27 | @set('showUnknownMembers', atom.config.get("#{@packageName}.showUnknownMembers")) 28 | @set('showUnknownGlobalFunctions', atom.config.get("#{@packageName}.showUnknownGlobalFunctions")) 29 | @set('showUnknownGlobalConstants', atom.config.get("#{@packageName}.showUnknownGlobalConstants")) 30 | @set('showUnusedUseStatements', atom.config.get("#{@packageName}.showUnusedUseStatements")) 31 | @set('showMissingDocs', atom.config.get("#{@packageName}.showMissingDocs")) 32 | @set('validateDocblockCorrectness', atom.config.get("#{@packageName}.validateDocblockCorrectness")) 33 | 34 | ###* 35 | * Attaches listeners to listen to Atom configuration changes. 36 | ### 37 | attachListeners: () -> 38 | atom.config.onDidChange "#{@packageName}.showUnknownClasses", () => 39 | @set('showUnknownClasses', atom.config.get("#{@packageName}.showUnknownClasses")) 40 | 41 | atom.config.onDidChange "#{@packageName}.showUnknownMembers", () => 42 | @set('showUnknownMembers', atom.config.get("#{@packageName}.showUnknownMembers")) 43 | 44 | atom.config.onDidChange "#{@packageName}.showUnknownGlobalFunctions", () => 45 | @set('showUnknownGlobalFunctions', atom.config.get("#{@packageName}.showUnknownGlobalFunctions")) 46 | 47 | atom.config.onDidChange "#{@packageName}.showUnknownGlobalConstants", () => 48 | @set('showUnknownGlobalConstants', atom.config.get("#{@packageName}.showUnknownGlobalConstants")) 49 | 50 | atom.config.onDidChange "#{@packageName}.showUnusedUseStatements", () => 51 | @set('showUnusedUseStatements', atom.config.get("#{@packageName}.showUnusedUseStatements")) 52 | 53 | atom.config.onDidChange "#{@packageName}.showMissingDocs", () => 54 | @set('showMissingDocs', atom.config.get("#{@packageName}.showMissingDocs")) 55 | 56 | atom.config.onDidChange "#{@packageName}.validateDocblockCorrectness", () => 57 | @set('validateDocblockCorrectness', atom.config.get("#{@packageName}.validateDocblockCorrectness")) 58 | -------------------------------------------------------------------------------- /lib/Main.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | ###* 3 | * Configuration settings. 4 | ### 5 | config: 6 | showUnknownClasses: 7 | title : 'Show unknown classes' 8 | description : ''' 9 | Highlights class names that could not be found. This will also work for docblocks. 10 | ''' 11 | type : 'boolean' 12 | default : true 13 | order : 1 14 | 15 | showUnknownGlobalFunctions: 16 | title : 'Show unknown global functions' 17 | description : ''' 18 | Highlights global functions that could not be found. 19 | ''' 20 | type : 'boolean' 21 | default : true 22 | order : 2 23 | 24 | showUnknownGlobalConstants: 25 | title : 'Show unknown global constants' 26 | description : ''' 27 | Highlights global constants that could not be found. 28 | ''' 29 | type : 'boolean' 30 | default : true 31 | order : 3 32 | 33 | showUnusedUseStatements: 34 | title : 'Show unused use statements' 35 | description : ''' 36 | Highlights use statements that don't seem to be used anywhere. This will also look inside docblocks. 37 | ''' 38 | type : 'boolean' 39 | default : true 40 | order : 4 41 | 42 | showMissingDocs: 43 | title : 'Show missing documentation' 44 | description : ''' 45 | Warns about any structural element that is currently missing documentation. 46 | ''' 47 | type : 'boolean' 48 | default : true 49 | order : 5 50 | 51 | validateDocblockCorrectness: 52 | title : 'Validate docblock correctness' 53 | description : ''' 54 | Analyzes the correctness of docblocks of structural elements such as classes, methods and properties. 55 | This will show various problems with docblocks such as missing parameters, incorrect parameter types 56 | and missing documentation. 57 | ''' 58 | type : 'boolean' 59 | default : true 60 | order : 6 61 | 62 | showUnknownMembers: 63 | title : 'Show unknown members (experimental)' 64 | description : ''' 65 | Highlights class members that could not be found. Note that this can be a large strain on performance. 66 | It is also experimental and might show false positives (especially inside conditionals). 67 | ''' 68 | type : 'boolean' 69 | default : false 70 | order : 7 71 | 72 | ###* 73 | * The name of the package. 74 | ### 75 | packageName: 'php-integrator-linter' 76 | 77 | ###* 78 | * The configuration object. 79 | ### 80 | configuration: null 81 | 82 | ###* 83 | * List of linters. 84 | ### 85 | providers: [] 86 | 87 | ###* 88 | * List of indie linters. 89 | ### 90 | indieProviders: [] 91 | 92 | ###* 93 | * The semantic lint provider. 94 | ### 95 | semanticLintProvider: null 96 | 97 | ###* 98 | * Activates the package. 99 | ### 100 | activate: -> 101 | AtomConfig = require './AtomConfig' 102 | SemanticLintProvider = require './SemanticLintProvider' 103 | 104 | @configuration = new AtomConfig(@packageName) 105 | 106 | @semanticLintProvider = new SemanticLintProvider(@configuration) 107 | 108 | @indieProviders.push(@semanticLintProvider) 109 | 110 | ###* 111 | * Deactivates the package. 112 | ### 113 | deactivate: -> 114 | @deactivateProviders() 115 | 116 | ###* 117 | * Activates the providers using the specified service. 118 | ### 119 | activateProviders: (service) -> 120 | for provider in @providers 121 | provider.activate(service) 122 | 123 | for provider in @indieProviders 124 | provider.activate(service) 125 | 126 | ###* 127 | * Deactivates any active providers. 128 | ### 129 | deactivateProviders: () -> 130 | for provider in @providers 131 | provider.deactivate() 132 | 133 | @providers = [] 134 | 135 | for provider in @indieProviders 136 | provider.deactivate() 137 | 138 | @indieProviders = [] 139 | 140 | ###* 141 | * Sets the php-integrator service. 142 | * 143 | * @param {mixed} service 144 | * 145 | * @return {Disposable} 146 | ### 147 | setService: (service) -> 148 | @activateProviders(service) 149 | 150 | {Disposable} = require 'atom' 151 | 152 | return new Disposable => @deactivateProviders() 153 | 154 | ###* 155 | * Sets the linter indie service. 156 | * 157 | * @param {mixed} service 158 | * 159 | * @return {Disposable} 160 | ### 161 | setLinterIndieService: (service) -> 162 | #indexingIndieLinter = null 163 | semanticIndieLinter = null 164 | 165 | if service 166 | semanticIndieLinter = service.register({name : @packageName, scope: 'file', grammarScopes: ['source.php']}) 167 | 168 | @semanticLintProvider.setIndieLinter(semanticIndieLinter) 169 | 170 | ###* 171 | * Retrieves a list of supported autocompletion providers. 172 | * 173 | * @return {array} 174 | ### 175 | getProviders: -> 176 | return @providers 177 | -------------------------------------------------------------------------------- /lib/SemanticLintProvider.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | 3 | ##* 4 | # The (provider) that handles indexing errors using an indie linter. 5 | ## 6 | class IndexingProvider 7 | ###* 8 | * The service (that can be used to query the source code and contains utility methods). 9 | ### 10 | service: null 11 | 12 | ###* 13 | * The indie linter. 14 | ### 15 | indieLinter: null 16 | 17 | ###* 18 | * Contains global package settings. 19 | ### 20 | config: null 21 | 22 | ###* 23 | * Keeps track of whether a linting operation is currently running. 24 | ### 25 | isLintingInProgress: false 26 | 27 | ###* 28 | * Whether to ignore the next linting result. 29 | ### 30 | ignoreLintingResult: false 31 | 32 | ###* 33 | * The next editor to start a linting task for. 34 | ### 35 | nextEditor: null 36 | 37 | ###* 38 | * Constructor. 39 | * 40 | * @param {Config} config 41 | ### 42 | constructor: (@config) -> 43 | 44 | ###* 45 | * Initializes this provider. 46 | * 47 | * @param {mixed} service 48 | ### 49 | activate: (@service) -> 50 | @attachListeners(@service) 51 | 52 | ###* 53 | * Deactives the provider. 54 | ### 55 | deactivate: () -> 56 | 57 | ###* 58 | * Sets the indie linter to use. 59 | * 60 | * @param {mixed} indieLinter 61 | ### 62 | setIndieLinter: (@indieLinter) -> 63 | @messages = [] 64 | 65 | ###* 66 | * Attaches listeners for the specified base service. 67 | * 68 | * @param {mixed} service 69 | ### 70 | attachListeners: (service) -> 71 | service.onDidFinishIndexing (response) => 72 | editor = @findTextEditorByPath(response.path) 73 | 74 | return if not editor? 75 | return if not @indieLinter? 76 | 77 | @semanticLint(editor) 78 | 79 | service.onDidFailIndexing (response) => 80 | editor = @findTextEditorByPath(response.path) 81 | 82 | return if not editor? 83 | return if not @indieLinter? 84 | 85 | @semanticLint(editor) 86 | 87 | ###* 88 | * @param {TextEditor} editor 89 | * 90 | * @return {Promise} 91 | ### 92 | semanticLint: (editor) -> 93 | if @isLintingInProgress 94 | # This file is already being linted, but by the time it finishes, the results will be out of date and we 95 | # will then need to perform a new lint (we don't do it now to avoid spawning an excessive amount of 96 | # linting processes). 97 | @ignoreLintingResult = true 98 | @nextEditor = editor 99 | return 100 | 101 | @isLintingInProgress = true 102 | 103 | doneHandler = () => 104 | ignoreResult = @ignoreLintingResult 105 | 106 | @isLintingInProgress = false 107 | @ignoreLintingResult = false 108 | 109 | if ignoreResult 110 | # The result was ignored because there is more recent data, run again. 111 | @semanticLint(@nextEditor) 112 | 113 | return ignoreResult 114 | 115 | successHandler = (response) => 116 | return if doneHandler() 117 | 118 | @processSuccess(editor, response) 119 | 120 | failureHandler = (response) => 121 | return if doneHandler() 122 | 123 | @processFailure() 124 | 125 | return @invokeSemanticLint(editor.getPath(), editor.getBuffer().getText()).then( 126 | successHandler, 127 | failureHandler 128 | ) 129 | 130 | ###* 131 | * @param {String} path 132 | * @param {String} source 133 | * 134 | * @return {Promise} 135 | ### 136 | invokeSemanticLint: (path, source) -> 137 | options = { 138 | noUnknownClasses : not @config.get('showUnknownClasses') 139 | noUnknownMembers : not @config.get('showUnknownMembers') 140 | noUnknownGlobalFunctions : not @config.get('showUnknownGlobalFunctions') 141 | noUnknownGlobalConstants : not @config.get('showUnknownGlobalConstants') 142 | noUnusedUseStatements : not @config.get('showUnusedUseStatements') 143 | noDocblockCorrectness : not @config.get('validateDocblockCorrectness') 144 | } 145 | 146 | return @service.semanticLint(path, source, options) 147 | 148 | ###* 149 | * @param {TextEditor} editor 150 | * @param {Object} response 151 | ### 152 | processSuccess: (editor, response) -> 153 | return if not @indieLinter 154 | 155 | messages = [] 156 | 157 | if response.errors.syntaxErrors? 158 | for item in response.errors.syntaxErrors 159 | messages.push @createLinterMessageForSyntaxErrorOutputItem(editor, item) 160 | 161 | if response.errors.unknownClasses? 162 | for item in response.errors.unknownClasses 163 | messages.push @createLinterMessageForOutputItem( 164 | editor, 165 | item, 166 | 'Error', 167 | "#{item.name} was not found." 168 | ) 169 | 170 | if response.errors.unknownMembers? 171 | for item in response.errors.unknownMembers.expressionHasNoType 172 | messages.push @createLinterMessageForOutputItem( 173 | editor, 174 | item, 175 | 'Error', 176 | "The member #{item.memberName} could not be found because the expression has no type." 177 | ) 178 | 179 | for item in response.errors.unknownMembers.expressionIsNotClasslike 180 | messages.push @createLinterMessageForOutputItem( 181 | editor, 182 | item, 183 | 'Error', 184 | "Type #{item.expressionType} does not have a member #{item.memberName}." 185 | ) 186 | 187 | for item in response.errors.unknownMembers.expressionHasNoSuchMember 188 | messages.push @createLinterMessageForOutputItem( 189 | editor, 190 | item, 191 | 'Error', 192 | "The member #{item.memberName} does not exist for type #{item.expressionType}." 193 | ) 194 | if response.warnings.unknownMembers? 195 | for item in response.warnings.unknownMembers.expressionNewMemberWillBeCreated 196 | messages.push @createLinterMessageForOutputItem( 197 | editor, 198 | item, 199 | 'Warning', 200 | "The member #{item.memberName} was not explicitly defined for type #{item.expressionType}." 201 | ) 202 | 203 | if response.errors.unknownGlobalFunctions? 204 | for item in response.errors.unknownGlobalFunctions 205 | messages.push @createLinterMessageForOutputItem( 206 | editor, 207 | item, 208 | 'Error', 209 | "The global function #{item.name} was not found." 210 | ) 211 | 212 | if response.errors.unknownGlobalConstants? 213 | for item in response.errors.unknownGlobalConstants 214 | messages.push @createLinterMessageForOutputItem( 215 | editor, 216 | item, 217 | 'Error', 218 | "The global constant #{item.name} was not found." 219 | ) 220 | 221 | if response.warnings.unusedUseStatements? and response.errors.syntaxErrors?.length == 0 222 | for item in response.warnings.unusedUseStatements 223 | messages.push @createLinterMessageForOutputItem( 224 | editor, 225 | item, 226 | 'Warning', 227 | "#{item.name} is not used anywhere." 228 | ) 229 | 230 | if response.warnings.docblockIssues? 231 | for item in response.warnings.docblockIssues.varTagMissing 232 | messages.push @createLinterMessageForOutputItem( 233 | editor, 234 | item, 235 | 'Warning', 236 | "The docblock for #{item.name} is missing a @var tag." 237 | ) 238 | 239 | if @config.get('showMissingDocs') 240 | for item in response.warnings.docblockIssues.missingDocumentation 241 | messages.push @createLinterMessageForOutputItem( 242 | editor, 243 | item, 244 | 'Warning', 245 | "Documentation for #{item.name} is missing." 246 | ) 247 | 248 | for item in response.warnings.docblockIssues.parameterMissing 249 | messages.push @createLinterMessageForOutputItem( 250 | editor, 251 | item, 252 | 'Warning', 253 | "The docblock for #{item.name} is missing a @param tag for #{item.parameter}." 254 | ) 255 | 256 | for item in response.warnings.docblockIssues.parameterTypeMismatch 257 | messages.push @createLinterMessageForOutputItem( 258 | editor, 259 | item, 260 | 'Warning', 261 | "The docblock for #{item.name} has an incorrect @param type for #{item.parameter}." 262 | ) 263 | 264 | for item in response.warnings.docblockIssues.superfluousParameter 265 | parameters = item.parameters.join(', ') 266 | 267 | messages.push @createLinterMessageForOutputItem( 268 | editor, 269 | item, 270 | 'Warning', 271 | "The docblock for #{item.name} contains superfluous @param tags for: #{parameters}." 272 | ) 273 | 274 | for item in response.warnings.docblockIssues.deprecatedCategoryTag 275 | messages.push @createLinterMessageForOutputItem( 276 | editor, 277 | item, 278 | 'Warning', 279 | "The docblock for #{item.name} contains a deprecated @category tag." 280 | ) 281 | 282 | for item in response.warnings.docblockIssues.deprecatedSubpackageTag 283 | messages.push @createLinterMessageForOutputItem( 284 | editor, 285 | item, 286 | 'Warning', 287 | "The docblock for #{item.name} contains a deprecated @subpackage tag." 288 | ) 289 | 290 | link = 'https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#710-link-deprecated' 291 | 292 | for item in response.warnings.docblockIssues.deprecatedLinkTag 293 | messages.push @createLinterMessageForOutputItem( 294 | editor, 295 | item, 296 | 'Warning', 297 | "The docblock for #{item.name} contains a deprecated @link tag. See also #{link}" 298 | ) 299 | 300 | @indieLinter.setMessages(messages) 301 | 302 | ###* 303 | * 304 | ### 305 | processFailure: () -> 306 | return if not @indieLinter 307 | 308 | @indieLinter.setMessages([]) 309 | 310 | ###* 311 | * @param {TextEditor} editor 312 | * @param {Object} item 313 | * 314 | * @return {Object} 315 | ### 316 | createLinterMessageForSyntaxErrorOutputItem: (editor, item) -> 317 | startLine = if item.startLine then item.startLine else 1 318 | endLine = if item.endLine then item.endLine else 1 319 | 320 | startColumn = if item.startColumn then item.startColumn else 1 321 | endColumn = if item.endColumn then item.endColumn else 1 322 | 323 | return { 324 | type : 'Error' 325 | html : item.message 326 | range : [[startLine - 1, startColumn - 1], [endLine - 1, endColumn]] 327 | filePath : editor.getPath() 328 | } 329 | 330 | ###* 331 | * @param {TextEditor} editor 332 | * @param {Object} item 333 | * @param {string} type 334 | * @param {string} html 335 | * 336 | * @return {Object} 337 | ### 338 | createLinterMessageForOutputItem: (editor, item, type, html) -> 339 | text = editor.getBuffer().getText() 340 | 341 | startCharacterOffset = @service.getCharacterOffsetFromByteOffset(item.start, text) 342 | endCharacterOffset = @service.getCharacterOffsetFromByteOffset(item.end, text) 343 | 344 | startPoint = editor.getBuffer().positionForCharacterIndex(startCharacterOffset) 345 | endPoint = editor.getBuffer().positionForCharacterIndex(endCharacterOffset) 346 | 347 | return { 348 | type : type 349 | html : html 350 | range : [startPoint, endPoint] 351 | filePath : editor.getPath() 352 | } 353 | 354 | ###* 355 | * Retrieves the text editor that is managing the file with the specified path. 356 | * 357 | * @param {string} path 358 | * 359 | * @return {TextEditor|null} 360 | ### 361 | findTextEditorByPath: (path) -> 362 | for textEditor in atom.workspace.getTextEditors() 363 | if textEditor.getPath() == path 364 | return textEditor 365 | 366 | return null 367 | --------------------------------------------------------------------------------