1c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar/*
2c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Copyright (C) 2015 The Android Open Source Project
3c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar *
4c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * you may not use this file except in compliance with the License.
6c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * You may obtain a copy of the License at
7c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar *
8c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar *
10c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Unless required by applicable law or agreed to in writing, software
11c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * See the License for the specific language governing permissions and
14c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * limitations under the License.
15c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar */
16c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
17c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarpackage android.databinding.tool.store;
18c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.ParserRuleContext;
19c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.Token;
20731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport org.apache.commons.lang3.StringUtils;
21c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
22aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.scopes.LocationScopeProvider;
23aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
24aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport java.util.Arrays;
25aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport java.util.List;
26aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
27c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAccessType;
28c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAccessorType;
29c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAttribute;
30c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlElement;
31c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
32c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar/**
33c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Identifies the range of a code block inside a file or a string.
34c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Note that, unlike antlr4 tokens, the line positions start from 0 (to be compatible with Studio).
35c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * <p>
36c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Both start and end line/column indices are inclusive.
37c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar */
38c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar@XmlAccessorType(XmlAccessType.NONE)
39c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarpublic class Location {
40c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public static final int NaN = -1;
41c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "startLine")
42c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int startLine;
43c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "startOffset")
44c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int startOffset;
45c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "endLine")
46c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int endLine;
47c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "endOffset")
48c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int endOffset;
49731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @XmlElement(name = "parentLocation")
50c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location parentLocation;
51c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
52c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    // for XML unmarshalling
53c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location() {
54c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        startOffset = endOffset = startLine = endLine = NaN;
55c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
56c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
57731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location(Location other) {
58731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        startOffset = other.startOffset;
59731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        endOffset = other.endOffset;
60731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        startLine = other.startLine;
61731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        endLine = other.endLine;
62731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
63731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
64c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location(Token start, Token end) {
65c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (start == null) {
66c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startLine = startOffset = NaN;
67c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } else {
68c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startLine = start.getLine() - 1; //token lines start from 1
69c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startOffset = start.getCharPositionInLine();
70c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
71c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
72c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (end == null) {
73c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            endLine = endOffset = NaN;
74c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } else {
75c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            endLine = end.getLine() - 1; // token lines start from 1
76731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            String endText = end.getText();
77731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            int lastLineStart = endText.lastIndexOf(System.lineSeparator());
78731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            String lastLine = lastLineStart < 0 ? endText : endText.substring(lastLineStart + 1);
79731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            endOffset = end.getCharPositionInLine() + lastLine.length() - 1;//end is inclusive
80c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
81c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
82c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
83c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location(ParserRuleContext context) {
84c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        this(context == null ? null : context.getStart(),
85c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                context == null ? null : context.getStop());
86c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
87c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
88731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location(int startLine, int startOffset, int endLine, int endOffset) {
89731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.startOffset = startOffset;
90731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.startLine = startLine;
91731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.endLine = endLine;
92731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.endOffset = endOffset;
93731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
94731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
95731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @Override
96731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public String toString() {
97731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return "Location{" +
98731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                "startLine=" + startLine +
99731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", startOffset=" + startOffset +
100731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", endLine=" + endLine +
101731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", endOffset=" + endOffset +
102731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", parentLocation=" + parentLocation +
103731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                '}';
104731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
105731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
106c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public void setParentLocation(Location parentLocation) {
107c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        this.parentLocation = parentLocation;
108c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
109c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
110c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @Override
111c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public boolean equals(Object o) {
112c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (this == o) {
113c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return true;
114c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
115c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (o == null || getClass() != o.getClass()) {
116c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
117c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
118c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
119c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        Location location = (Location) o;
120c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
121c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (endLine != location.endLine) {
122c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
123c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
124c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (endOffset != location.endOffset) {
125c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
126c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
127c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (startLine != location.startLine) {
128c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
129c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
130c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (startOffset != location.startOffset) {
131c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
132c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
133c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (parentLocation != null ? !parentLocation.equals(location.parentLocation)
134c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                : location.parentLocation != null) {
135c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
136c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
137c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
138c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        return true;
139c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
140c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
141c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @Override
142c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int hashCode() {
143c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        int result = startLine;
144c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + startOffset;
145c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + endLine;
146c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + endOffset;
147c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        return result;
148c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
149731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
150731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public boolean isValid() {
151731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return startLine != NaN && endLine != NaN && startOffset != NaN && endOffset != NaN;
152731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
153731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
154731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public boolean contains(Location other) {
155731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (startLine > other.startLine) {
156731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
157731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
158731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (startLine == other.startLine && startOffset > other.startOffset) {
159731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
160731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
161731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (endLine < other.endLine) {
162731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
163731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
164731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (endLine == other.endLine && endOffset < other.endOffset) {
165731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
166731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
167731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return true;
168731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
169731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
170731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    private Location getValidParentAbsoluteLocation() {
171731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (parentLocation == null) {
172731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return null;
173731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
174731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (parentLocation.isValid()) {
175731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return parentLocation.toAbsoluteLocation();
176731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
177731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return parentLocation.getValidParentAbsoluteLocation();
178731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
179731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
180731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location toAbsoluteLocation() {
181731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location absoluteParent = getValidParentAbsoluteLocation();
182731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (absoluteParent == null) {
183731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return this;
184731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
185731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location copy = new Location(this);
186731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        boolean sameLine = copy.startLine == copy.endLine;
187731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (copy.startLine == 0) {
188731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            copy.startOffset += absoluteParent.startOffset;
189731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
190731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (sameLine) {
191731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            copy.endOffset += absoluteParent.startOffset;
192731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
193731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
194731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        copy.startLine += absoluteParent.startLine;
195731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        copy.endLine += absoluteParent.startLine;
196731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return copy;
197731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
198731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
199731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public String toUserReadableString() {
200731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return startLine + ":" + startOffset + " - " + endLine + ":" + endOffset;
201731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
202731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
203731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public static Location fromUserReadableString(String str) {
204731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int glue = str.indexOf('-');
205731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (glue == -1) {
206731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return new Location();
207731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
208731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        String start = str.substring(0, glue);
209731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        String end = str.substring(glue + 1);
210731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int[] point = new int[]{-1, -1};
211731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location location = new Location();
212731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        parsePoint(start, point);
213731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.startLine = point[0];
214731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.startOffset = point[1];
215731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        point[0] = point[1] = -1;
216731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        parsePoint(end, point);
217731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.endLine = point[0];
218731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.endOffset = point[1];
219731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return location;
220731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
221731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
222731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    private static boolean parsePoint(String content, int[] into) {
223731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int index = content.indexOf(':');
224731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (index == -1) {
225731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
226731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
227731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        into[0] = Integer.parseInt(content.substring(0, index).trim());
228731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        into[1] = Integer.parseInt(content.substring(index + 1).trim());
229731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return true;
230731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
231aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
232aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    public LocationScopeProvider createScope() {
233aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        return new LocationScopeProvider() {
234aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            @Override
235aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            public List<Location> provideScopeLocation() {
236aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                return Arrays.asList(Location.this);
237aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
238aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        };
239aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    }
240c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar}
241