Ejemplo n.º 1
0
    def lint_with_text(self, request, text):
        cwd = request.cwd
        prefset = getProxiedEffectivePrefs(request)
        # Remove a possible "-d" in the shebang line, this will tell Perl to
        # launch the debugger which, if the PDK is installed, is the PDK
        # debugger.  Be careful to handle single-line files correctly.
        splitText = text.split("\n", 1)
        firstLine = RemoveDashDFromShebangLine(splitText[0])
        if len(splitText) > 1:
            text = "\n".join([firstLine, splitText[1]])
        else:
            text = firstLine
        if prefset.getBooleanPref("perl_lintOption_disableBeginBlocks"):
            text = _begin_to_init_re.sub("INIT", text)
        # Save perl buffer to a temporary file.

        tmpFileName = self._writeTempFile(cwd, text)
        try:
            perlExe = self._selectPerlExe(prefset)
            lintOptions = prefset.getStringPref("perl_lintOption")
            option = '-' + lintOptions
            perlExtraPaths = prefset.getStringPref("perlExtraPaths")
            if perlExtraPaths:
                if sys.platform.startswith("win"):
                    perlExtraPaths = perlExtraPaths.replace('\\', '/')
                perlExtraPaths = [
                    x for x in perlExtraPaths.split(os.pathsep) if x.strip()
                ]
            argv = [perlExe]
            for incpath in perlExtraPaths:
                argv += ['-I', incpath]
            if prefset.getBooleanPref(
                    "perl_lintOption_includeCurrentDirForLinter"):
                argv += ['-I', '.']

            # bug 27963: Fix instances of <<use PerlTray>> from code
            # to make them innocuous for the syntax checker.
            # 'use PerlTray' in comments or strings will trigger a false positive
            if sys.platform.startswith(
                    "win") and self._use_perltray_module.search(text):
                argv += ['-I', self._perlTrayDir]

            argv.append(option)
            argv.append(tmpFileName)
            cwd = cwd or None  # convert '' to None (cwd=='' for new files)
            env = koprocessutils.getUserEnv()
            # We only need stderr output.

            p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None)
            _, stderr = p.communicate()
            lintResults = PerlWarnsToLintResults(stderr.splitlines(1),
                                                 tmpFileName,
                                                 request.koDoc.displayPath,
                                                 text)
        finally:
            os.unlink(tmpFileName)

        return lintResults
Ejemplo n.º 2
0
    def lint_with_text(self, request, text):
        if not text:
            return None
        prefset = getProxiedEffectivePrefs(request)
        if not prefset.getBooleanPref("lint_python_with_pyflakes"):
            return
        pythonExe = self._pythonInfo.getExecutableFromDocument(request.koDoc)
        if not pythonExe:
            return
        tmpfilename = tempfile.mktemp() + '.py'
        fout = open(tmpfilename, 'wb')
        fout.write(text)
        fout.close()
        textlines = text.splitlines()
        cwd = request.cwd
        env = self._get_fixed_env(prefset)
        try:
            checkerExe = which.which("pyflakes", path=_getUserPath())
        except which.WhichError:
            log.warn("pyflakes not found")
            return
        if not checkerExe:
            log.warn("pyflakes not found")
            return
            
        cmd = [pythonExe, checkerExe, tmpfilename]
        # stdout for pyflakes.checker.Checker
        # stderr for __builtin__.compile()
        try:
            p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None)
            stdout, stderr = p.communicate()
            errorLines = stderr.splitlines(0) # Don't need the newlines.
            warnLines = stdout.splitlines() 
        finally:
            os.unlink(tmpfilename)
        results = koLintResults()

        # "createAddResult" will change lineno in some situation, so we use our version
        self._createAddResult(results, textlines, errorLines, koLintResult.SEV_ERROR)
        self._createAddResult(results, textlines, warnLines, koLintResult.SEV_WARNING)
        return results
