~vil/pydev/upstream

« back to all changes in this revision

Viewing changes to org.python.pydev/src/org/python/pydev/editor/codecompletion/PyCodeCompletion.java

  • Committer: Vladimír Lapáček
  • Date: 2006-08-30 18:38:44 UTC
  • Revision ID: vladimir.lapacek@gmail.com-20060830183844-f4d82c1239a7770a
Initial import of upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Created on Aug 11, 2004
 
3
 *
 
4
 * @author Fabio Zadrozny
 
5
 */
 
6
package org.python.pydev.editor.codecompletion;
 
7
 
 
8
import java.io.File;
 
9
import java.util.ArrayList;
 
10
import java.util.Arrays;
 
11
import java.util.Collection;
 
12
import java.util.HashSet;
 
13
import java.util.Iterator;
 
14
import java.util.List;
 
15
import java.util.StringTokenizer;
 
16
 
 
17
import org.eclipse.core.runtime.CoreException;
 
18
import org.eclipse.jface.text.BadLocationException;
 
19
import org.eclipse.jface.text.IDocument;
 
20
import org.eclipse.jface.text.IRegion;
 
21
import org.eclipse.jface.text.ITextViewer;
 
22
import org.eclipse.jface.text.contentassist.CompletionProposal;
 
23
import org.eclipse.jface.text.contentassist.ICompletionProposal;
 
24
import org.eclipse.swt.graphics.Image;
 
25
import org.python.pydev.core.ExtensionHelper;
 
26
import org.python.pydev.core.ICodeCompletionASTManager;
 
27
import org.python.pydev.core.ICompletionState;
 
28
import org.python.pydev.core.IModule;
 
29
import org.python.pydev.core.IPythonNature;
 
30
import org.python.pydev.core.IToken;
 
31
import org.python.pydev.core.bundle.ImageCache;
 
32
import org.python.pydev.core.docutils.DocUtils;
 
33
import org.python.pydev.editor.codecompletion.revisited.ASTManager;
 
34
import org.python.pydev.editor.codecompletion.revisited.CompletionRecursionException;
 
35
import org.python.pydev.editor.codecompletion.revisited.CompletionState;
 
36
import org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule;
 
37
import org.python.pydev.editor.codecompletion.revisited.modules.CompiledModule;
 
38
import org.python.pydev.editor.codecompletion.revisited.visitors.FindScopeVisitor;
 
39
import org.python.pydev.editor.codecompletion.revisited.visitors.Scope;
 
40
import org.python.pydev.editor.codecompletion.shell.AbstractShell;
 
41
import org.python.pydev.parser.PyParser;
 
42
import org.python.pydev.parser.jython.SimpleNode;
 
43
import org.python.pydev.parser.jython.ast.ClassDef;
 
44
import org.python.pydev.parser.jython.ast.Name;
 
45
import org.python.pydev.parser.jython.ast.NameTok;
 
46
import org.python.pydev.parser.visitors.NodeUtils;
 
47
import org.python.pydev.plugin.PydevPlugin;
 
48
import org.python.pydev.ui.UIConstants;
 
49
 
 
50
/**
 
51
 * @author Dmoore
 
52
 * @author Fabio Zadrozny
 
53
 */
 
