cflint / CFLint

Static code analysis for CFML (a linter)
BSD 3-Clause "New" or "Revised" License
174 stars 84 forks source link

Performance issues in ST3 #598

Open redtopia opened 6 years ago

redtopia commented 6 years ago

I am having serious performance issues using CFLint in Sublime Text 3 (SublimeLinter integration). I have to set CFLint to execute manually, and when I do, in some files, it absolutely crushes my CPU and prevents me from doing almost anything until the process completes. I'm dealing with CFCs written in cfscript with over 5K lines of code in them. Is it possible that CFLint is not terminating its current processes when the user starts typing again? Are there any settings I can tweak to get this to run automatically without sucking up my system resources? Thanks in advance, and I am very impressed with the work that has been done on this project since the last time I evaluated it. Great job everyone!!!!

TheRealAgentK commented 6 years ago

I don't know how the integration with Sublime Text 3 works in detail, but it sounds to me that this might be an issue that needs to be solved in https://github.com/ckaznocha/SublimeLinter-contrib-CFLint.

This is obviously assuming that you're using that particular plugin. From my point of view the plugin would in some way trigger the cflint binary (jar file) and if its processing takes a while and then gets retriggered over and over again, then the IDE plugin would need to prevent that in some way.

redtopia commented 6 years ago