Ejemplo n.º 3
0
    def run(self):
        """Process lint requests serially until told to stop.
        
        Before the requested linter is run on a document it is first checked
        for encoding problems (i.e. encoding is not sufficient for current
        content).
        """
        TIME_LINTS = False
        log.info("manager thread: start")
        while 1:
            try:
                # wait for next request
                request = self.requests.get()
                
                # quit if request is the quit sentinel
                if request is None:
                    log.info("manager thread: quit sentinel")
                    break
    
                # process the request
                if TIME_LINTS: startlint = time.clock()
                log.info("manager thread: process request: %r", request)
                try:
                    # Look for encoding errors first.
                    results = self._getEncodingLintResults(request.content,
                                                           request.encoding)
                    if TIME_LINTS: endencodinglint = time.clock()

                    # If there were no encoding errors, try the
                    # requested linter.
                    if not results.getNumResults() and request.linter:
                        #XXX This is where context-sensitive linting args should
                        #    be passed in, but linters don't support this yet.
                        log.debug("manager thread: call linter.lint(request)")
                        try:
                            if self._passesGenericCheck(request):
                                results = request.linter.lint(request)
                                #results = UnwrapObject(request.linter).lint(request)
                                # This makes a red statusbar icon go green, but it
                                # might not be what we always want.
                                # Needs more investigation.
                                #if results is None:
                                #   results = koLintResults() 
                            
                        except:
                            log.exception("Unexpected error while linting")
                        
                        # This makes a red statusbar icon go green, but it
                        # might not be what we always want.
                        # Needs more investigation.
                        #if results is None:
                        #   results = koLintResults() 
                        log.debug("manager thread: linter.lint(request) returned")
                    if TIME_LINTS: endlintlint = time.clock()

                    prefset = getProxiedEffectivePrefs(request)
                    if prefset.getBooleanPref("lintEOLs"):
                        # Also look for mixed-line endings warnings.
                        self._addMixedEOLWarnings(results, request.content,
                            request.koDoc.new_line_endings)

                    if TIME_LINTS:
                        endeollint = time.clock()
                        print "lint of '%s': encoding=%.3fs  lint=%.3fs  eol=%.3fs"\
                              % (request.koDoc.baseName,
                                 endencodinglint-startlint,
                                 endlintlint-endencodinglint,
                                 endeollint-endlintlint)
    
                    request.results = results
                except (ServerException, COMException), ex:
                    request.errorString = str(ex)
                except:
                    # Any exceptions that are not ServerException or
                    # COMException are unexpected internal errors.
                    try:
                        err = "unexpected internal error checking '%s' with '%s' linter"\
                            % (request.koDoc.baseName, request.linterType)
                        log.exception(err)
                        request.errorString = err
                    except:
                        err = "Unexpected error in koLintService.run"
                        log.error(err)
                        request.errorString = err
                else:
                    log.info("manager thread: lint results for uid %s: %r",
                             request.uid, results)

                # Notify of request completion
                # Note: this is not guaranteed to properly guard the proxy
                # call because a context switch could happen in between the
                # condition check and body. That is ok though. At worst it
                # will raise an exception that will be trapped just below.
                # The point is to catch the common case. I am pretty sure
                # that there is no way to do this properly without going
                # to great lengths.
                if not self._shuttingDown:
                    try:
                        # Proxy this so the worker thread can report results on this iface.
                        lintBufferProxy = getProxyForObject(1,
                            components.interfaces.koILintBuffer, request.lintBuffer,
                            PROXY_ALWAYS | PROXY_SYNC)
                        lintBufferProxy.reportResults(request)
                    except COMException, ex:
                        # Ignore this error, which will happen if results
                        # are reported after the buffer has gone away (i.e.
                        # the file owning that buffer was closed):
                        #   Traceback (most recent call last):
                        #     File "...\koLintService.py", line 370, in run
                        #       request.lintBuffer.reportResults(request)
                        #     File "<XPCOMObject method 'reportResults'>", line 3, in reportResults
                        #   Exception: 0x80570021 ()
                        errno = ex.args[0]
                        if errno == 0x80570021:
                            pass
                        else:
                            raise
Ejemplo n.º 4
0
 def __init__(self, request, scope):
     if haveKO8:
         self.prefset = request.prefset
     else:
         self.prefset = getProxiedEffectivePrefs(request)
     self.scope = scope
