PageRenderTime 32ms CodeModel.GetById 11ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 1ms

/bundles/plugins-trunk/RubyPlugin/src/org/jedit/ruby/ast/RubyMembers.java

#
Java | 214 lines | 149 code | 31 blank | 34 comment | 42 complexity | 3554fb35c6a6fc4ed3048591e2c8c7c5 MD5 | raw file
  1/*
  2 * RubyMembers.java - Represents members in a Ruby file
  3 *
  4 * Copyright 2005 Robert McKinnon
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version 2
  9 * of the License, or any later version.
 10 *
 11 * This program is distributed in the hope that it will be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 19 */
 20package org.jedit.ruby.ast;
 21
 22import java.util.ArrayList;
 23import java.util.List;
 24
 25/**
 26 * @author robmckinnon at users.sourceforge.net
 27 */
 28public final class RubyMembers {
 29
 30    private static final int ROOT = -1;
 31    private final Member[] members;
 32
 33    private List<Member> memberList;
 34    private List<Problem> problems;
 35    private Root rootMember;
 36
 37    public RubyMembers(Member[] memberArray, List<Problem> problems, int textLength) {
 38        members = memberArray;
 39        setProblems(problems);
 40
 41        if (members != null) {
 42            memberList = new ArrayList<Member>();
 43            populateMemberList(memberArray, memberList);
 44            rootMember = new Root(textLength);
 45        }
 46    }
 47
 48    public final void setProblems(List<Problem> problems) {
 49        this.problems = problems;
 50    }
 51
 52    public final boolean containsErrors() {
 53        return members == null;
 54    }
 55
 56    public final Problem[] getProblems() {
 57        return problems.toArray(new Problem[problems.size()]);
 58    }
 59
 60    private void populateMemberList(Member[] members, List<Member> list) {
 61        for(Member member : members) {
 62            list.add(member);
 63            if(member.hasChildMembers()) {
 64                populateMemberList(member.getChildMembers(), list);
 65            }
 66        }
 67    }
 68
 69    /**
 70     * @throws RuntimeException if {@link #containsErrors()} returns true
 71     * @return size
 72     */
 73    public final int size() {
 74        return members.length;
 75    }
 76
 77    public final Member getNextMember(int caretPosition) {
 78        int index = getLastMemberIndexBefore(caretPosition);
 79        if (index == ROOT) {
 80            if(memberList.size() > 0) {
 81                return memberList.get(0);
 82            } else {
 83                return null;
 84            }
 85        } else if (index < memberList.size() - 1) {
 86            return memberList.get(index + 1);
 87        } else {
 88            return null;
 89        }
 90    }
 91
 92    public final Member getPreviousMember(int caretPosition) {
 93        int index = getLastMemberIndexBefore(caretPosition);
 94        Member lastMember = memberList.get(index);
 95        if (index > 0) {
 96            Member member = memberList.get(index - 1);
 97            if (member.getEndOffset() < lastMember.getEndOffset() || caretPosition == lastMember.getStartOffset()) {
 98                return member;
 99            } else {
100                return lastMember;
101            }
102        } else if(lastMember.getStartOffset() < caretPosition) {
103            return lastMember;
104        } else {
105            return null;
106        }
107    }
108
109    /**
110     * Returns member at caret position, if caret position
111     * is outside a Ruby member then the file's {@link Root}
112     * member is returned.
113     *
114     * @param caretPosition caret position
115     * @return {@link Member} at caret or file {@link Root} member
116     */
117    public final Member getMemberAt(int caretPosition) {
118        int index = getMemberIndexAt(caretPosition);
119        return index == ROOT ? rootMember : memberList.get(index);
120    }
121
122    public final Member getLastMemberBefore(int caretPosition) {
123        int index = getLastMemberIndexBefore(caretPosition);
124        return index == ROOT ? null : memberList.get(index);
125    }
126
127    private int getLastMemberIndexBefore(int caretPosition) {
128        int lastIndex = memberList.size() - 1;
129        int memberIndex = ROOT;
130
131        for (int i = 0; memberIndex == ROOT && i < memberList.size(); i++) {
132            Member member = memberList.get(i);
133            int start = member.getStartOffset();
134
135            if (caretPosition >= start) {
136                if (i < lastIndex) {
137                    Member nextMember = memberList.get(i + 1);
138                    int nextOffset = nextMember.getStartOffset();
139                    if (caretPosition < nextOffset) {
140                        memberIndex = i;
141                    }
142                } else {
143                    memberIndex = i;
144                }
145            }
146        }
147
148        return memberIndex;
149    }
150
151    private int getMemberIndexAt(int caretPosition) {
152        int memberIndex = ROOT;
153
154        for (int i = 0; i < memberList.size(); i++) {
155            Member member = memberList.get(i);
156            int offset = member.getStartOuterOffset();
157
158            if (caretPosition >= offset && caretPosition <= member.getEndOffset()) {
159                memberIndex = i;
160            }
161        }
162
163        return memberIndex;
164    }
165
166    public final Member[] getMembers() {
167        return members;
168    }
169
170    public final Member[] combineMembersAndProblems(int offsetLimit) {
171        if (members != null && problems != null) {
172            List<Member> accesibleMembers = new ArrayList<Member>();
173
174            for (Member member : members) {
175                if(member.getStartOffset() < offsetLimit) {
176                    accesibleMembers.add(member);
177                }
178            }
179
180            Member[] combined = new Member[accesibleMembers.size() + problems.size()];
181            int index = 0;
182            for (Member member : accesibleMembers) {
183                combined[index++] = member;
184            }
185            for (Problem problem : problems) {
186                combined[index++] = problem;
187            }
188            return combined;
189        } else {
190            throw new IllegalStateException("Can only call when members and problems are non-null arrays");
191        }
192    }
193
194    public final Member get(int index) {
195        return members[index];
196    }
197
198    public final List<Member> getClasses() {
199        final List<Member> classes = new ArrayList<Member>();
200        visitMembers(new MemberVisitorAdapter() {
201            public void handleClass(org.jedit.ruby.ast.ClassMember classMember) {
202                classes.add(classMember);
203            }
204        });
205        return classes;
206    }
207
208    public final void visitMembers(MemberVisitor visitor) {
209        for(Member member : memberList) {
210            member.accept(visitor);
211        }
212    }
213
214}