54
public class PyCodeCompletion {
 
55
 
 
56
    /**
 
57
     * Type for unknown.
 
58
     */
 
59
    public static final int TYPE_UNKNOWN = -1;
 
60
 
 
61
    /**
 
62
     * Type for import (used to decide the icon)
 
63
     */
 
64
    public static final int TYPE_IMPORT = 0;
 
65
    
 
66
    /**
 
67
     * Type for class (used to decide the icon)
 
68
     */
 
69
    public static final int TYPE_CLASS = 1;
 
70
    
 
71
    /**
 
72
     * Type for function (used to decide the icon)
 
73
     */
 
74
    public static final int TYPE_FUNCTION = 2;
 
75
    
 
76
    /**
 
77
     * Type for attr (used to decide the icon)
 
78
     */
 
79
    public static final int TYPE_ATTR = 3;
 
80
    
 
81
    /**
 
82
     * Type for attr (used to decide the icon)
 
83
     */
 
84
    public static final int TYPE_BUILTIN = 4;
 
85
    
 
86
    /**
 
87
     * Type for parameter (used to decide the icon)
 
88
     */
 
89
    public static final int TYPE_PARAM = 5;
 
90
    
 
91
    /**
 
92
     * Type for package (used to decide the icon)
 
93
     */
 
94
    public static final int TYPE_PACKAGE = 6;
 
95
 
 
96
    /**
 
97
     * Type for relative import
 
98
     */
 
99
    public static final int TYPE_RELATIVE_IMPORT = 7;
 
100
    
 
101
 
 
102
    /**
 
103
     * Returns an image for the given type
 
104
     * @param type
 
105
     * @return
 
106
     */
 
107
    public static Image getImageForType(int type){
 
108
        try {
 
109
            ImageCache imageCache = PydevPlugin.getImageCache();
 
110
            if (imageCache == null)
 
111
                return null;
 
112
 
 
113
            switch (type) {
 
114
            case PyCodeCompletion.TYPE_IMPORT:
 
115
                return imageCache.get(UIConstants.COMPLETION_IMPORT_ICON);
 
116
 
 
117
            case PyCodeCompletion.TYPE_CLASS:
 
118
                return imageCache.get(UIConstants.COMPLETION_CLASS_ICON);
 
119
 
 
120
            case PyCodeCompletion.TYPE_FUNCTION:
 
121
                return imageCache.get(UIConstants.PUBLIC_METHOD_ICON);
 
122
 
 
123
            case PyCodeCompletion.TYPE_ATTR:
 
124
                return imageCache.get(UIConstants.PUBLIC_ATTR_ICON);
 
125
 
 
126
            case PyCodeCompletion.TYPE_BUILTIN:
 
127
                return imageCache.get(UIConstants.BUILTINS_ICON);
 
128
 
 
129
            case PyCodeCompletion.TYPE_PARAM:
 
130
                return imageCache.get(UIConstants.COMPLETION_PARAMETERS_ICON);
 
131
 
 
132
            case PyCodeCompletion.TYPE_PACKAGE:
 
133
                return imageCache.get(UIConstants.COMPLETION_PACKAGE_ICON);
 
134
                
 
135
            case PyCodeCompletion.TYPE_RELATIVE_IMPORT:
 
136
                return imageCache.get(UIConstants.COMPLETION_RELATIVE_IMPORT_ICON);
 
137
 
 
138
            default:
 
139
                return null;
 
140
            }
 
141
            
 
142
        } catch (Exception e) {
 
143
            PydevPlugin.log(e, false);
 
144
            return null;
 
145
        }
 
146
    }
 
147
 
 
148
    /**
 
149
     * Returns a list with the tokens to use for autocompletion.
 
150
     * 
 
151
     * The list is composed from tuples containing the following:
 
152
     * 
 
153
     * 0 - String  - token name
 
154
     * 1 - String  - token description
 
155
     * 2 - Integer - token type (see constants)
 
156
     * @param viewer 
 
157
     * 
 
158
     * @return list of IToken.
 
159
     * 
 
160
     * (This is where we do the "REAL" work).
 
161
     * @throws BadLocationException
 
162
     */
 
163
    public List getCodeCompletionProposals(ITextViewer viewer, CompletionRequest request) throws CoreException, BadLocationException {
 
164
        
 
165
        ArrayList ret = new ArrayList();
 
166
        try {
 
167
                IPythonNature pythonNature = request.nature;
 
168
            if (pythonNature == null) {
 
169
                throw new RuntimeException("Unable to get python nature.");
 
170
            }
 
171
            ICodeCompletionASTManager astManager = pythonNature.getAstManager();
 
172
            if (astManager == null) { //we're probably still loading it.
 
173
                return new ArrayList();
 
174
            }
 
175
 
 
176
            List theList = new ArrayList();
 
177
            try {
 
178
                if (CompiledModule.COMPILED_MODULES_ENABLED) {
 
179
                    AbstractShell.getServerShell(request.nature, AbstractShell.COMPLETION_SHELL); //just start it
 
180
                }
 
181
            } catch (Exception e) {
 
182
                throw new RuntimeException(e);
 
183
            }
 
184
 
 
185
            String trimmed = request.activationToken.replace('.', ' ').trim();
 
186
 
 
187
            String importsTipper = getImportsTipperStr(request);
 
188
 
 
189
            int line = request.doc.getLineOfOffset(request.documentOffset);
 
190
            IRegion region = request.doc.getLineInformation(line);
 
191
 
 
192
            CompletionState state = new CompletionState(line, request.documentOffset - region.getOffset(), null, request.nature);
 
193
 
 
194
            boolean importsTip = false;
 
195
            //code completion in imports 
 
196
            if (importsTipper.length() != 0) {
 
197
 
 
198
                //get the project and make the code completion!!
 
199
                //so, we want to do a code completion for imports...
 
200
                //let's see what we have...
 
201
 
 
202
                importsTip = true;
 
203
                importsTipper = importsTipper.trim();
 
204
                IToken[] imports = astManager.getCompletionsForImport(importsTipper, request);
 
205
                theList.addAll(Arrays.asList(imports));
 
206
 
 
207
                //code completion for a token
 
208
            } else if (trimmed.equals("") == false && request.activationToken.indexOf('.') != -1) {
 
209
 
 
210
                if (request.activationToken.endsWith(".")) {
 
211
                    request.activationToken = request.activationToken.substring(0, request.activationToken.length() - 1);
 
212
                }
 
213
                
 
214
                List completions = new ArrayList();
 
215
                if (trimmed.equals("self") || trimmed.startsWith("self")) {
 
216
                    getSelfCompletions(request, theList, state);
 
217
 
 
218
                } else {
 
219
 
 
220
                    state.activationToken = request.activationToken;
 
221
 
 
222
                    //Ok, looking for a token in globals.
 
223
                    IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state);
 
224
                    theList.addAll(Arrays.asList(comps));
 
225
                }
 
226
                theList.addAll(completions);
 
227
 
 
228
            } else { //go to globals
 
229
 
 
230
                state.activationToken = request.activationToken;
 
231
                IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state);
 
232
 
 
233
                theList.addAll(Arrays.asList(comps));
 
234
                
 
235
                theList.addAll(getGlobalsFromParticipants(request, state));
 
236
            }
 
237
 
 
238
            changeItokenToCompletionPropostal(viewer, request, ret, theList, importsTip);
 
239
        } catch (CompletionRecursionException e) {
 
240
            ret.add(new CompletionProposal("",request.documentOffset,0,0,null,e.getMessage(), null,null));
 
241
        }
 