Ejemplo n.º 5
0
    def lint_with_text(self, request, text):
        if not text.strip():
            return None
        prefset = getProxiedEffectivePrefs(request)
        cwd = request.cwd
        env = koprocessutils.getUserEnv()
        settingsDir = env.get("DJANGO_SETTINGS_MODULE", None)
        if not settingsDir:
            settingsDir = self._getSettingsDir(cwd)
        if settingsDir:
            # Save the current buffer to a temporary file.
            tmpFileName = tempfile.mktemp()
            fout = open(tmpFileName, 'wb')
            try:
                fout.write(text)
                fout.close()

                #XXX: How to tell whether we're using Python or Python3?
                prefName = "pythonExtraPaths"
                pythonPath = prefset.hasPref(
                    prefName) and prefset.getStringPref(prefName) or None
                pythonPathEnv = env.get("PYTHONPATH", "")
                if pythonPathEnv:
                    if pythonPath:
                        pythonPath += os.pathsep + pythonPathEnv
                    else:
                        pythonPath = pythonPathEnv
                if pythonPath:
                    if sys.platform.startswith("win"):
                        pythonPath = pythonPath.replace('\\', '/')
                    env["PYTHONPATH"] = pythonPath
                elif env.has_key("PYTHONPATH"):
                    del env["PYTHONPATH"]

                results = koLintResults()
                pythonExe = self._pythonInfo.getExecutableFromDocument(
                    request.koDoc)
                argv = [
                    pythonExe, self._djangoLinterPath, tmpFileName, settingsDir
                ]
                p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None)
                output, error = p.communicate()
                #log.debug("Django output: output:[%s], error:[%s]", output, error)
                retval = p.returncode
            finally:
                os.unlink(tmpFileName)
            if retval == 1:
                if error:
                    results.addResult(self._buildResult(text, error))
                else:
                    results.addResult(
                        self._buildResult(text, "Unexpected error"))
        else:
            result = KoLintResult()
            result.lineStart = 1
            result.lineEnd = 1
            result.columnStart = 1
            result.columnEnd = 1 + len(text.splitlines(1)[0])
            result.description = "Can't find settings.py for this Django file"
            result.encodedDescription = result.description
            result.severity = result.SEV_ERROR
            results = koLintResults()
            results.addResult(result)
        return results
Ejemplo n.º 6
0
    def lint_with_text(self, request, text):
        """Lint the given Tcl content.
        
        Raise an exception if there is a problem.
        """
        prefset = getProxiedEffectivePrefs(request)
        argv = self._getLinterArgv(prefset)
        env = koprocessutils.getUserEnv()

        # if there is no setting for the dev kit environment, use
        # the shared directory for it.  This enables site wide
        # use of *.pdx and *.pcx files for debugging

        if "TCLDEVKIT_LOCAL" not in env:
            koDirs = components.classes["@activestate.com/koDirs;1"].\
                getService(components.interfaces.koIDirs)
            sharedDir = os.path.join(koDirs.commonDataDir, "tcl")
            env["TCLDEVKIT_LOCAL"] = sharedDir

        if prefset.hasPref("tclExtraPaths"):
            tclExtraPaths = prefset.getStringPref("tclExtraPaths")
            # If TCLLIBPATH is set, then it must contain a valid Tcl
            # list giving directories to search during auto-load
            # operations. Directories must be specified in Tcl format,
            # using "/" as the path separator, regardless of platform.
            # This variable is only used when initializing the
            # auto_path variable.  Also escape spaces in paths.
            tclExtraPaths = tclExtraPaths.replace('\\', '/')
            tclExtraPaths = tclExtraPaths.replace(' ', '\ ')
            TCLLIBPATH = ' '.join(tclExtraPaths.split(os.pathsep))
            env["TCLLIBPATH"] = TCLLIBPATH

        cwd = request.cwd or None
        print 'argv: %r' % (argv, )
        p = process.ProcessOpen(argv, cwd=cwd, env=env)
        lOutput, lErrOut = p.communicate(text)
        lOutput = lOutput.splitlines(1)
        #print '======'
        #print lOutput
        #print '======'
        #print lErrOut
        #print '<<<<<<'

        if not lOutput and lErrOut:
            raise ServerException(nsError.NS_ERROR_UNEXPECTED, lErrOut)
        
        if not lOutput:
            # this should never happen unless the tcl linter is broken, or
            # not executable on linux.
            raise ServerException(nsError.NS_ERROR_UNEXPECTED,
                                  "No output from Tcl linter available")
        
        if lOutput[0].startswith("TclPro") or \
           lOutput[0].startswith("scanning"):
            # The open source TclPro has the header stripped,
            # so we need to check for both "TclPro" and "scanning"
            lInput = text.split('\n')
            return self._TclPro_lint(lInput, lOutput)
        else:
            errmsg = "unrecognized lint output format:\n%s" % lOutput[0]
            raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg)
