Changeset 876

Show
Ignore:
Timestamp:
10/22/07 22:32:59 (1 year ago)
Author:
asterite
Message:

First interesting completion: case statement for enum values. :-D
(experimental and horribly coded for my taste... and not optimized, of course, but it works!)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/descent.core/src/descent/internal/codeassist/CompletionEngine.java

    r875 r876  
    44import java.util.Map; 
    55 
     6import descent.core.CompletionContext; 
    67import descent.core.CompletionProposal; 
    78import descent.core.CompletionRequestor; 
     
    1314import descent.internal.codeassist.complete.CompletionOnArgumentName; 
    1415import descent.internal.codeassist.complete.CompletionOnBreakStatement; 
     16import descent.internal.codeassist.complete.CompletionOnCaseStatement; 
    1517import descent.internal.codeassist.complete.CompletionOnContinueStatement; 
    1618import descent.internal.codeassist.complete.CompletionOnGotoStatement; 
     
    2527import descent.internal.compiler.parser.ASTDmdNode; 
    2628import descent.internal.compiler.parser.Argument; 
     29import descent.internal.compiler.parser.CaseStatement; 
     30import descent.internal.compiler.parser.CastExp; 
    2731import descent.internal.compiler.parser.ClassDeclaration; 
    2832import descent.internal.compiler.parser.CompoundStatement; 
     33import descent.internal.compiler.parser.Dsymbol; 
    2934import descent.internal.compiler.parser.EnumDeclaration; 
     35import descent.internal.compiler.parser.EnumMember; 
     36import descent.internal.compiler.parser.ErrorExp; 
     37import descent.internal.compiler.parser.Expression; 
    3038import descent.internal.compiler.parser.FuncDeclaration; 
    3139import descent.internal.compiler.parser.FuncLiteralDeclaration; 
     
    4048import descent.internal.compiler.parser.Statement; 
    4149import descent.internal.compiler.parser.StructDeclaration; 
     50import descent.internal.compiler.parser.SwitchStatement; 
    4251import descent.internal.compiler.parser.TemplateDeclaration; 
    4352import descent.internal.compiler.parser.Type; 
     53import descent.internal.compiler.parser.TypeEnum; 
    4454import descent.internal.compiler.parser.TypeFunction; 
    4555import descent.internal.compiler.parser.UnionDeclaration; 
    4656import descent.internal.compiler.parser.UnitTestDeclaration; 
     57import descent.internal.compiler.parser.VarDeclaration; 
     58import descent.internal.compiler.parser.VarExp; 
    4759import descent.internal.compiler.parser.VersionCondition; 
    4860import descent.internal.compiler.parser.ast.AstVisitorAdapter; 
     
    158170            ASTDmdNode assistNode = parser.getAssistNode(); 
    159171             
     172            this.requestor.acceptContext(buildContext()); 
     173             
    160174            // First the assist node 
    161175            if (assistNode != null) { 
     
    183197                    CompletionOnVersionCondition node = (CompletionOnVersionCondition) assistNode; 
    184198                    completeVersionCondition(node); 
     199                } else if (assistNode instanceof CompletionOnCaseStatement) { 
     200                    CompletionOnCaseStatement node = (CompletionOnCaseStatement) assistNode; 
     201                    completeCaseStatement(node); 
    185202                } 
    186203            } 
     
    195212                } 
    196213            } 
    197              
     214        } catch (Exception e) { 
     215            e.printStackTrace(); 
    198216        } finally { 
    199217            this.requestor.endReporting(); 
    200218        } 
     219    } 
     220 
     221    private CompletionContext buildContext() { 
     222        // TODO Descent completion context 
     223        CompletionContext context = new CompletionContext(); 
     224        context.setOffset(this.offset); 
     225        return context; 
    201226    } 
    202227 
     
    405430                proposal.setName(id); 
    406431                proposal.setCompletion(id); 
     432                proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); 
     433                CompletionEngine.this.requestor.accept(proposal); 
     434            } 
     435        } 
     436    } 
     437     
     438    private void completeCaseStatement(CompletionOnCaseStatement node) { 
     439        doSemantic(module); 
     440         
     441        // Check to see if the condition is an enum, and suggest 
     442        // the members of it 
     443        SwitchStatement sw = node.sw; 
     444        if (sw == null) { 
     445            return; 
     446        } 
     447         
     448        // TODO maybe make each node implement something like 
     449        // "findEnumDeclaration" 
     450        TypeEnum typeEnum; 
     451         
     452        Expression condition = sw.condition; 
     453        if (condition == null) { 
     454            return; 
     455        } else if (condition instanceof VarExp) { 
     456            VarExp var = (VarExp) condition; 
     457            Type type = var.type; 
     458            if (type == null || !(type instanceof TypeEnum)) { 
     459                return; 
     460            } 
     461             
     462            typeEnum = (TypeEnum) type;  
     463        } else if (condition instanceof CastExp) { 
     464            CastExp castExp = (CastExp) condition; 
     465            if (castExp.e1 == null || !(castExp.e1 instanceof VarExp)) { 
     466                return; 
     467            } 
     468             
     469            VarExp varExp = (VarExp) castExp.e1; 
     470            if (varExp.var == null || !(varExp.var instanceof VarDeclaration)) { 
     471                return; 
     472            } 
     473             
     474            VarDeclaration varDeclaration = (VarDeclaration) varExp.var; 
     475            if (varDeclaration.type == null || !(varDeclaration.type instanceof TypeEnum)) { 
     476                return; 
     477            } 
     478             
     479            typeEnum = (TypeEnum) varDeclaration.type; 
     480        } else { 
     481            return; 
     482        } 
     483         
     484        EnumDeclaration enumDeclaration = typeEnum.sym; 
     485        if (enumDeclaration == null) { 
     486            return; 
     487        } 
     488         
     489        if (enumDeclaration.members == null) { 
     490            return; 
     491        } 
     492         
     493        char[] name; 
     494        Expression caseExp = node.originalExpression; 
     495        if (caseExp instanceof ErrorExp) { 
     496            name = CharOperation.NO_CHAR; 
     497            this.startPosition = this.actualCompletionPosition; 
     498            this.endPosition = this.actualCompletionPosition; 
     499        } else if (caseExp instanceof IdentifierExp) { 
     500            IdentifierExp idExp = (IdentifierExp) caseExp; 
     501            name = idExp.ident; 
     502            this.startPosition = idExp.start; 
     503            this.endPosition = this.actualCompletionPosition; 
     504        } else { 
     505            return; 
     506        } 
     507         
     508        HashtableOfCharArrayAndObject excludedNames = new HashtableOfCharArrayAndObject(); 
     509        if (sw.cases != null) { 
     510            for(Object caseObject : sw.cases) { 
     511                CaseStatement caseStatement = (CaseStatement) caseObject; 
     512                Expression exp = caseStatement.sourceExp; 
     513                if (exp != null) { 
     514                    excludedNames.put(exp.toCharArray(), this); 
     515                } 
     516            } 
     517        } 
     518         
     519        for(Dsymbol symbol : enumDeclaration.members) { 
     520            if (!(symbol instanceof EnumMember)) { 
     521                continue; 
     522            } 
     523             
     524            EnumMember member = (EnumMember) symbol; 
     525             
     526            char[] proposition = CharOperation.concat(enumDeclaration.ident.ident, member.ident.ident, '.'); 
     527            if (!excludedNames.containsKey(proposition) && 
     528                    CharOperation.prefixEquals(name, proposition, false)) { 
     529                CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); 
     530                proposal.setName(proposition); 
     531                proposal.setCompletion(proposition); 
    407532                proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); 
    408533                CompletionEngine.this.requestor.accept(proposal); 
  • trunk/descent.core/src/descent/internal/codeassist/complete/CompletionParser.java

    r874 r876  
    22 
    33import java.util.ArrayList; 
     4import java.util.Collections; 
    45import java.util.List; 
    56 
     
    89import descent.internal.compiler.parser.Argument; 
    910import descent.internal.compiler.parser.BreakStatement; 
     11import descent.internal.compiler.parser.CaseStatement; 
    1012import descent.internal.compiler.parser.Chars; 
    1113import descent.internal.compiler.parser.ContinueStatement; 
     14import descent.internal.compiler.parser.ErrorExp; 
    1215import descent.internal.compiler.parser.Expression; 
    1316import descent.internal.compiler.parser.GotoStatement; 
     
    2023import descent.internal.compiler.parser.ModuleDeclaration; 
    2124import descent.internal.compiler.parser.Parser; 
     25import descent.internal.compiler.parser.Statement; 
    2226import descent.internal.compiler.parser.TOK; 
    2327import descent.internal.compiler.parser.Type; 
     
    4650     
    4751    public List<ICompletionOnKeyword> getKeywordCompletions() { 
    48         return keywordCompletions; 
     52        if (includeExpectations) { 
     53            return keywordCompletions; 
     54        } else { 
     55            return Collections.EMPTY_LIST; 
     56        } 
    4957    } 
    5058     
     
    190198    } 
    191199     
     200    @Override 
     201    protected CaseStatement newCaseStatement(Loc loc, Expression exp, Statement statement, int caseEnd, int expStart, int expLength) { 
     202        // exp.start is -1 if it's an error expression 
     203        if (caseEnd <= cursorLocation && cursorLocation <= expStart + expLength && exp != null && (exp instanceof ErrorExp ||  
     204                (exp.getNodeType() == ASTDmdNode.IDENTIFIER_EXP))) { 
     205            includeExpectations = false; 
     206             
     207            assistNode = new CompletionOnCaseStatement(loc, exp, statement); 
     208            return (CaseStatement) assistNode; 
     209        } else { 
     210            return super.newCaseStatement(loc, exp, statement, caseEnd, expStart, expLength); 
     211        } 
     212    } 
     213     
    192214    private boolean inCompletion() { 
    193215        return prevToken.ptr + prevToken.sourceLen <= cursorLocation && cursorLocation <= token.ptr + token.sourceLen 
  • trunk/descent.core/src/descent/internal/compiler/parser/CaseStatement.java

    r847 r876  
    1212    public Expression exp, sourceExp; 
    1313    public Statement statement, sourceStatement; 
     14     
     15    public SwitchStatement sw; // descent 
    1416 
    1517    public CaseStatement(Loc loc, Expression exp, Statement s) { 
     
    7880    public Statement semantic(Scope sc, SemanticContext context) { 
    7981        SwitchStatement sw = sc.sw; 
     82        this.sw = sw; 
    8083 
    8184        exp = exp.semantic(sc, context); 
     
    120123    } 
    121124     
     125    public void setStatement(Statement s) { 
     126        this.statement = this.sourceStatement = s; 
     127    } 
     128     
    122129    @Override 
    123130    public Statement syntaxCopy() { 
     
    150157    } 
    151158 
     159     
     160 
    152161} 
  • trunk/descent.core/src/descent/internal/compiler/parser/GotoStatement.java

    r860 r876  
    1111    public LabelDsymbol label; 
    1212    public TryFinallyStatement tf; 
    13      
    14     public FuncDeclaration fd; // descent: The parent function declaration after the first semantic pass is done 
    1513 
    1614    public GotoStatement(Loc loc, IdentifierExp ident) { 
     
    5856    @Override 
    5957    public Statement semantic(Scope sc, SemanticContext context) { 
    60         FuncDeclaration fd = sc.parent.isFuncDeclaration(); 
    61         this.fd = fd; // descent 
    62         tf = sc.tf; 
    63          
    6458        if (ident == null) { 
    65             // It's a broken node, it has already syntax errors, 
    66             // but assign fd and tf first 
     59            // It's a broken node, it has already syntax errors 
    6760            return this; 
    6861        } 
    6962         
     63        FuncDeclaration fd = sc.parent.isFuncDeclaration(); 
     64        tf = sc.tf; 
    7065        label = fd.searchLabel(ident); 
    7166        if (null == label.statement && sc.fes != null) { 
  • trunk/descent.core/src/descent/internal/compiler/parser/Parser.java

    r874 r876  
    41284128            Expression exp; 
    41294129            Statements statements; 
    4130             List cases = new ArrayList(); // array of Expression's 
     4130            // List cases = new ArrayList(); // array of Expression's 
     4131             
     4132            // Note: this code was changed a little from DMD to support 
     4133            // better code completion 
     4134            List<CaseStatement> caseStatements = new ArrayList<CaseStatement>(); 
    41314135 
    41324136            while (true) { 
     4137                int caseEnd = token.ptr + token.sourceLen; 
     4138                 
    41334139                nextToken(); 
     4140                 
     4141                int expStart = token.ptr; 
     4142                int expLength = token.sourceLen; 
     4143                 
    41344144                exp = parseAssignExp(); 
    4135                 cases.add(exp); 
    4136                 if (token.value != TOKcomma) 
     4145                caseStatements.add(newCaseStatement(loc, exp, null, caseEnd, expStart, expLength));          
     4146                // cases.add(exp); 
     4147                 
     4148                if (token.value != TOKcomma) { 
    41374149                    break; 
     4150                } 
    41384151            } 
    41394152            check(TOKcolon); 
     
    41424155            while (token.value != TOKcase && token.value != TOKdefault 
    41434156                    && token.value != TOKrcurly) { 
     4157                 
     4158                if (token.value == TOKeof) { 
     4159                    break; 
     4160                } 
     4161                 
    41444162                statements.add(parseStatement(PSsemi | PScurlyscope)); 
    41454163            } 
     
    41484166             
    41494167            /* 
     4168            FIXME this can bring incompatibilities between Descent and DMD: put back! 
    41504169            s = new ScopeStatement(s); 
    41514170            */ 
    41524171 
    41534172            // Keep cases in order by building the case statements backwards 
    4154             for (int i = cases.size(); i != 0; i--) { 
    4155                 exp = (Expression) cases.get(i - 1); 
    4156                 s = new CaseStatement(loc, exp, s); 
    4157             } 
     4173//          for (int i = cases.size(); i != 0; i--) { 
     4174//              exp = (Expression) cases.get(i - 1); 
     4175//              s = new CaseStatement(loc, exp, s); 
     4176//          } 
     4177             
     4178            for(int i = caseStatements.size(); i != 0; i--) { 
     4179                CaseStatement cs = caseStatements.get(i - 1); 
     4180                cs.setStatement(s); 
     4181                s = cs; 
     4182            } 
     4183             
    41584184            break; 
    41594185        } 
     
    58165842        // Lerr: 
    58175843            // Anything for e, as long as it's not NULL 
    5818             e = new IntegerExp(loc, Id.ZERO, 0, Type.tint32); 
     5844            e = new ErrorExp(); 
    58195845            e.setSourceRange(token.ptr, token.sourceLen); 
    58205846            nextToken(); 
     
    70047030    } 
    70057031     
     7032    protected CaseStatement newCaseStatement(Loc loc, Expression exp, Statement statement, int caseEnd, int expStart, int expLength) { 
     7033        return new CaseStatement(loc, exp, statement); 
     7034    } 
     7035     
    70067036    /** 
    70077037     * The parser expects the current token to be 
  • trunk/descent.tests/descent/tests/mars/Bugs_Test.java

    r797 r876  
    230230    } 
    231231     
     232    public void testCaseOpen() { 
     233        String s = "void foo() { switch(1) case "; 
     234        getCompilationUnit(s);   
     235    } 
     236     
    232237    public void testDstress_run_t_typeof_16_A() { 
    233238        String s = "char[] name = (typeof(o)).classinfo.name;"; 
  • trunk/descent.ui/src/descent/ui/text/java/CompletionProposalLabelProvider.java

    r875 r876  
    369369        StringBuffer buf= new StringBuffer(); 
    370370        buf.append(proposal.getCompletion()); 
     371        /* TODO JDT code complete 
    371372        char[] typeName= Signature.getSignatureSimpleName(proposal.getSignature()); 
    372373        if (typeName.length > 0) { 
     
    382383            } 
    383384        } 
    384  
     385        */ 
    385386        return buf.toString(); 
    386387    } 
     
    544545 
    545546    ImageDescriptor createPackageImageDescriptor(CompletionProposal proposal) { 
    546         return decorateImageDescriptor(JavaPluginImages.DESC_OBJS_PACKAGE, proposal); 
     547        return decorateImageDescriptor(JavaPluginImages.DESC_OBJS_MODULE, proposal); 
    547548    } 
    548549