242
 
 
243
        return ret;
 
244
    }
 
245
 
 
246
    private Collection getGlobalsFromParticipants(CompletionRequest request, ICompletionState state) {
 
247
        ArrayList ret = new ArrayList();
 
248
        
 
249
        List participants = ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_COMPLETION);
 
250
        for (Iterator iter = participants.iterator(); iter.hasNext();) {
 
251
            IPyDevCompletionParticipant participant = (IPyDevCompletionParticipant) iter.next();
 
252
            ret.addAll(participant.getGlobalCompletions(request, state));
 
253
        }
 
254
        return ret;
 
255
    }
 
256
 
 
257
    /**
 
258
     * @param request
 
259
     * @param pythonNature
 
260
     * @param astManager
 
261
     * @param theList OUT - returned completions are added here. (IToken instances)
 
262
     * @param line 
 
263
     * @param state
 
264
     * @return the same tokens added in theList
 
265
     */
 
266
    public static IToken[] getSelfCompletions(CompletionRequest request, List theList, CompletionState state) {
 
267
        return getSelfCompletions(request, theList, state, false);
 
268
    }
 
269
    
 
270
    /**
 
271
     * @param request
 
272
     * @param pythonNature
 
273
     * @param astManager
 
274
     * @param theList OUT - returned completions are added here. (IToken instances)
 
275
     * @param line 
 
276
     * @param state
 
277
     * @return the same tokens added in theList
 
278
     */
 