Ejemplo n.º 7
0
    def lint_with_text(self, request, text):
        encoding_name = request.encoding.python_encoding_name
        cwd = request.cwd
        prefset = getProxiedEffectivePrefs(request)
        prefName = "lint_%s_with_standard_python" % self.language_name_lc
        if not prefset.getBooleanPref(prefName):
            return
        try:
            # Get the Python interpreter (prefs or first valid one on the path).
            interpreter_pref_name = "%sDefaultInterpreter" % (self.language_name_lc, )
            python = prefset.getString(interpreter_pref_name)
            if not python:
                python = self._pythonInfo.executablePath
                if not python:
                    return
            if not self._pythonInfo.isSupportedBinary(python):
                raise ServerException(nsError.NS_ERROR_FAILURE,
                                      "Invalid %r executable: %r" %
                                      (self.language_name, python))
            # Determine the pycompile settings.
            if self.language_name == "Python3":
                compilePy = os.path.join(self._koDirSvc.supportDir, "python",
                                         "py3compile.py")
                if encoding_name not in self._simple_python3_string_encodings:
                    # First, make sure the text is Unicode
                    if type(text) == self._stringType:
                        text = text.decode(encoding_name)
                    # Now save it as utf-8 -- python3 knows how to read utf-8
                    text = text.encode("utf-8")
            else:
                compilePy = os.path.join(self._koDirSvc.supportDir, "python",
                                         "pycompile.py")
            if request.koDoc.displayPath.startswith("macro2://"):
                text = projectUtils.wrapPythonMacro(text)
                leadingWS = _leading_ws_re.match(text.splitlines()[1]).group(1)
            else:
                leadingWS = None

            # Save the current buffer to a temporary file.
            tmpFileName = tempfile.mktemp()
            fout = open(tmpFileName, 'wb')
            fout.write(text)
            fout.close()
    
            results = koLintResults()
            try:
                argv = [python, '-u', compilePy, tmpFileName]
                #print "---- check syntax of the following with %r" % argv
                #sys.stdout.write(text)
                #print "-"*70
    
                cwd = cwd or None
                env = self._get_fixed_env(prefset)
                if sys.platform.startswith("win") and cwd is not None\
                   and cwd.startswith("\\\\"):
                    # Don't try to switch to a UNC path because pycompile.py
                    # ends up spitting out:
                    #     CMD.EXE was started with '\\netshare\apps\Komodo\stuff' as the current directory
                    #     path.  UNC paths are not supported.  Defaulting to Windows directory.
                    # XXX Could perhaps try to ensure that command is not
                    #     run via "cmd.exe /c", but don't know if that would
                    #     help either.
                    cwd = None
                
                p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None)
                output, error = p.communicate()
                retval = p.returncode
                #print "-"*60, "env"
                #pprint(env)
                #print "-"*60, "output"
                #print output
                #print "-"*60, "error"
                #print error
                #print "-"*70
                if retval:
                    errmsg = "Error checking syntax: retval=%s, stderr=%s"\
                             % (retval, error)
                    log.exception(errmsg)
                    raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg)
                else:
                    # Parse syntax errors in the output.
                    dicts = eval(output)
                    for d in dicts:
                        results.addResult( self._buildResult(d, leadingWS) )
                    # Parse warnings in the error.
                    results.addResults(self._parseWarnings(error, text, leadingWS))
            finally:
                os.unlink(tmpFileName)
        except ServerException:
            log.exception("ServerException")
            raise
        except:
            # non-ServerException's are unexpected internal errors
            log.exception("unexpected internal error")
            raise
        return results
