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;
184ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta
19c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.ParserRuleContext;
20c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.Token;
21c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
22aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.scopes.LocationScopeProvider;
234ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport android.databinding.tool.util.StringUtils;
24aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
255bd6addc9cb9dda23d022a6632e90591457f613eDeepanshu Guptaimport java.util.Collections;
26aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport java.util.List;
27aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
28c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAccessType;
29c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAccessorType;
30c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlAttribute;
31c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport javax.xml.bind.annotation.XmlElement;
32c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
33c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar/**
34c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Identifies the range of a code block inside a file or a string.
35c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Note that, unlike antlr4 tokens, the line positions start from 0 (to be compatible with Studio).
36c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * <p>
37c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar * Both start and end line/column indices are inclusive.
38c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar */
39c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar@XmlAccessorType(XmlAccessType.NONE)
40c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarpublic class Location {
41c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public static final int NaN = -1;
42c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "startLine")
43c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int startLine;
44c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "startOffset")
45c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int startOffset;
46c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "endLine")
47c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int endLine;
48c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @XmlAttribute(name = "endOffset")
49c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int endOffset;
50731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @XmlElement(name = "parentLocation")
51c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location parentLocation;
52c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
53c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    // for XML unmarshalling
54c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location() {
55c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        startOffset = endOffset = startLine = endLine = NaN;
56c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
57c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
58731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location(Location other) {
59731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        startOffset = other.startOffset;
60731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        endOffset = other.endOffset;
61731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        startLine = other.startLine;
62731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        endLine = other.endLine;
63731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
64731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
65c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location(Token start, Token end) {
66c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (start == null) {
67c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startLine = startOffset = NaN;
68c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } else {
69c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startLine = start.getLine() - 1; //token lines start from 1
70c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            startOffset = start.getCharPositionInLine();
71c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
72c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
73c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (end == null) {
74c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            endLine = endOffset = NaN;
75c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } else {
76c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            endLine = end.getLine() - 1; // token lines start from 1
77731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            String endText = end.getText();
784ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta            int lastLineStart = endText.lastIndexOf(StringUtils.LINE_SEPARATOR);
79731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            String lastLine = lastLineStart < 0 ? endText : endText.substring(lastLineStart + 1);
80731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            endOffset = end.getCharPositionInLine() + lastLine.length() - 1;//end is inclusive
81c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
82c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
83c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
84c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Location(ParserRuleContext context) {
85c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        this(context == null ? null : context.getStart(),
86c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                context == null ? null : context.getStop());
87c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
88c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
89731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location(int startLine, int startOffset, int endLine, int endOffset) {
90731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.startOffset = startOffset;
91731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.startLine = startLine;
92731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.endLine = endLine;
93731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        this.endOffset = endOffset;
94731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
95731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
96731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @Override
97731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public String toString() {
98731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return "Location{" +
99731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                "startLine=" + startLine +
100731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", startOffset=" + startOffset +
101731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", endLine=" + endLine +
102731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", endOffset=" + endOffset +
103731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ", parentLocation=" + parentLocation +
104731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                '}';
105731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
106731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
107c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public void setParentLocation(Location parentLocation) {
108c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        this.parentLocation = parentLocation;
109c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
110c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
111c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @Override
112c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public boolean equals(Object o) {
113c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (this == o) {
114c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return true;
115c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
116c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (o == null || getClass() != o.getClass()) {
117c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
118c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
119c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
120c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        Location location = (Location) o;
121c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
122c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (endLine != location.endLine) {
123c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
124c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
125c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (endOffset != location.endOffset) {
126c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
127c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
128c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (startLine != location.startLine) {
129c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
130c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
131c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (startOffset != location.startOffset) {
132c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
133c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
134af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar        return !(parentLocation != null ? !parentLocation.equals(location.parentLocation)
135af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar                : location.parentLocation != null);
136c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
137c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
138c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
139c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    @Override
140c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public int hashCode() {
141c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        int result = startLine;
142c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + startOffset;
143c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + endLine;
144c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        result = 31 * result + endOffset;
145c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        return result;
146c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
147731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
148731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public boolean isValid() {
149731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return startLine != NaN && endLine != NaN && startOffset != NaN && endOffset != NaN;
150731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
151731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
152731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public boolean contains(Location other) {
153731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (startLine > other.startLine) {
154731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
155731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
156731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (startLine == other.startLine && startOffset > other.startOffset) {
157731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
158731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
159731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (endLine < other.endLine) {
160731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
161731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
162af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar        return !(endLine == other.endLine && endOffset < other.endOffset);
163731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
164731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
165731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    private Location getValidParentAbsoluteLocation() {
166731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (parentLocation == null) {
167731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return null;
168731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
169731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (parentLocation.isValid()) {
170731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return parentLocation.toAbsoluteLocation();
171731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
172731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return parentLocation.getValidParentAbsoluteLocation();
173731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
174731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
175731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public Location toAbsoluteLocation() {
176731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location absoluteParent = getValidParentAbsoluteLocation();
177731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (absoluteParent == null) {
178731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return this;
179731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
180731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location copy = new Location(this);
181731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        boolean sameLine = copy.startLine == copy.endLine;
182731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (copy.startLine == 0) {
183731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            copy.startOffset += absoluteParent.startOffset;
184731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
185731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (sameLine) {
186731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            copy.endOffset += absoluteParent.startOffset;
187731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
188731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
189731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        copy.startLine += absoluteParent.startLine;
190731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        copy.endLine += absoluteParent.startLine;
191731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return copy;
192731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
193731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
194731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public String toUserReadableString() {
195731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return startLine + ":" + startOffset + " - " + endLine + ":" + endOffset;
196731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
197731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
198731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public static Location fromUserReadableString(String str) {
199731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int glue = str.indexOf('-');
200731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (glue == -1) {
201731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return new Location();
202731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
203731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        String start = str.substring(0, glue);
204731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        String end = str.substring(glue + 1);
205731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int[] point = new int[]{-1, -1};
206731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        Location location = new Location();
207731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        parsePoint(start, point);
208731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.startLine = point[0];
209731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.startOffset = point[1];
210731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        point[0] = point[1] = -1;
211731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        parsePoint(end, point);
212731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.endLine = point[0];
213731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        location.endOffset = point[1];
214731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return location;
215731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
216731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
217731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    private static boolean parsePoint(String content, int[] into) {
218731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        int index = content.indexOf(':');
219731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (index == -1) {
220731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return false;
221731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
222731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        into[0] = Integer.parseInt(content.substring(0, index).trim());
223731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        into[1] = Integer.parseInt(content.substring(index + 1).trim());
224731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return true;
225731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
226aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
227aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    public LocationScopeProvider createScope() {
228aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        return new LocationScopeProvider() {
229aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            @Override
230aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            public List<Location> provideScopeLocation() {
2315bd6addc9cb9dda23d022a6632e90591457f613eDeepanshu Gupta                return Collections.singletonList(Location.this);
232aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
233aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        };
234aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    }
235c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar}
236