279
    public static IToken[] getSelfCompletions(CompletionRequest request, List theList, CompletionState state, boolean getOnlySupers) {
 
280
        IToken[] comps = new IToken[0];
 
281
        SimpleNode s = PyParser.reparseDocument(new PyParser.ParserInfo(request.doc, true, request.nature, state.line)).o1;
 
282
        if(s != null){
 
283
            FindScopeVisitor visitor = new FindScopeVisitor(state.line, 0);
 
284
            try {
 
285
                s.accept(visitor);
 
286
                comps = getSelfCompletions(visitor.scope, request, theList, state, getOnlySupers);
 
287
            } catch (Exception e1) {
 
288
                e1.printStackTrace();
 
289
            }
 
290
        }
 
291
        return comps;
 
292
    }
 
293
    
 
294
    /**
 
295
     * Get self completions when you already have a scope
 
296
     */
 
297
    public static IToken[] getSelfCompletions(Scope scope, CompletionRequest request, List theList, CompletionState state, boolean getOnlySupers) throws BadLocationException {
 
298
        IToken[] comps = new IToken[0];
 
299
        while(scope.scope.size() > 0){
 
300
            SimpleNode node = (SimpleNode) scope.scope.pop();
 
301
            if(node instanceof ClassDef){
 
302
                ClassDef d = (ClassDef) node;
 
303
                
 
304
                if(getOnlySupers){
 
305
                    List gottenComps = new ArrayList();
 
306
                    for (int i = 0; i < d.bases.length; i++) {
 
307
                        if(d.bases[i] instanceof Name){
 
308
                            Name n = (Name) d.bases[i];
 
309
                                state.activationToken = n.id;
 
310
                                    IToken[] completions = request.nature.getAstManager().getCompletionsForToken(request.editorFile, request.doc, state);
 
311
                                    gottenComps.addAll(Arrays.asList(completions));
 
312
                        }
 
313
                    }
 
314
                    comps = (IToken[]) gottenComps.toArray(new IToken[0]);
 
315
                }else{
 
316
                    //ok, get the completions for the class, only thing we have to take care now is that we may 
 
317
                    //not have only 'self' for completion, but somthing lile self.foo.
 
318
                    //so, let's analyze our activation token to see what should we do.
 
319
                    
 
320
                    String trimmed = request.activationToken.replace('.', ' ').trim();
 
321
                    String[] actTokStrs = trimmed.split(" ");
 
322
                    if(actTokStrs.length == 0 || actTokStrs[0].equals("self") == false){
 
323
                        throw new AssertionError("We need to have at least one token (self) for doing completions in the class.");
 
324
                    }
 
325
                    
 
326
                    if(actTokStrs.length == 1){
 
327
                        //ok, it's just really self, let's get on to get the completions
 
328
                        state.activationToken = NodeUtils.getNameFromNameTok((NameTok) d.name);
 
329
                            comps = request.nature.getAstManager().getCompletionsForToken(request.editorFile, request.doc, state);
 
330
                            
 
331
                    }else{
 
332
                        //it's not only self, so, first we have to get the definition of the token
 
333
                        //the first one is self, so, just discard it, and go on, token by token to know what is the last 
 
334
                        //one we are completing (e.g.: self.foo.bar)
 
335
                        int line = request.doc.getLineOfOffset(request.documentOffset);
 
336
                        IRegion region = request.doc.getLineInformationOfOffset(request.documentOffset);
 
337
                        int col =  request.documentOffset - region.getOffset();
 
338
                        IModule module = AbstractModule.createModuleFromDoc("", null, request.doc, request.nature, line);
 
339
                      
 
340
                        ASTManager astMan = ((ASTManager)request.nature.getAstManager());
 
341
                        comps = astMan.getAssignCompletions(module, new CompletionState(line, col, request.activationToken, request.nature));
 
342
 
 
343
                    }
 
344
                }
 
345
                    theList.addAll(Arrays.asList(comps));
 
346
            }
 
347
        }
 
348
        return comps;
 
349
 
 
350
    }
 
351
 
 
352
    /**
 
353
     * @param viewer 
 
354
     * @param request
 
355
     * @param convertedProposals
 
356
     * @param iTokenList
 
357
     * @param importsTip
 
358
     */
 