Ejemplo n.º 8
0
    def lint_with_text(self, request, text):
        if not text:
            return None
        prefset = getProxiedEffectivePrefs(request)
        if not prefset.getBooleanPref("lint_python_with_pychecker"):
            return
        pychecker = prefset.getStringPref("pychecker_wrapper_location")
        if not pychecker:
            return
        if sys.platform.startswith("win") and not os.path.exists(pychecker):
            if os.path.exists(pychecker + ".bat"):
                pychecker = pychecker + ".bat"
            elif os.path.exists(pychecker + ".exe"):
                pychecker = pychecker + ".exe"
        if not os.path.exists(pychecker):
            return
        tmpfilename = tempfile.mktemp() + '.py'
        fout = open(tmpfilename, 'wb')
        fout.write(text)
        fout.close()
        textlines = text.splitlines()
        cwd = request.cwd
        env = self._get_fixed_env(prefset)
        rcfilePath = prefset.getStringPref("pychecker_checking_rcfile")
        if rcfilePath and os.path.exists(rcfilePath):
            if self.nonIdentChar_RE.search(rcfilePath):
                rcfilePath = '"' + rcfilePath + '"'
            extraArgs = [ "--config=" + rcfilePath ]
        else:
            extraArgs = []
            
        cmd = [pychecker, "--keepgoing", "--only"] + extraArgs + [tmpfilename]
        cwd = request.cwd or None
        # We only need the stdout result.
        try:
            p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None)
            stdout, stderr = p.communicate()
            warnLines = stdout.splitlines(0) # Don't need the newlines.
            errorLines = stderr.splitlines(0)
        finally:
            os.unlink(tmpfilename)
        # Check raw output for an exception
        results = koLintResults()
        re_escaped_filename = re.escape(tmpfilename)
        exception_ptn = re.compile('''Caught exception importing module.+?File "%s", line (\d+), in <module>.+?\s*(\w+(?:Error|Exception):\s+.*)''' % re_escaped_filename, re.DOTALL)
        m = exception_ptn.search(stderr)
        if m:
            lineNo = int(m.group(1))
            desc = m.group(2)
            koLintResult.createAddResult(results, textlines, koLintResult.SEV_ERROR, lineNo, desc)

        warn_ptn = re.compile(r'^%s:(\d+):\s+(.+)' % re_escaped_filename)
        error_ptn = re.compile(r'(.*[Ee]rror:.*?)\s*\(%s,\s+line\s+(\d+)\)'
                               % re_escaped_filename)
        for line in warnLines:
            m = warn_ptn.match(line)
            if m:
                lineNo = int(m.group(1))
                desc = m.group(2)
                koLintResult.createAddResult(results, textlines, koLintResult.SEV_WARNING, lineNo,
                           "pychecker: " + desc)
        for line in errorLines:
            m = error_ptn.match(line)
            if m:
                lineNo = int(m.group(2))
                desc = m.group(1)
                koLintResult.createAddResult(results, textlines, koLintResult.SEV_ERROR, lineNo,
                           "pychecker: " + desc)
        return results
