Search in sources :

Example 1 with IMessage

use of org.python.pydev.ast.analysis.messages.IMessage in project Pydev by fabioz.

the class AnalysisBuilderRunnable method doAnalysis.

@Override
protected void doAnalysis() {
    if (!nature.startRequests()) {
        return;
    }
    try {
        if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
            org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "doAnalysis() - " + moduleName + " " + this.getAnalysisCauseStr());
        }
        // if the resource is not open, there's not much we can do...
        final IResource r = resource;
        if (r == null) {
            org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Finished analysis -- resource null -- " + moduleName);
            return;
        }
        if (!r.getProject().isOpen()) {
            org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Finished analysis -- project closed -- " + moduleName);
            return;
        }
        AnalysisRunner runner = new AnalysisRunner();
        checkStop();
        IAnalysisPreferences analysisPreferences = new AnalysisPreferences(r);
        boolean makeAnalysis = // just get problems in resources that are in the pythonpath
        runner.canDoAnalysis(document) && PyDevBuilderVisitor.isInPythonPath(r) && analysisPreferences.makeCodeAnalysis();
        boolean anotherVisitorRequiresAnalysis = false;
        for (IExternalCodeAnalysisVisitor visitor : allVisitors) {
            anotherVisitorRequiresAnalysis |= visitor.getRequiresAnalysis();
        }
        if (!makeAnalysis) {
            // let's see if we should do code analysis
            if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
                org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Skipping: !makeAnalysis -- " + moduleName);
            }
            if (!anotherVisitorRequiresAnalysis) {
                AnalysisRunner.deleteMarkers(r);
                return;
            } else {
                // Only delete pydev markers (others will be deleted by the respective visitors later on).
                boolean onlyPydevAnalysisMarkers = true;
                AnalysisRunner.deleteMarkers(r, onlyPydevAnalysisMarkers);
            }
        }
        if (makeAnalysis && onlyRecreateCtxInsensitiveInfo) {
            if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
                org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Skipping: !forceAnalysis && analysisCause == ANALYSIS_CAUSE_BUILDER && " + "PyDevBuilderPrefPage.getAnalyzeOnlyActiveEditor() -- " + moduleName);
            }
            return;
        }
        if (nature == null) {
            Log.log("Finished analysis: null nature -- " + moduleName);
            return;
        }
        AbstractAdditionalTokensInfo info = AdditionalProjectInterpreterInfo.getAdditionalInfoForProject(nature);
        if (info == null) {
            Log.log("Unable to get additional info for: " + r + " -- " + moduleName);
            return;
        }
        if (makeAnalysis && DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
            org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "makeAnalysis:" + makeAnalysis + " " + "analysisCause: " + getAnalysisCauseStr() + " -- " + moduleName);
        }
        checkStop();
        if (isHierarchicallyDerived(r)) {
            if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
                org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Resource marked as derived not analyzed: " + r + " -- " + moduleName);
            }
            // might be already there)
            if (r != null) {
                AnalysisRunner.deleteMarkers(r);
            }
            return;
        }
        // Maybe we can improve that when https://github.com/PyCQA/pylint/pull/1189 is done.
        if (!DocumentChanged.hasDocumentChanged(resource, document)) {
            for (IExternalCodeAnalysisVisitor visitor : allVisitors) {
                visitor.startVisit();
            }
        } else {
            for (IExternalCodeAnalysisVisitor visitor : allVisitors) {
                visitor.deleteMarkers();
            }
            if (!makeAnalysis) {
                return;
            }
        }
        List<MarkerInfo> markersFromCodeAnalysis = null;
        if (makeAnalysis) {
            OccurrencesAnalyzer analyzer = new OccurrencesAnalyzer();
            checkStop();
            SourceModule module = (SourceModule) this.module.call(moduleRequest);
            IMessage[] messages = analyzer.analyzeDocument(nature, module, analysisPreferences, document, this.internalCancelMonitor, DefaultIndentPrefs.get(this.resource));
            checkStop();
            if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
                org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Adding markers for module: " + moduleName);
            // for (IMessage message : messages) {
            // Log.toLogFile(this, message.toString());
            // }
            }
            // last chance to stop...
            checkStop();
            // don't stop after setting to add / remove the markers
            if (r != null) {
                boolean analyzeOnlyActiveEditor = PyDevBuilderPreferences.getAnalyzeOnlyActiveEditor();
                if (forceAnalysis || !analyzeOnlyActiveEditor || (analyzeOnlyActiveEditor && (!PyDevBuilderPreferences.getRemoveErrorsWhenEditorIsClosed() || OpenEditors.isEditorOpenForResource(r)))) {
                    markersFromCodeAnalysis = runner.setMarkers(r, document, messages, this.internalCancelMonitor);
                } else {
                    if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
                        org.python.pydev.shared_core.log.ToLogFile.toLogFile(this, "Skipped adding markers for module: " + moduleName + " (editor not opened).");
                    }
                }
            }
        }
        // if there are callbacks registered, call them if we still didn't return (mostly for tests)
        for (ICallback<Object, IResource> callback : analysisBuilderListeners) {
            try {
                callback.call(r);
            } catch (Exception e) {
                Log.log(e);
            }
        }
        checkStop();
        for (IExternalCodeAnalysisVisitor visitor : allVisitors) {
            visitor.join();
        }
        checkStop();
        if (r != null) {
            for (IExternalCodeAnalysisVisitor visitor : allVisitors) {
                String problemMarker = visitor.getProblemMarkerId();
                String messageId = visitor.getMessageId();
                List<MarkerInfo> markersFromVisitor = visitor.getMarkers(resource);
                if (markersFromVisitor != null && markersFromVisitor.size() > 0) {
                    Map<Integer, List<MarkerInfo>> lineToMarkerInfo = new HashMap<>();
                    if (markersFromCodeAnalysis != null) {
                        for (MarkerInfo codeAnalysisMarkerInfo : markersFromCodeAnalysis) {
                            List<MarkerInfo> list = lineToMarkerInfo.get(codeAnalysisMarkerInfo.lineStart);
                            if (list == null) {
                                list = new ArrayList<>(2);
                                lineToMarkerInfo.put(codeAnalysisMarkerInfo.lineStart, list);
                            }
                            list.add(codeAnalysisMarkerInfo);
                        }
                    }
                    if (visitor == pyLintVisitor) {
                        // (there's no real point in putting an error twice).
                        for (Iterator<MarkerInfo> visitorMarkerInfoIterator = markersFromVisitor.iterator(); visitorMarkerInfoIterator.hasNext(); ) {
                            MarkerInfo visitorMarkerInfo = visitorMarkerInfoIterator.next();
                            List<MarkerInfo> codeAnalysisMarkers = lineToMarkerInfo.get(visitorMarkerInfo.lineStart);
                            if (codeAnalysisMarkers != null && codeAnalysisMarkers.size() > 0) {
                                for (MarkerInfo codeAnalysisMarker : codeAnalysisMarkers) {
                                    if (codeAnalysisMarker.severity < IMarker.SEVERITY_INFO) {
                                        // Don't consider if it shouldn't be shown.
                                        continue;
                                    }
                                    Map<String, Object> additionalInfo = codeAnalysisMarker.additionalInfo;
                                    if (additionalInfo != null) {
                                        Object analysisType = additionalInfo.get(AnalysisRunner.PYDEV_ANALYSIS_TYPE);
                                        if (analysisType != null && analysisType instanceof Integer) {
                                            String pyLintMessageId = CheckAnalysisErrors.getPyLintMessageIdForPyDevAnalysisType((int) analysisType);
                                            if (pyLintMessageId != null && pyLintMessageId.equals(visitorMarkerInfo.additionalInfo.get(messageId))) {
                                                visitorMarkerInfoIterator.remove();
                                                // Stop the for (we've already removed it).
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    PyMarkerUtils.replaceMarkers(markersFromVisitor, resource, problemMarker, true, this.internalCancelMonitor);
                } else {
                    visitor.deleteMarkers();
                }
            }
        }
    } catch (OperationCanceledException e) {
        // ok, ignore it
        logOperationCancelled();
    } catch (Exception e) {
        Log.log(e);
    } finally {
        try {
            nature.endRequests();
        } catch (Throwable e) {
            Log.log("Error when analyzing: " + moduleName, e);
        }
        try {
            AnalysisBuilderRunnableFactory.removeFromThreads(key, this);
        } catch (Throwable e) {
            Log.log(e);
        }
        dispose();
    }
}
Also used : HashMap(java.util.HashMap) OperationCanceledException(org.eclipse.core.runtime.OperationCanceledException) IAnalysisPreferences(org.python.pydev.ast.analysis.IAnalysisPreferences) ArrayList(java.util.ArrayList) List(java.util.List) MarkerInfo(org.python.pydev.shared_core.markers.PyMarkerUtils.MarkerInfo) SourceModule(org.python.pydev.ast.codecompletion.revisited.modules.SourceModule) AnalysisPreferences(com.python.pydev.analysis.AnalysisPreferences) IAnalysisPreferences(org.python.pydev.ast.analysis.IAnalysisPreferences) OccurrencesAnalyzer(com.python.pydev.analysis.OccurrencesAnalyzer) IMessage(org.python.pydev.ast.analysis.messages.IMessage) CoreException(org.eclipse.core.runtime.CoreException) OperationCanceledException(org.eclipse.core.runtime.OperationCanceledException) MisconfigurationException(org.python.pydev.core.MisconfigurationException) AbstractAdditionalTokensInfo(com.python.pydev.analysis.additionalinfo.AbstractAdditionalTokensInfo) IResource(org.eclipse.core.resources.IResource) IExternalCodeAnalysisVisitor(com.python.pydev.analysis.external.IExternalCodeAnalysisVisitor)

Example 2 with IMessage

use of org.python.pydev.ast.analysis.messages.IMessage in project Pydev by fabioz.

the class TabNanny method analyzeDoc.

/**
 * Analyze the doc for mixed tabs and indents with the wrong number of chars.
 * @param monitor
 *
 * @return a list with the error messages to be shown to the user.
 */
public static List<IMessage> analyzeDoc(IDocument doc, IAnalysisPreferences analysisPrefs, String moduleName, IIndentPrefs indentPrefs, IProgressMonitor monitor) {
    ArrayList<IMessage> ret = new ArrayList<IMessage>();
    // don't even try to gather indentation errors if they should be ignored.
    if (analysisPrefs.getSeverityForType(IAnalysisPreferences.TYPE_INDENTATION_PROBLEM) < IMarker.SEVERITY_INFO) {
        return ret;
    }
    List<IndentInfo> foundTabs = new ArrayList<IndentInfo>();
    List<IndentInfo> foundSpaces = new ArrayList<IndentInfo>();
    TabNannyDocIterator it;
    try {
        it = new TabNannyDocIterator(doc);
    } catch (BadLocationException e) {
        return ret;
    }
    while (it.hasNext()) {
        IndentInfo indentation;
        try {
            indentation = it.next();
        } catch (BadLocationException e) {
            return ret;
        }
        // it can actually be in both (if we have spaces and tabs in the same indent line).
        if (indentation.indent.indexOf('\t') != -1) {
            foundTabs.add(indentation);
        }
        if (indentation.indent.indexOf(' ') != -1) {
            foundSpaces.add(indentation);
        }
        if (monitor.isCanceled()) {
            return ret;
        }
    }
    int spacesFoundSize = foundSpaces.size();
    int tabsFoundSize = foundTabs.size();
    if (spacesFoundSize == 0 && tabsFoundSize == 0) {
        // nothing to do here... (no indents available)
        return ret;
    }
    // let's discover whether we should mark the tabs found as errors or the spaces found...
    boolean markTabsAsError;
    // if we found the same number of indents for tabs and spaces, let's use the user-prefs to decide what to do
    if (spacesFoundSize == tabsFoundSize) {
        // ok, we have both, spaces and tabs... let's see what the user actually wants
        markTabsAsError = indentPrefs.getUseSpaces(false);
    } else if (tabsFoundSize > spacesFoundSize) {
        // let's see what appears more in the file (and mark the other as error).
        markTabsAsError = false;
    } else {
        markTabsAsError = true;
    }
    List<IndentInfo> errorsAre;
    List<IndentInfo> validsAre;
    String errorMsg;
    char errorChar;
    if (markTabsAsError) {
        validsAre = foundSpaces;
        errorsAre = foundTabs;
        errorMsg = "Mixed Indentation: Tab found";
        errorChar = '\t';
        createBadIndentForSpacesMessages(doc, analysisPrefs, indentPrefs, ret, validsAre, monitor);
    } else {
        validsAre = foundTabs;
        errorsAre = foundSpaces;
        errorMsg = "Mixed Indentation: Spaces found";
        errorChar = ' ';
    }
    createMixedErrorMessages(doc, analysisPrefs, ret, errorsAre, errorMsg, errorChar, monitor);
    return ret;
}
Also used : IndentInfo(org.python.pydev.core.docutils.TabNannyDocIterator.IndentInfo) TabNannyDocIterator(org.python.pydev.core.docutils.TabNannyDocIterator) IMessage(org.python.pydev.ast.analysis.messages.IMessage) ArrayList(java.util.ArrayList) BadLocationException(org.eclipse.jface.text.BadLocationException)

Example 3 with IMessage

use of org.python.pydev.ast.analysis.messages.IMessage in project Pydev by fabioz.

the class TabNanny method createBadIndentForSpacesMessages.

/**
 * Creates the errors that are related to a bad indentation (number of space chars is not ok).
 * @param monitor
 */
private static void createBadIndentForSpacesMessages(IDocument doc, IAnalysisPreferences analysisPrefs, IIndentPrefs indentPrefs, ArrayList<IMessage> ret, List<IndentInfo> validsAre, IProgressMonitor monitor) {
    int tabWidth = indentPrefs.getTabWidth();
    // if we're analyzing the spaces, let's mark invalid indents (tabs are not searched for those because
    // a tab always marks a full indent).
    FastStringBuffer buffer = new FastStringBuffer();
    for (IndentInfo indentation : validsAre) {
        if (monitor.isCanceled()) {
            return;
        }
        if (!indentation.hasNonIndentChars) {
            // if it does not have more contents (its only whitespaces), let's keep on going!
            continue;
        }
        String indentStr = indentation.indent;
        if (indentStr.indexOf("\t") != -1) {
            // the ones that appear in tabs and spaces should not be analyzed here (they'll have their own error messages).
            continue;
        }
        int lenFound = indentStr.length();
        int extraChars = lenFound % tabWidth;
        if (extraChars != 0) {
            Integer offset = indentation.startOffset;
            int startLine = PySelection.getLineOfOffset(doc, offset) + 1;
            int startCol = 1;
            int endCol = startCol + lenFound;
            buffer.clear();
            ret.add(new Message(IAnalysisPreferences.TYPE_INDENTATION_PROBLEM, buffer.append("Bad Indentation (").append(lenFound).append(" spaces)").toString(), startLine, startLine, startCol, endCol, analysisPrefs));
        }
    }
}
Also used : FastStringBuffer(org.python.pydev.shared_core.string.FastStringBuffer) IndentInfo(org.python.pydev.core.docutils.TabNannyDocIterator.IndentInfo) Message(org.python.pydev.ast.analysis.messages.Message) IMessage(org.python.pydev.ast.analysis.messages.IMessage)

Example 4 with IMessage

use of org.python.pydev.ast.analysis.messages.IMessage in project Pydev by fabioz.

the class TabNanny method createMixedErrorMessages.

/**
 * Creates the errors that are related to the mixed indentation.
 * @param monitor
 */
private static void createMixedErrorMessages(IDocument doc, IAnalysisPreferences analysisPrefs, ArrayList<IMessage> ret, List<IndentInfo> errorsAre, String errorMsg, char errorChar, IProgressMonitor monitor) {
    for (IndentInfo indentation : errorsAre) {
        if (monitor.isCanceled()) {
            return;
        }
        Integer offset = indentation.startOffset;
        int startLine = PySelection.getLineOfOffset(doc, offset) + 1;
        IRegion region;
        try {
            region = doc.getLineInformationOfOffset(offset);
            int startCol = offset - region.getOffset() + 1;
            String indentationString = indentation.indent;
            int charIndex = indentationString.indexOf(errorChar);
            startCol += charIndex;
            // now, get the endCol
            int endCol = startCol;
            int indentationStringLen = indentationString.length();
            // endCol starts at 1, but string access starts at 0 (so <= is needed)
            while (endCol <= indentationStringLen) {
                if (indentationString.charAt(endCol - 1) == errorChar) {
                    endCol++;
                } else {
                    break;
                }
            }
            ret.add(new Message(IAnalysisPreferences.TYPE_INDENTATION_PROBLEM, errorMsg, startLine, startLine, startCol, endCol, analysisPrefs));
        } catch (BadLocationException e) {
            Log.log(e);
        }
    }
}
Also used : IndentInfo(org.python.pydev.core.docutils.TabNannyDocIterator.IndentInfo) Message(org.python.pydev.ast.analysis.messages.Message) IMessage(org.python.pydev.ast.analysis.messages.IMessage) IRegion(org.eclipse.jface.text.IRegion) BadLocationException(org.eclipse.jface.text.BadLocationException)

Example 5 with IMessage

use of org.python.pydev.ast.analysis.messages.IMessage in project Pydev by fabioz.

the class MessagesManager method getMessages.

/**
 * @return the generated messages.
 */
public List<IMessage> getMessages() {
    List<IMessage> result = new ArrayList<IMessage>();
    // let's get the messages
    for (List<IMessage> l : messages.values()) {
        if (l.size() < 1) {
            // we need at least one message
            continue;
        }
        Map<Integer, List<IMessage>> messagesByType = getMessagesByType(l);
        for (int type : messagesByType.keySet()) {
            l = messagesByType.get(type);
            // the values are guaranteed to have size at least equal to 1
            IMessage message = l.get(0);
            // messages are grouped by type, and the severity is set by type, so, this is ok...
            if (message.getSeverity() < IMarker.SEVERITY_INFO) {
                if (doIgnoreMessageIfJustInformational(message.getType())) {
                    // used anyways for other actions)
                    continue;
                }
            }
            if (l.size() == 1) {
                // don't add additional info: not being used
                // addAdditionalInfoToUnusedWildImport(message);
                addToResult(result, message);
            } else {
                // the generator token has many associated messages - the messages may have different types,
                // so, we need to get them by types
                IToken generator = message.getGenerator();
                CompositeMessage compositeMessage;
                if (generator != null) {
                    compositeMessage = new CompositeMessage(message.getType(), generator, prefs);
                } else {
                    compositeMessage = new CompositeMessage(message.getType(), message.getStartLine(document), message.getEndLine(document), message.getStartCol(document), message.getEndCol(document), prefs);
                }
                for (IMessage m : l) {
                    compositeMessage.addMessage(m);
                }
                // don't add additional info: not being used
                // addAdditionalInfoToUnusedWildImport(compositeMessage);
                addToResult(result, compositeMessage);
            }
        }
    }
    for (IMessage message : independentMessages) {
        if (message.getSeverity() < IMarker.SEVERITY_INFO) {
            if (doIgnoreMessageIfJustInformational(message.getType())) {
                // used anyways for other actions)
                continue;
            }
        // otherwise keep on and add it (needed for some actions)
        }
        addToResult(result, message);
    }
    return result;
}
Also used : CompositeMessage(org.python.pydev.ast.analysis.messages.CompositeMessage) IToken(org.python.pydev.core.IToken) IMessage(org.python.pydev.ast.analysis.messages.IMessage) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

IMessage (org.python.pydev.ast.analysis.messages.IMessage)46 Document (org.eclipse.jface.text.Document)34 ArrayList (java.util.ArrayList)6 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)5 Message (org.python.pydev.ast.analysis.messages.Message)5 TestIndentPrefs (org.python.pydev.core.autoedit.TestIndentPrefs)5 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 List (java.util.List)3 BadLocationException (org.eclipse.jface.text.BadLocationException)3 CompositeMessage (org.python.pydev.ast.analysis.messages.CompositeMessage)3 IndentInfo (org.python.pydev.core.docutils.TabNannyDocIterator.IndentInfo)3 OperationCanceledException (org.eclipse.core.runtime.OperationCanceledException)2 MarkerInfo (org.python.pydev.shared_core.markers.PyMarkerUtils.MarkerInfo)2 FastStringBuffer (org.python.pydev.shared_core.string.FastStringBuffer)2 AnalysisPreferences (com.python.pydev.analysis.AnalysisPreferences)1 OccurrencesAnalyzer (com.python.pydev.analysis.OccurrencesAnalyzer)1 AbstractAdditionalTokensInfo (com.python.pydev.analysis.additionalinfo.AbstractAdditionalTokensInfo)1 IExternalCodeAnalysisVisitor (com.python.pydev.analysis.external.IExternalCodeAnalysisVisitor)1 Pep8Visitor (com.python.pydev.analysis.pep8.Pep8Visitor)1