359
    private void changeItokenToCompletionPropostal(ITextViewer viewer, CompletionRequest request, List convertedProposals, List iTokenList, boolean importsTip) {
 
360
        //TODO: check org.eclipse.jface.text.templates.TemplateCompletionProcessor to see how to do custom 'selections' in completions
 
361
//        int offset = request.documentOffset;
 
362
//        ITextSelection selection= (ITextSelection) viewer.getSelectionProvider().getSelection();
 
363
//
 
364
//        // adjust offset to end of normalized selection
 
365
//        if (selection.getOffset() == offset)
 
366
//            offset= selection.getOffset() + selection.getLength();
 
367
//
 
368
//        String prefix= extractPrefix(viewer, offset);
 
369
//        Region region= new Region(offset - prefix.length(), prefix.length());
 
370
//
 
371
//        TemplateContextType contextType= getContextType(viewer, region);
 
372
//        if (contextType != null) {
 
373
//            IDocument document= viewer.getDocument();
 
374
//            new DocumentTemplateContext(contextType, document, region.getOffset(), region.getLength());
 
375
//        }
 
376
 
 
377
        
 
378
        for (Iterator iter = iTokenList.iterator(); iter.hasNext();) {
 
379
            
 
380
            Object obj = iter.next();
 
381
            
 
382
            if(obj instanceof IToken){
 
383
                IToken element =  (IToken) obj;
 
384
                
 
385
                String name = element.getRepresentation();
 
386
                
 
387
                //GET the ARGS
 
388
                int l = name.length();
 
389
                
 
390
                String args = "";
 
391
                if(! importsTip){
 
392
                        args = getArgs(element);                
 
393
                        if(args.length()>0){
 
394
                            l++; //cursor position is name + '('
 
395
                        }
 
396
                }
 
397
                //END
 
398
                
 
399
                String docStr = element.getDocStr();
 
400
                int type = element.getType();
 
401
                
 
402
                int priority = IPyCompletionProposal.PRIORITY_DEFAULT;
 
403
                if(type == PyCodeCompletion.TYPE_PARAM){
 
404
                    priority = IPyCompletionProposal.PRIORITY_LOCALS;
 
405
                }
 
406
                    
 
407
                PyCompletionProposal proposal = new PyCompletionProposal(name+args,
 
408
                        request.documentOffset - request.qlen, request.qlen, l, getImageForType(type), null, null, docStr, priority);
 
409
                
 
410
                convertedProposals.add(proposal);
 
411
            
 
412
            }else if(obj instanceof Object[]){
 
413
                Object element[] = (Object[]) obj;
 
414
                
 
415
                String name = (String) element[0];
 
416
                String docStr = (String) element [1];
 
417
                int type = -1;
 
418
                if(element.length > 2){
 
419
                    type = ((Integer) element [2]).intValue();
 
420
                }
 
421
 
 
422
                int priority = IPyCompletionProposal.PRIORITY_DEFAULT;
 
423
                if(type == PyCodeCompletion.TYPE_PARAM){
 
424
                    priority = IPyCompletionProposal.PRIORITY_LOCALS;
 
425
                }
 
426
                
 
427
                PyCompletionProposal proposal = new PyCompletionProposal(name,
 
428
                        request.documentOffset - request.qlen, request.qlen, name.length(), getImageForType(type), null, null, docStr, priority);
 
429
                
 
430
                convertedProposals.add(proposal);
 
431
                
 
432
            }else if(obj instanceof ICompletionProposal){
 
433
                //no need to convert
 
434
                convertedProposals.add(obj);
 
435
            }
 
436
            
 
437
        }
 
438
    }
 
439
 
 
440
    
 
441
    
 
442
    /**
 
443
     * @param element
 
444
     * @param args
 
445
     * @return
 
446
     */
 
447
    private String getArgs(IToken element) {
 
448
        String args = "";
 
449
        if(element.getArgs().trim().length() > 0){
 
450
            StringBuffer buffer = new StringBuffer("(");
 
451
            StringTokenizer strTok = new StringTokenizer(element.getArgs(), "( ,)");
 
452
 
 
453
            while(strTok.hasMoreTokens()){
 
454
                String tok = strTok.nextToken();
 
455
                if(tok.equals("self") == false){
 
456
                    if(buffer.length() > 1){
 
457
                        buffer.append(", ");
 
458
                    }
 
459
                    buffer.append(tok);
 
460
                }
 
461
            }
 
462
            buffer.append(")");
 
463
            args = buffer.toString();
 
464
        } else if (element.getType() == PyCodeCompletion.TYPE_FUNCTION){
 
465
            args = "()";
 
466
        }
 
467
        
 
468
        return args;
 
469
    }
 
