| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.jetbrains.python.codeInsight.stdlib; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFileSystemItem; |
| import com.intellij.psi.PsiNamedElement; |
| import com.jetbrains.python.PyNames; |
| import com.jetbrains.python.documentation.PythonDocumentationLinkProvider; |
| import com.jetbrains.python.documentation.PythonDocumentationProvider; |
| import com.jetbrains.python.psi.PyClass; |
| import com.jetbrains.python.psi.PyFile; |
| import com.jetbrains.python.psi.PyFunction; |
| import com.jetbrains.python.psi.impl.PyBuiltinCache; |
| import com.intellij.psi.util.QualifiedName; |
| import com.jetbrains.python.psi.resolve.QualifiedNameFinder; |
| import com.jetbrains.python.sdk.PythonSdkType; |
| |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class PyStdlibDocumentationLinkProvider implements PythonDocumentationLinkProvider { |
| // use tools/stdlib-modindex.py to regenerate the map when new Python versions are released |
| private static List<String> py2LibraryModules = ImmutableList.of( |
| "abc", |
| "aepack", |
| "aetools", |
| "aetypes", |
| "aifc", |
| "al", |
| "anydbm", |
| "argparse", |
| "array", |
| "asynchat", |
| "asyncore", |
| "atexit", |
| "audioop", |
| "autoGIL", |
| "base64", |
| "BaseHTTPServer", |
| "Bastion", |
| "bdb", |
| "binascii", |
| "binhex", |
| "bisect", |
| "bsddb", |
| "bz2", |
| "calendar", |
| "cd", |
| "cgi", |
| "CGIHTTPServer", |
| "cgitb", |
| "chunk", |
| "cmath", |
| "cmd", |
| "code", |
| "codecs", |
| "codeop", |
| "collections", |
| "ColorPicker", |
| "colorsys", |
| "commands", |
| "compileall", |
| "ConfigParser", |
| "contextlib", |
| "Cookie", |
| "cookielib", |
| "copy", |
| "copy_reg", |
| "crypt", |
| "csv", |
| "ctypes", |
| "curses.ascii", |
| "curses.panel", |
| "curses", |
| "datetime", |
| "dbhash", |
| "dbm", |
| "decimal", |
| "difflib", |
| "dircache", |
| "dis", |
| "distutils", |
| "dl", |
| "doctest", |
| "DocXMLRPCServer", |
| "dumbdbm", |
| "dummy_thread", |
| "dummy_threading", |
| "EasyDialogs", |
| "email.charset", |
| "email.encoders", |
| "email.errors", |
| "email.generator", |
| "email.header", |
| "email.iterators", |
| "email.message", |
| "email.mime", |
| "email.parser", |
| "email", |
| "email.utils", |
| "errno", |
| "fcntl", |
| "filecmp", |
| "fileinput", |
| "fl", |
| "fm", |
| "fnmatch", |
| "formatter", |
| "fpectl", |
| "fpformat", |
| "fractions", |
| "FrameWork", |
| "ftplib", |
| "functools", |
| "future_builtins", |
| "gc", |
| "gdbm", |
| "gensuitemodule", |
| "getopt", |
| "getpass", |
| "gettext", |
| "gl", |
| "glob", |
| "grp", |
| "gzip", |
| "hashlib", |
| "heapq", |
| "hmac", |
| "hotshot", |
| "htmllib", |
| "HTMLParser", |
| "httplib", |
| "ic", |
| "imageop", |
| "imaplib", |
| "imgfile", |
| "imghdr", |
| "imp", |
| "importlib", |
| "imputil", |
| "inspect", |
| "io", |
| "itertools", |
| "jpeg", |
| "json", |
| "keyword", |
| "linecache", |
| "locale", |
| "logging", |
| "MacOS", |
| "macostools", |
| "macpath", |
| "mailbox", |
| "mailcap", |
| "marshal", |
| "math", |
| "md5", |
| "mhlib", |
| "mimetools", |
| "mimetypes", |
| "MimeWriter", |
| "mimify", |
| "MiniAEFrame", |
| "mmap", |
| "modulefinder", |
| "msilib", |
| "msvcrt", |
| "multifile", |
| "multiprocessing", |
| "mutex", |
| "netrc", |
| "new", |
| "nis", |
| "nntplib", |
| "numbers", |
| "operator", |
| "optparse", |
| "os.path", |
| "os", |
| "ossaudiodev", |
| "parser", |
| "pickle", |
| "pickletools", |
| "pipes", |
| "pkgutil", |
| "platform", |
| "plistlib", |
| "popen2", |
| "poplib", |
| "posix", |
| "posixfile", |
| "pprint", |
| "pty", |
| "pwd", |
| "pyclbr", |
| "pydoc", |
| "xml.parsers.expat", |
| "py_compile", |
| "Queue", |
| "quopri", |
| "random", |
| "re", |
| "readline", |
| "repr", |
| "resource", |
| "rexec", |
| "rfc822", |
| "rlcompleter", |
| "robotparser", |
| "runpy", |
| "sched", |
| "ScrolledText", |
| "select", |
| "sets", |
| "sgmllib", |
| "sha", |
| "shelve", |
| "shlex", |
| "shutil", |
| "signal", |
| "SimpleHTTPServer", |
| "SimpleXMLRPCServer", |
| "site", |
| "smtpd", |
| "smtplib", |
| "sndhdr", |
| "socket", |
| "SocketServer", |
| "spwd", |
| "sqlite3", |
| "ssl", |
| "stat", |
| "statvfs", |
| "string", |
| "StringIO", |
| "stringprep", |
| "struct", |
| "subprocess", |
| "sunau", |
| "sunaudiodev", |
| "symbol", |
| "symtable", |
| "sys", |
| "sysconfig", |
| "syslog", |
| "tabnanny", |
| "telnetlib", |
| "tempfile", |
| "termios", |
| "test", |
| "textwrap", |
| "thread", |
| "threading", |
| "time", |
| "timeit", |
| "Tix", |
| "Tkinter", |
| "token", |
| "tokenize", |
| "trace", |
| "traceback", |
| "ttk", |
| "tty", |
| "types", |
| "unicodedata", |
| "unittest", |
| "urllib", |
| "urllib2", |
| "urlparse", |
| "user", |
| "UserDict", |
| "uu", |
| "uuid", |
| "warnings", |
| "wave", |
| "weakref", |
| "webbrowser", |
| "whichdb", |
| "winsound", |
| "wsgiref", |
| "xdrlib", |
| "xml.dom.minidom", |
| "xml.dom.pulldom", |
| "xml.dom", |
| "xml.etree.ElementTree", |
| "xml.sax.handler", |
| "xml.sax.xmlreader", |
| "xml.sax", |
| "xml.sax.saxutils", |
| "xmllib", |
| "xmlrpclib", |
| "zipfile", |
| "zipimport", |
| "zlib", |
| "_winreg", |
| "__builtin__", |
| "__future__" |
| ); |
| |
| private static List<String> py3LibraryModules = ImmutableList.of( |
| "abc", |
| "aifc", |
| "argparse", |
| "array", |
| "ast", |
| "asynchat", |
| "asyncore", |
| "atexit", |
| "audioop", |
| "base64", |
| "bdb", |
| "binascii", |
| "binhex", |
| "bisect", |
| "builtins", |
| "bz2", |
| "calendar", |
| "cgi", |
| "cgitb", |
| "chunk", |
| "cmath", |
| "cmd", |
| "code", |
| "codecs", |
| "codeop", |
| "collections", |
| "colorsys", |
| "compileall", |
| "concurrent.futures", |
| "configparser", |
| "contextlib", |
| "copy", |
| "copyreg", |
| "crypt", |
| "csv", |
| "ctypes", |
| "curses.ascii", |
| "curses.panel", |
| "curses", |
| "datetime", |
| "dbm", |
| "decimal", |
| "difflib", |
| "dis", |
| "distutils", |
| "doctest", |
| "dummy_threading", |
| "email.charset", |
| "email.encoders", |
| "email.errors", |
| "email.generator", |
| "email.header", |
| "email.iterators", |
| "email.message", |
| "email.mime", |
| "email.parser", |
| "email", |
| "email.utils", |
| "errno", |
| "fcntl", |
| "filecmp", |
| "fileinput", |
| "fnmatch", |
| "formatter", |
| "fpectl", |
| "fractions", |
| "ftplib", |
| "functools", |
| "gc", |
| "getopt", |
| "getpass", |
| "gettext", |
| "glob", |
| "grp", |
| "gzip", |
| "hashlib", |
| "heapq", |
| "hmac", |
| "html.entities", |
| "html.parser", |
| "html", |
| "http.client", |
| "http.cookiejar", |
| "http.cookies", |
| "http.server", |
| "imaplib", |
| "imghdr", |
| "imp", |
| "importlib", |
| "inspect", |
| "io", |
| "itertools", |
| "json", |
| "keyword", |
| "linecache", |
| "locale", |
| "logging.config", |
| "logging.handlers", |
| "logging", |
| "macpath", |
| "mailbox", |
| "mailcap", |
| "marshal", |
| "math", |
| "mimetypes", |
| "mmap", |
| "modulefinder", |
| "msilib", |
| "msvcrt", |
| "multiprocessing", |
| "netrc", |
| "nis", |
| "nntplib", |
| "numbers", |
| "operator", |
| "optparse", |
| "os.path", |
| "os", |
| "ossaudiodev", |
| "parser", |
| "pickle", |
| "pickletools", |
| "pipes", |
| "pkgutil", |
| "platform", |
| "plistlib", |
| "poplib", |
| "posix", |
| "pprint", |
| "pty", |
| "pwd", |
| "pyclbr", |
| "pydoc", |
| "xml.parsers.expat", |
| "py_compile", |
| "queue", |
| "quopri", |
| "random", |
| "re", |
| "readline", |
| "reprlib", |
| "resource", |
| "rlcompleter", |
| "runpy", |
| "sched", |
| "select", |
| "shelve", |
| "shlex", |
| "shutil", |
| "signal", |
| "site", |
| "smtpd", |
| "smtplib", |
| "sndhdr", |
| "socket", |
| "socketserver", |
| "spwd", |
| "sqlite3", |
| "ssl", |
| "stat", |
| "string", |
| "stringprep", |
| "struct", |
| "subprocess", |
| "sunau", |
| "symbol", |
| "symtable", |
| "sys", |
| "sysconfig", |
| "syslog", |
| "tabnanny", |
| "tarfile", |
| "telnetlib", |
| "tempfile", |
| "termios", |
| "test", |
| "textwrap", |
| "threading", |
| "time", |
| "timeit", |
| "tkinter", |
| "tkinter.scrolledtext", |
| "tkinter.tix", |
| "tkinter.ttk", |
| "token", |
| "tokenize", |
| "trace", |
| "traceback", |
| "tty", |
| "types", |
| "unicodedata", |
| "unittest", |
| "urllib.error", |
| "urllib.parse", |
| "urllib.request", |
| "urllib.robotparser", |
| "uu", |
| "uuid", |
| "warnings", |
| "wave", |
| "weakref", |
| "webbrowser", |
| "winreg", |
| "winsound", |
| "wsgiref", |
| "xdrlib", |
| "xml.dom.minidom", |
| "xml.dom.pulldom", |
| "xml.dom", |
| "xml.etree.ElementTree", |
| "xml.sax.handler", |
| "xml.sax.xmlreader", |
| "xml.sax", |
| "xml.sax.saxutils", |
| "xmlrpc.client", |
| "xmlrpc.server", |
| "zipfile", |
| "zipimport", |
| "zlib", |
| "_dummy_thread", |
| "_thread", |
| "__future__" |
| ); |
| |
| @Override |
| public String getExternalDocumentationUrl(PsiElement element, PsiElement originalElement) { |
| PsiFileSystemItem file = element instanceof PsiFileSystemItem ? (PsiFileSystemItem) element : element.getContainingFile(); |
| if (PyNames.INIT_DOT_PY.equals(file.getName())) { |
| file = file.getParent(); |
| assert file != null; |
| } |
| Sdk sdk = PyBuiltinCache.findSdkForFile(file); |
| VirtualFile vFile = file.getVirtualFile(); |
| if (vFile != null && sdk != null && PythonSdkType.isStdLib(vFile, sdk)) { |
| QualifiedName qName = QualifiedNameFinder.findCanonicalImportPath(element, originalElement); |
| return getStdlibUrlFor(element, qName, sdk); |
| } |
| return null; |
| } |
| |
| @Override |
| public String getExternalDocumentationRoot(Sdk sdk) { |
| final String versionString = sdk.getVersionString(); |
| if (versionString != null && StringUtil.startsWithIgnoreCase(versionString, "jython")) { |
| return "http://jython.org/docs/library/"; |
| } |
| final String pyVersion = PythonDocumentationProvider.pyVersion(versionString); |
| StringBuilder urlBuilder = new StringBuilder("http://docs.python.org/"); |
| if (pyVersion != null) { |
| urlBuilder.append(pyVersion).append("/"); |
| } |
| if (pyVersion != null && (pyVersion.startsWith("2.4") || pyVersion.startsWith("2.5"))) { |
| urlBuilder.append("lib/"); |
| } |
| else { |
| urlBuilder.append("library/"); |
| } |
| return urlBuilder.toString(); |
| } |
| |
| private String getStdlibUrlFor(PsiElement element, QualifiedName moduleName, Sdk sdk) { |
| StringBuilder urlBuilder = new StringBuilder(getExternalDocumentationRoot(sdk)); |
| String qnameString = moduleName.toString(); |
| if (qnameString.equals("ntpath") || qnameString.equals("posixpath")) { |
| qnameString = "os.path"; |
| } |
| else if (qnameString.equals("nt")) { |
| qnameString = "os"; |
| } |
| else if (qnameString.equals("cPickle")) { |
| qnameString = "pickle"; |
| } |
| else if (qnameString.equals("pyexpat")) { |
| qnameString = "xml.parsers.expat"; |
| } |
| |
| final String pyVersion = PythonDocumentationProvider.pyVersion(sdk.getVersionString()); |
| List<String> modules = pyVersion != null && pyVersion.startsWith("3") ? py3LibraryModules : py2LibraryModules; |
| boolean foundModule = false; |
| for (String module : modules) { |
| if (qnameString.startsWith(module)) { |
| urlBuilder.append(module.toLowerCase()); |
| urlBuilder.append(".html"); |
| foundModule = true; |
| break; |
| } |
| } |
| if (foundModule && element instanceof PsiNamedElement && !(element instanceof PyFile)) { |
| urlBuilder.append('#').append(moduleName).append("."); |
| if (element instanceof PyFunction) { |
| final PyClass containingClass = ((PyFunction)element).getContainingClass(); |
| if (containingClass != null) { |
| urlBuilder.append(containingClass.getName()).append('.'); |
| } |
| } |
| urlBuilder.append(((PsiNamedElement)element).getName()); |
| } |
| return urlBuilder.toString(); |
| } |
| |
| } |