Ejemplo n.º 9
0
    def lint_with_text(self, request, text):
        if not text:
            return None
        prefset = getProxiedEffectivePrefs(request)
        if not prefset.getBooleanPref("lint_python_with_pylint"):
            return
        # if not prefset.getBooleanPref("lintWithPylint"): return
        pythonExe = self._pythonInfo.getExecutableFromDocument(request.koDoc)
        if not pythonExe:
            return
        tmpfilename = tempfile.mktemp() + '.py'
        fout = open(tmpfilename, 'wb')
        fout.write(text)
        fout.close()
        textlines = text.splitlines()
        cwd = request.cwd
        env = self._get_fixed_env(prefset)
        rcfilePath = prefset.getStringPref("pylint_checking_rcfile")
        if rcfilePath and os.path.exists(rcfilePath):
            if self.nonIdentChar_RE.search(rcfilePath):
                rcfilePath = '"' + rcfilePath + '"'
            extraArgs = [ "--rcfile=" + rcfilePath ]
        else:
            # Hardwire in these three messages:
            extraArgs = []# [ "-d", "C0103", "-d" , "C0111", "-d", "F0401"]
        preferredLineWidth = prefset.getLongPref("editAutoWrapColumn")
        if preferredLineWidth > 0:
            extraArgs.append("--max-line-length=%d" % preferredLineWidth)

        baseArgs = [pythonExe, '-c', 'import sys; from pylint.lint import Run; Run(sys.argv[1:])']
        cmd = baseArgs + ["-f", "text", "-r", "n", "-i", "y"] + extraArgs
        # Put config file entry here: .rcfile=<file>
        cmd.append(tmpfilename)
        cwd = request.cwd or None
        # We only need the stdout result.
        try:
            p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None)
            stdout, _ = p.communicate()
            warnLines = stdout.splitlines(0) # Don't need the newlines.
        except:
            log.exception("Failed to run %s", cmd)
            stdout = ""
            warnLines = []
        finally:
            os.unlink(tmpfilename)
        ptn = re.compile(r'^([A-Z])(\d+):\s*(\d+)(?:,\d+)?:\s*(.*)')
        results = koLintResults()
        for line in warnLines:
            m = ptn.match(line)
            if m:
                status = m.group(1)
                statusCode = m.group(2)
                lineNo = int(m.group(3))
                desc = "pylint: %s%s %s" % (status, statusCode,
                                                          m.group(4))
                if status in ("E", "F"):
                    severity = koLintResult.SEV_ERROR
                elif status in ("C", "R", "W"):
                    severity = koLintResult.SEV_WARNING
                else:
                    #log.debug("Skip %s", line)
                    continue
                koLintResult.createAddResult(results, textlines, severity, lineNo, desc)
        return results
Ejemplo n.º 10
0
    def lint_with_text(self, request, text):
        """Lint the given Tcl content.
        
        Raise an exception if there is a problem.
        """
        if gHaveGetProxiedEffectivePrefs:
            prefset = getProxiedEffectivePrefs(request)
        else:
            # Komodo 8 sets the prefet on the request.
            prefset = request.prefset
        argv = self._getLinterArgv(prefset)
        env = koprocessutils.getUserEnv()

        # if there is no setting for the dev kit environment, use
        # the shared directory for it.  This enables site wide
        # use of *.pdx and *.pcx files for debugging

        if "TCLDEVKIT_LOCAL" not in env:
            koDirs = components.classes["@activestate.com/koDirs;1"].\
                getService(components.interfaces.koIDirs)
            sharedDir = os.path.join(koDirs.commonDataDir, "tcl")
            env["TCLDEVKIT_LOCAL"] = sharedDir

        if prefset.hasPref("tclExtraPaths"):
            tclExtraPaths = prefset.getStringPref("tclExtraPaths")
            # If TCLLIBPATH is set, then it must contain a valid Tcl
            # list giving directories to search during auto-load
            # operations. Directories must be specified in Tcl format,
            # using "/" as the path separator, regardless of platform.
            # This variable is only used when initializing the
            # auto_path variable.  Also escape spaces in paths.
            tclExtraPaths = tclExtraPaths.replace('\\', '/')
            tclExtraPaths = tclExtraPaths.replace(' ', '\ ')
            TCLLIBPATH = ' '.join(tclExtraPaths.split(os.pathsep))
            env["TCLLIBPATH"] = TCLLIBPATH

        cwd = request.cwd or None
        print 'argv: %r' % (argv, )
        p = process.ProcessOpen(argv, cwd=cwd, env=env)
        lOutput, lErrOut = p.communicate(text)
        lOutput = lOutput.splitlines(1)
        #print '======'
        #print lOutput
        #print '======'
        #print lErrOut
        #print '<<<<<<'

        if not lOutput and lErrOut:
            raise ServerException(nsError.NS_ERROR_UNEXPECTED, lErrOut)
        
        if not lOutput:
            # this should never happen unless the tcl linter is broken, or
            # not executable on linux.
            raise ServerException(nsError.NS_ERROR_UNEXPECTED,
                                  "No output from Tcl linter available")
        
        if lOutput[0].startswith("TclPro") or \
           lOutput[0].startswith("scanning"):
            # The open source TclPro has the header stripped,
            # so we need to check for both "TclPro" and "scanning"
            lInput = text.split('\n')
            return self._TclPro_lint(lInput, lOutput)
        else:
            errmsg = "unrecognized lint output format:\n%s" % lOutput[0]
            raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg)