I'm not using that plugin... I'm using SublimeLinter (http://www.sublimelinter.com/en/stable/), and pointing it to the CFLint jar file.

TheRealAgentK commented 6 years ago

Hm, ok - how is this plugin calling cflint and what parameters is it passing in the process? Is it executing cflint while you're typing all the time or is it running a lint when saving the file etc?

Ideally we'd understand whatever the "command line equivalent" is of what SublimeLinter is doing.

The other thing you could try:

Run cflint manually against one of the problematic big cfscript cfcs and see what happens - is it taking a while against these, too?

ryaneberly commented 6 years ago

Are your large cfcs pure cfscript, or a mix of cfml and cfscript?

redtopia commented 6 years ago

They are pure cfscript. I'm in the process of trying out a few SublimeLinter settings changes, and I'll report back. Specifically, I turned kill_old_processes on. Here are the default settings for SublimeLinter:

{ // Set to true to print extra information in the console. "debug": false,

    // When in the "background" lint mode, this value determines
    // the minimum delay before a request is send to the linter
    "delay": 0.1,

    // Available gutter themes:
    // - Blueberry Cross
    // - Blueberry Round
    // - Circle
    // - Danish Royalty
    // - Default
    // - Hands
    // - Knob
    // - Knob Symbol
    // - Koloria
    // - ProjectIcons
    // Note that you may need to change the "icon" property in "styles"
    // to an icon in the theme (they usually include "warning" and "error")
    "gutter_theme": "Default",

    // Demote the visibility of a class off errors while you're editing.
    // The errors will re-appear after `time_to_idle` and immediately on save.
    // - ws_only: erroneous regions that contain only whitespace
    // - some_ws: erroneous regions that contain *some* whitespace
    // - multilines: multiline errors
    // - warnings: errors of the "warning" type
    // - all: demote all the things
    // - none: disable this feature
    "highlights.demote_while_editing": "none",

    // Apply a color (via scope) to the demoted errors.
    // E.g. "" will hide the errors, "comment" is usually a subtle color.
    "highlights.demote_scope": "",

    // How long to wait before showing the demoted errors again.
    // Tip: A big value like 3600 will essentially hide the regions until
    // you save the buffer.
    "highlights.time_to_idle": 1.5,

    // Send a "terminate" signal to old lint processes, if their result would
    // be thrown away. If false we fire-and-forget processes instead.
    "kill_old_processes": false,

    // Lint Mode determines when the linter is run.
    // - background: asynchronously on every change
    // - load_save: when a file is opened and every time it's saved
    // - manual: only when calling the Lint This View command
    // - save: only when a file is saved
    "lint_mode": "background",

    // Linter specific settings.
    // More info: http://www.sublimelinter.com/en/stable/linter_settings.html
    // Linter specific settings except for "styles" can also be changed
    // in sublime-project settings.
    // What settings are available is documented in the readme of the
    // specific linter plugin.
    // Example:
    "linters": {
        // The name of the linter you installed
        "linter_name": {
            // Disables the linter. The default here is 'not set'
            "disable": false,

            // Additional arguments for the command line. Either a 'string'
            // or an 'array'. If set to a string, we 'shlex.split' it*.
            // E.g. '--ignore D112' or ['--config', './.config/foo.ini']
            //
            // * Note: Use proper quoting around paths esp. on Windows!
            "args": [],

            // Path to the executable to be used. Either a 'string' or an
            // 'array'. E.g. ['nvm', 'exec', '8.6', 'eslint']
            "executable": "<automatically set>",

            // A modified runtime environment for the lint job. Settings here
            // override the default, inherited ENV.
            "env": {},

            "excludes": [],

            // Lint mode determines when the linter is run. The linter setting
            // will take precedence over the global setting.
            "lint_mode": "manual",

            // Determines for which views this linter will run.
            "selector": "",

            // A list of additional style definition blocks.
            "styles": [
                {
                    // Instead of 'types' you can specify error 'codes' for
                    // a style definition block
                    "codes": [""]
                }
            ],

            // The current working dir the lint job will run in.
            "working_dir": "",

            // **Only valid for PythonLinter**
            // Specify which python to use. Either a number or full path
            // to a python binary. SL will then basically use 'python -m'
            // to run the linter.
            "python": 3,

            // **Only valid for NodeLinter**
            // If true, will *not* use a globally installed binary
            "disable_if_not_dependency": false
        }
    },

    // Determines what happens when a linter reports a problem without column.
    // By default, a mark is put in the gutter and the first character is highlighted.
    // If this setting is true, the entire line is also highlighted.
    "no_column_highlights_line": false,

    // Provide extra paths to be searched when locating system executables.
    "paths": {
        "linux": [],
        "osx": [],
        "windows": []
    },

    // Show a report for problems on a line by hovering over the gutter.
    "show_hover_line_report": true,

    // Show a report for problems on a region by hovering over it.
    "show_hover_region_report": true,

    // Highlight problems in the minimap.
    "show_marks_in_minimap": true,

    // Show the output panel on save if there are problems.
    // - window: check if the window has problems.
    // - view: only check the current file.
    // - never: disable this feature.
    "show_panel_on_save": "never",

    // Display counters in the status bar.
    // The {}'s will be replaced by warnings and errors respectively.
    // Example alternative: (w:{}, e:{})
    "statusbar.counters_template": "({}|{})",

    // Show the messages for problems at your cursor position.
    // - {message} will be replaced by the actual messages.
    // - {linter} will be replaced by the linter reporting the error.
    // - {type} will be replaced by either warning or error.
    // - {code} will be replaced by the error code.
    // Set to "" to display nothing
    "statusbar.messages_template": "{message}",

    "statusbar.show_active_linters": true,

    // Global styles for all linters.
    // Note: Styles can also be specified per linter! See above.
    // Only for linter-styles, there is one more setting:
    // - codes:
    //   An array which can contain error codes provided by a linter.
    //   Only valid as linter style in the "linters" section
    //
    // The styles list form a stack evaluated top-down. We call each object
    // herein a style definition. A style definition must match a specific
    // linter error, either its code or its error type, to take any effect.
    //
    // The default styles cannot be overriden per se, you extend them
    // in your user settings. The defaults can be read as "All linter problems
    // are red, outline, dots, but warnings are yellow."
    "styles": [
        {
            // Used to determine the color. E.g. region.<colorish>, with one of
            // redish, orangish, yellowish, greenish, bluish, purplish, pinkish.
            "scope": "region.yellowish markup.warning.sublime_linter",

            // The error type this style definition will match for.
            // An array which can contain "warning" and/or "error".
            // If omitted will match both.
            "types": ["warning"]
        },
        {
            // Determines, for overlapping errors, which one is visualised.
            "priority": 1,

            // The icon displayed in the gutter area
            // - "circle", "dot" or "bookmark"
            // - "none" to remove the icon
            // - A path to an icon file like
            //   "Packages/SublimeLinter/gutter-themes/Blueberry Cross/error.png"
            // - One provided by a gutter theme (e.g. "warning" or "error").
            //   In theme Default: warning, error, cog, x,
            //   and diamond, heart, pointer, square, star, triangle, which all
            //   also have an -outline variant.
            "icon": "dot",

            // The highlight style:
            // - "none"
            // - "fill", "outline",
            // - "solid_underline", "squiggly_underline", "stippled_underline"
            // The underline styles are replaced with outlines when there is
            // whitespace in the problem region, because underlines aren't drawn
            // on whitespace (ST issue #137).
            "mark_style": "outline",

            "scope": "region.redish markup.error.sublime_linter"
        }
    ],

    // DEPRECATED: use the selector linter setting instead:
    // http://www.sublimelinter.com/en/stable/linter_settings.html#selector
    // Maps variant syntaxes to the syntax that you have a linter for.
    // The syntax is the name of the syntax definition file, in lower case
    // Run this in the console to find it: view.settings().get('syntax').lower()
    "syntax_map": {
        "html (django)": "html",
        "html (rails)": "html",
        "html 5": "html",
        "javascript (babel)": "javascript",
        "magicpython": "python",
        "php": "html",
        "python django": "python",
        "pythonimproved": "python"
    }
}
redtopia commented 6 years ago

UPDATE What I'm finding is that CFLint definitely cannot be run in the background using SublimeLinter, even with kill_old_processes turned on. When doing so, my CPU is getting hammered every time I make a change. I think that kill_old_processes is making a bit of a difference, but not enough for me to turn off background linting.

It's also unclear to me how to get CFLint to exclude rules that are specified in the exclude array, which is obviously a different issue. The SublimeLinter settings expect a string for each element, whereas the CFLint settings show each element as being a struct. Maybe that's problematic... not sure.

It would be great if anyone contributing to CFLint could figure out the best settings for it to work with ST3, since it has the best CF support of all editors (imho), and I'm guessing that lots of CF devs are using it. I would love to integrate CFLint into my dev environment in a way that it's useful. I haven't gotten there yet, but I'm willing to help test if anyone pings me. Thanks!