470
 
 
471
 
 
472
 
 
473
    /**
 
474
     * Returns non empty string if we are in imports section 
 
475
     * 
 
476
     * @param theActivationToken
 
477
     * @param edit
 
478
     * @param doc
 
479
     * @param documentOffset
 
480
     * @return single space string if we are in imports but without any module
 
481
     *         string with current module (e.g. foo.bar.
 
482
     */
 
483
    public String getImportsTipperStr(CompletionRequest request) {
 
484
        
 
485
        IDocument doc = request.doc;
 
486
        int documentOffset = request.documentOffset;
 
487
        
 
488
        return getImportsTipperStr(doc, documentOffset);
 
489
    }
 
490
 
 
491
    public static String getImportsTipperStr(IDocument doc, int documentOffset) {
 
492
        IRegion region;
 
493
        try {
 
494
            region = doc.getLineInformationOfOffset(documentOffset);
 
495
            String trimmedLine = doc.get(region.getOffset(), documentOffset-region.getOffset());
 
496
            trimmedLine = trimmedLine.trim();
 
497
            return getImportsTipperStr(trimmedLine, true);
 
498
        } catch (BadLocationException e) {
 
499
            throw new RuntimeException(e);
 
500
        }
 
501
    }
 
502
    
 
503
    /**
 
504
     * @param doc
 
505
     * @param documentOffset
 
506
     * @return
 
507
     */
 
508
    public static String getImportsTipperStr(String trimmedLine, boolean returnEvenEmpty) {
 
509
        String importMsg = "";
 
510
        
 
511
        if(!trimmedLine.startsWith("from") && !trimmedLine.startsWith("import")){
 
512
            return "";
 
513
        }
 
514
        
 
515
        int fromIndex = trimmedLine.indexOf("from");
 
516
        int importIndex = trimmedLine.indexOf("import");
 
517
 
 
518
        //check if we have a from or an import.
 
519
        if(fromIndex  != -1 || importIndex != -1){
 
520
            trimmedLine = trimmedLine.replaceAll("#.*", ""); //remove comments 
 
521
            String[] strings = trimmedLine.split(" ");
 
522
            
 
523
            if(fromIndex != -1 && importIndex == -1){
 
524
                if(strings.length > 2){
 
525
                    //user has spaces as in  'from xxx uuu'
 
526
                    return "";
 
527
                }
 
528
            }
 
529
            
 
530
            
 
531
            for (int i = 0; i < strings.length; i++) {
 
532
                if(strings[i].equals("from")==false && strings[i].equals("import")==false){
 
533
                    if(importMsg.length() != 0){
 
534
                        importMsg += '.';
 
535
                    }
 
536
                    importMsg += strings[i];
 
537
                }
 
538
            }
 
539
            
 
540
            if(fromIndex  != -1 && importIndex != -1){
 
541
                if(strings.length == 3){
 
542
                    importMsg += '.';
 
543
                }
 
544
            }
 
545
        }else{
 
546
            return "";
 
547
        }
 
548
        if (importMsg.indexOf(".") == -1){
 
549
            if(returnEvenEmpty || importMsg.trim().length() > 0){
 
550
                return " "; //we have only import fff or from iii (so, we're going for all imports).
 
551
            }else{
 
552
                return ""; //we have only import fff or from iii (so, we're going for all imports).
 
553
            }
 
554
        }
 
555
 
 
556
        //now, we may still have something like 'unittest.test,' or 'unittest.test.,'
 
557
        //so, we have to remove this comma (s).
 
558
        int i;
 
559
        while ( ( i = importMsg.indexOf(',')) != -1){
 
560
            if(importMsg.charAt(i-1) == '.'){
 
561
                int j = importMsg.lastIndexOf('.');
 
562
                importMsg = importMsg.substring(0, j);
 
563
            }
 
564
            
 
565
            int j = importMsg.lastIndexOf('.');
 
566
            importMsg = importMsg.substring(0, j);
 
567
        }
 
568
 
 
569
        //if it is something like aaa.sss.bb : removes the bb because it is the qualifier
 
570
        //if it is something like aaa.sss.   : removes only the last point
 
571
        if (importMsg.length() > 0 && importMsg.indexOf('.') != -1){
 
572
            importMsg = importMsg.substring(0, importMsg.lastIndexOf('.'));
 
573
        }
 
574
        
 
575
        
 
576
        return importMsg;
 
577
    }
 
