Beispiel #1
0
 def testAnalyzeFile(self):
     path = os.path.abspath('File.py')
     source = dedent("""\
         CONSTANT = 1
     """)
     expectedDict = ModuleDict()
     expectedDict.enterModule('File')
     expectedDict.addProperty(None, 'CONSTANT')
     outDict = analyzeFile(path, getSafeTree(source, 1))
     self.assertEquals(outDict, expectedDict, '%r != %r' % (outDict._modules, expectedDict._modules))
Beispiel #2
0
 def testAnalyzeFile(self):
     path = os.path.abspath('File.py')
     source = dedent("""\
         CONSTANT = 1
     """)
     expectedDict = ModuleDict()
     expectedDict.enterModule('File')
     expectedDict.addProperty(None, 'CONSTANT')
     outDict = analyzeFile(path, getSafeTree(source, 1))
     self.assertEqual(outDict, expectedDict, '%r != %r' % (outDict._modules, expectedDict._modules))
Beispiel #3
0
def detectCompletionType(fullPath, origSource, lineNo, origCol, base, PYSMELLDICT, update=True):
    """
    Return a CompletionOptions instance describing the type of the completion, along with extra parameters.
    
    args: fullPath -> The full path and filename of the file that is edited
          origSource -> The source of the edited file (it's probably not saved)
          lineNo -> The line number the cursor is in, 1-based
          origCol -> The column number the cursor is in, 0-based
          base -> The string that will be replaced when the completion is inserted
          PYSMELLDICT -> The loaded PYSMELLDICT

    Note that Vim deletes the "base" when a completion is requested so extra trickery must be performed to get it from the source.

    """
    AST = getSafeTree(origSource, lineNo)
    if update:
        currentDict = analyzeFile(fullPath, AST)
        if currentDict is not None:
            updatePySmellDict(PYSMELLDICT, currentDict)
    origLineText = origSource.splitlines()[lineNo - 1] # lineNo is 1 based
    leftSide, rightSide = origLineText[:origCol], origLineText[origCol:]
    leftSideStripped = leftSide.lstrip()

    isImportCompletion = (leftSideStripped.startswith("from ") or leftSideStripped.startswith("import "))
    if isImportCompletion:
        module = leftSideStripped.split(" ")[1]
        if "." in module and " import " not in leftSideStripped:
            module, _ = module.rsplit(".", 1)
        showMembers = False
        if " import " in leftSide:
            showMembers = True
        return CompletionOptions(Types.MODULE, module=module, showMembers=showMembers)

    isAttrLookup = "." in leftSide and not isImportCompletion
    isArgCompletion = base.endswith('(') and leftSide.endswith(base)

    if isArgCompletion:
        rindex = None
        if rightSide.startswith(')'):
            rindex = -1
        funcName = None
        lindex = leftSide.rfind('.') + 1 #rfind will return -1, so with +1 it will be zero
        funcName = leftSide[lindex:-1].lstrip()
        if isAttrLookup:
            return CompletionOptions(Types.METHOD, parents=[], klass=None, name=funcName, rindex=rindex)
        else:
            return CompletionOptions(Types.FUNCTION, name=funcName, rindex=rindex)

    if isAttrLookup and AST is not None:
        var = leftSideStripped[:leftSideStripped.rindex('.')]
        isClassLookup = var == 'self'
        if isClassLookup:
            klass, parents = inferClass(fullPath, AST, lineNo, PYSMELLDICT)
            return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)
        else:
            chain = getChain(leftSideStripped)[:-1] # strip dot
            possibleModule = inferModule(chain, AST, lineNo)
            if possibleModule is not None:
                return CompletionOptions(Types.MODULE, module=possibleModule, showMembers=True)
        klass, parents = inferInstance(fullPath, AST, lineNo, var, PYSMELLDICT)
        return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)
        

    return CompletionOptions(Types.TOPLEVEL)
Beispiel #4
0
def detectCompletionType(fullPath,
                         origSource,
                         lineNo,
                         origCol,
                         base,
                         PYSMELLDICT,
                         update=True):
    """
    Return a CompletionOptions instance describing the type of the completion, along with extra parameters.
    
    args: fullPath -> The full path and filename of the file that is edited
          origSource -> The source of the edited file (it's probably not saved)
          lineNo -> The line number the cursor is in, 1-based
          origCol -> The column number the cursor is in, 0-based
          base -> The string that will be replaced when the completion is inserted
          PYSMELLDICT -> The loaded PYSMELLDICT

    Note that Vim deletes the "base" when a completion is requested so extra trickery must be performed to get it from the source.

    """
    AST = getSafeTree(origSource, lineNo)
    if update:
        currentDict = analyzeFile(fullPath, AST)
        if currentDict is not None:
            updatePySmellDict(PYSMELLDICT, currentDict)
    origLineText = origSource.splitlines()[lineNo - 1]  # lineNo is 1 based
    leftSide, rightSide = origLineText[:origCol], origLineText[origCol:]
    leftSideStripped = leftSide.lstrip()

    isImportCompletion = (leftSideStripped.startswith("from ")
                          or leftSideStripped.startswith("import "))
    if isImportCompletion:
        module = leftSideStripped.split(" ")[1]
        if "." in module and " import " not in leftSideStripped:
            module, _ = module.rsplit(".", 1)
        showMembers = False
        if " import " in leftSide:
            showMembers = True
        return CompletionOptions(Types.MODULE,
                                 module=module,
                                 showMembers=showMembers)

    isAttrLookup = "." in leftSide and not isImportCompletion
    isArgCompletion = base.endswith('(') and leftSide.endswith(base)

    if isArgCompletion:
        rindex = None
        if rightSide.startswith(')'):
            rindex = -1
        funcName = None
        lindex = leftSide.rfind(
            '.') + 1  #rfind will return -1, so with +1 it will be zero
        funcName = leftSide[lindex:-1].lstrip()
        if isAttrLookup:
            return CompletionOptions(Types.METHOD,
                                     parents=[],
                                     klass=None,
                                     name=funcName,
                                     rindex=rindex)
        else:
            return CompletionOptions(Types.FUNCTION,
                                     name=funcName,
                                     rindex=rindex)

    if isAttrLookup and AST is not None:
        var = leftSideStripped[:leftSideStripped.rindex('.')]
        isClassLookup = var == 'self'
        if isClassLookup:
            klass, parents = inferClass(fullPath, AST, lineNo, PYSMELLDICT)
            return CompletionOptions(Types.INSTANCE,
                                     klass=klass,
                                     parents=parents)
        else:
            chain = getChain(leftSideStripped)  # strip dot
            if base and chain.endswith(base):
                chain = chain[:-len(base)]
            if chain.endswith('.'):
                chain = chain[:-1]
            possibleModule = inferModule(chain, AST, lineNo)
            if possibleModule is not None:
                return CompletionOptions(Types.MODULE,
                                         module=possibleModule,
                                         showMembers=True)
        klass, parents = inferInstance(fullPath, AST, lineNo, var, PYSMELLDICT)
        return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)

    return CompletionOptions(Types.TOPLEVEL)