/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.services.internal.correction;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.dart.engine.services.correction.CorrectionImage;
import com.google.dart.engine.services.correction.CorrectionProposal;
import com.google.dart.engine.services.correction.LinkedPositionProposal;
import com.google.dart.engine.utilities.source.SourceRange;
import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeStartEnd;
import java.util.List;
import java.util.Map;
/**
* Helper for building Dart source with tracked positions.
*/
public class SourceBuilder {
private final int offset;
private final StringBuilder buffer = new StringBuilder();
private final Map<String, List<SourceRange>> linkedPositions = Maps.newHashMap();
private final Map<String, List<LinkedPositionProposal>> linkedProposals = Maps.newHashMap();
private String currentPositionGroupId;
private int currentPositionStart;
private int endPosition = -1;
public SourceBuilder(int offset) {
this.offset = offset;
}
public SourceBuilder(SourceRange offsetRange) {
this(offsetRange.getOffset());
}
/**
* Adds proposal for the current position, may be called after {@link #startPosition(String)}.
*/
public void addProposal(CorrectionImage icon, String text) {
List<LinkedPositionProposal> proposals = linkedProposals.get(currentPositionGroupId);
if (proposals == null) {
proposals = Lists.newArrayList();
linkedProposals.put(currentPositionGroupId, proposals);
}
proposals.add(new LinkedPositionProposal(icon, text));
}
/**
* Appends source to the buffer.
*/
public SourceBuilder append(CharSequence s) {
buffer.append(s);
return this;
}
/**
* Ends position started using {@link #startPosition(String)}.
*/
public void endPosition() {
assert currentPositionGroupId != null;
addPosition();
currentPositionGroupId = null;
}
/**
* @return the "end position" for the {@link CorrectionProposal}, may be <code>-1</code> if not
* set in this {@link SourceBuilder}.
*/
public int getEndPosition() {
if (endPosition == -1) {
return -1;
}
return offset + endPosition;
}
/**
* @return the {@link Map} or position IDs to their locations.
*/
public Map<String, List<SourceRange>> getLinkedPositions() {
return linkedPositions;
}
/**
* @return the {@link Map} of position IDs to their proposals.
*/
public Map<String, List<LinkedPositionProposal>> getLinkedProposals() {
return linkedProposals;
}
/**
* @return the offset at which this {@link SourceBuilder} should be applied in the original
* document.
*/
public int getOffset() {
return offset;
}
/**
* @return the length of the built source.
*/
public int length() {
return buffer.length();
}
/**
* Marks current position as "end position" of the {@link CorrectionProposal}.
*/
public void setEndPosition() {
endPosition = buffer.length();
}
/**
* Sets text-only proposals for the current position.
*/
public void setProposals(String[] proposals) {
List<LinkedPositionProposal> proposalList = Lists.newArrayList();
for (String proposalText : proposals) {
proposalList.add(new LinkedPositionProposal(null, proposalText));
}
linkedProposals.put(currentPositionGroupId, proposalList);
}
/**
* Starts linked position with given ID.
*/
public void startPosition(String groupId) {
assert currentPositionGroupId == null;
currentPositionGroupId = groupId;
currentPositionStart = buffer.length();
}
@Override
public String toString() {
return buffer.toString();
}
/**
* Adds position location {@link SourceRange} using current fields.
*/
private void addPosition() {
List<SourceRange> locations = linkedPositions.get(currentPositionGroupId);
if (locations == null) {
locations = Lists.newArrayList();
linkedPositions.put(currentPositionGroupId, locations);
}
int start = offset + currentPositionStart;
int end = offset + buffer.length();
locations.add(rangeStartEnd(start, end));
}
}