578
 
 
579
    /**
 
580
     * Return a document to parse, using some heuristics to make it parseable.
 
581
     * 
 
582
     * @param doc
 
583
     * @param documentOffset
 
584
     * @return
 
585
     */
 
586
    public static String getDocToParse(IDocument doc, int documentOffset) {
 
587
        int lineOfOffset = -1;
 
588
        try {
 
589
            lineOfOffset = doc.getLineOfOffset(documentOffset);
 
590
        } catch (BadLocationException e) {
 
591
            e.printStackTrace();
 
592
        }
 
593
        
 
594
        if(lineOfOffset!=-1){
 
595
            String docToParseFromLine = getDocToParseFromLine(doc, lineOfOffset);
 
596
            if(docToParseFromLine != null)
 
597
                return docToParseFromLine;
 
598
//                return "\n"+docToParseFromLine;
 
599
            else
 
600
                return "";
 
601
        }else{
 
602
            return "";
 
603
        }
 
604
    }
 
605
 
 
606
    /**
 
607
     * Return a document to parse, using some heuristics to make it parseable.
 
608
     * (Changes the line specified by a pass)
 
609
     * 
 
610
     * @param doc
 
611
     * @param documentOffset
 
612
     * @param lineOfOffset
 
613
     * @return
 
614
     */
 
615
    public static String getDocToParseFromLine(IDocument doc, int lineOfOffset) {
 
616
        return DocUtils.getDocToParseFromLine(doc, lineOfOffset);
 
617
    }
 
618
 
 
619
    /**
 
620
     * 
 
621
     * @param useSimpleTipper
 
622
     * @return the script to get the variables.
 
623
     * 
 
624
     * @throws CoreException
 
625
     */
 
626
    public static File getAutoCompleteScript() throws CoreException {
 
627
        return PydevPlugin.getScriptWithinPySrc("simpleTipper.py");
 
628
    }
 
629
 
 
630
    
 
631
    /**
 
632
     * @param pythonAndTemplateProposals
 
633
     * @param qualifier
 
634
     * @return
 
635
     */
 
636
    public ICompletionProposal[] onlyValidSorted(List pythonAndTemplateProposals, String qualifier) {
 
637
        //FOURTH: Now, we have all the proposals, only thing is deciding wich ones are valid (depending on
 
638
        //qualifier) and sorting them correctly.
 
639
        Collection returnProposals = new HashSet();
 
640
        String lowerCaseQualifier = qualifier.toLowerCase();
 
641
        
 
642
        for (Iterator iter = pythonAndTemplateProposals.iterator(); iter.hasNext();) {
 
643
            Object o = iter.next();
 
644
            if (o instanceof ICompletionProposal) {
 
645
                ICompletionProposal proposal = (ICompletionProposal) o;
 
646
            
 
647
                    if (proposal.getDisplayString().toLowerCase().startsWith(lowerCaseQualifier)) {
 
648
                        returnProposals.add(proposal);
 
649
                    }
 
650
            }else{
 
651
                throw new RuntimeException("Error: expected instanceof ICompletionProposal and received: "+o.getClass().getName());
 
652
            }
 
653
        }
 
654
 
 
655
        ICompletionProposal[] proposals = new ICompletionProposal[returnProposals.size()];
 
656
 
 
657
        // and fill with list elements
 
658
        returnProposals.toArray(proposals);
 
659
 
 
660
        Arrays.sort(proposals, PROPOSAL_COMPARATOR);
 
661
        return proposals;
 
662
    }
 
663
 
 
664
    /**
 
665
     * Compares proposals so that we can order them.
 
666
     */
 
667
    public static final ProposalsComparator PROPOSAL_COMPARATOR = new ProposalsComparator();
 
668
 
 
669
}
 
 
b'\\ No newline at end of file'