Ejemplo n.º 11
0
    def lint_with_text(self, request, text):
        prefset = getProxiedEffectivePrefs(request)
        criticLevel = prefset.getStringPref('perl_lintOption_perlCriticLevel')
        if criticLevel == 'off':
            return

        if not self._appInfoEx.isPerlCriticInstalled(False):
            # This check is necessary in case Perl::Critic and/or criticism were uninstalled
            # between Komodo sessions.  appInfoEx.isPerlCriticInstalled caches the state
            # until the pref is changed.
            return

        # Bug 82713: Since linting isn't done on the actual file, but a copy,
        # Perl-Critic will complain about legitimate package declarations.
        # Find them, and append an annotation to turn the Perl-Critic feature off.
        # This will also tag comments, strings, and POD, but that won't affect
        # lint results.
        # This is no longer needed with Perl-Critic 1.5, which
        # goes by the filename given in any #line directives
        perlCriticVersion = self._appInfoEx.getPerlCriticVersion()
        currFile = request.koDoc.file
        baseFileName = None
        if currFile:
            baseFileName = currFile.baseName[0:-len(currFile.ext)]
            if perlCriticVersion < 1.500:
                munger = re.compile(
                    r'''^\s*(?P<package1>package \s+ (?:[\w\d_]+::)*) 
                                         (?P<baseFileName>%s)
                                         (?P<space1>\s*;)
                                         (?P<space2>\s*)
                                         (?P<rest>(?:\#.*)?)$''' %
                    (baseFileName, ), re.MULTILINE | re.VERBOSE)
                text = munger.sub(self._insertPerlCriticFilenameMatchInhibitor,
                                  text)
        elif perlCriticVersion >= 1.500 and currFile:
            text = "#line 1 " + currFile.baseName + "\n" + text

        cwd = request.cwd or None  # convert '' to None (cwd=='' for new files)
        tmpFileName = self._writeTempFile(cwd, text)
        try:
            perlExe = self._selectPerlExe(prefset)
            lintOptions = prefset.getStringPref("perl_lintOption")
            option = '-' + lintOptions
            if perlCriticVersion <= 1.100 or not baseFileName:
                pcOption = '-Mcriticism=' + criticLevel
            else:
                pcOption = '''-Mcriticism (-severity => '%s', 'as-filename' => '%s')''' % (
                    criticLevel, baseFileName)
            perlExtraPaths = prefset.getStringPref("perlExtraPaths")
            if perlExtraPaths:
                if sys.platform.startswith("win"):
                    perlExtraPaths = perlExtraPaths.replace('\\', '/')
                perlExtraPaths = [
                    x for x in perlExtraPaths.split(os.pathsep) if x.strip()
                ]
            argv = [perlExe]
            for incpath in perlExtraPaths:
                argv += ['-I', incpath]
            if 'T' in lintOptions and prefset.getBooleanPref(
                    "perl_lintOption_includeCurrentDirForLinter"):
                argv += ['-I', '.']

            # bug 27963: Fix instances of <<use PerlTray>> from code
            # to make them innocuous for the syntax checker.
            # 'use PerlTray' in comments or strings will trigger a false positive
            if sys.platform.startswith(
                    "win") and self._use_perltray_module.search(text):
                argv += ['-I', self._perlTrayDir]

            argv.append(option)
            argv.append(pcOption)
            argv.append(tmpFileName)
            env = koprocessutils.getUserEnv()
            # We only need stderr output.

            p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None)
            _, stderr = p.communicate()
            lintResults = PerlWarnsToLintResults(stderr.splitlines(1),
                                                 tmpFileName,
                                                 request.koDoc.displayPath,
                                                 text)
        finally:
            os.unlink(tmpFileName)

        return lintResults
Ejemplo n.º 12
0
 def __init__(self, request, scope):
     self.prefset = getProxiedEffectivePrefs(request)
     self.scope = scope