| /* |
| * 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.util; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| public class LocationSpec { |
| |
| /** |
| * Parse a set of tests from the given <code>originalSource</code>. The source string has test |
| * locations embedded in it, which are identified by '!X' where X is a single character. Each X is |
| * matched to positive or negative results in the array of <code>validationStrings</code>. |
| * Validation strings contain the name of a prediction with a two character prefix. The first |
| * character of the prefix corresponds to an X in the <code>originalSource</code>. The second |
| * character is either a '+' or a '-' indicating whether the string is a positive or negative |
| * result. If logical not is needed in the source it can be represented by '!!'. |
| * |
| * @param originalSource The source for a test that contains test locations |
| * @param validationStrings The positive and negative predictions |
| * @return a collection of LocationSpec instances |
| */ |
| public static Collection<LocationSpec> from(String originalSource, String[] validationStrings) { |
| Map<Character, LocationSpec> tests = new HashMap<Character, LocationSpec>(); |
| String modifiedSource = originalSource; |
| int modifiedPosition = 0; |
| while (true) { |
| int index = modifiedSource.indexOf('!', modifiedPosition); |
| if (index < 0) { |
| break; |
| } |
| int n = 1; // only delete one char for double-bangs |
| char id = modifiedSource.charAt(index + 1); |
| if (id != '!') { |
| n = 2; |
| LocationSpec test = new LocationSpec(id); |
| tests.put(id, test); |
| test.testLocation = index; |
| } else { |
| modifiedPosition = index + 1; |
| } |
| modifiedSource = modifiedSource.substring(0, index) + modifiedSource.substring(index + n); |
| } |
| if (modifiedSource.equals(originalSource)) { |
| throw new IllegalStateException("No tests in source: " + originalSource); |
| } |
| for (String result : validationStrings) { |
| if (result.length() < 3) { |
| throw new IllegalStateException("Invalid location result: " + result); |
| } |
| char id = result.charAt(0); |
| char sign = result.charAt(1); |
| String value = result.substring(2); |
| LocationSpec test = tests.get(id); |
| if (test == null) { |
| throw new IllegalStateException("Invalid location result id: " + id + " for: " + result); |
| } |
| test.source = modifiedSource; |
| if (sign == '+') { |
| test.positiveResults.add(value); |
| } else if (sign == '-') { |
| test.negativeResults.add(value); |
| } else { |
| String err = "Invalid location result sign: " + sign + " for: " + result; |
| throw new IllegalStateException(err); |
| } |
| } |
| List<Character> badPoints = new ArrayList<Character>(); |
| List<Character> badResults = new ArrayList<Character>(); |
| for (LocationSpec test : tests.values()) { |
| if (test.testLocation == -1) { |
| badPoints.add(test.id); |
| } |
| if (test.positiveResults.isEmpty() && test.negativeResults.isEmpty()) { |
| badResults.add(test.id); |
| } |
| } |
| if (!(badPoints.isEmpty() && badResults.isEmpty())) { |
| StringBuffer err = new StringBuffer(); |
| if (!badPoints.isEmpty()) { |
| err.append("No test location for tests:"); |
| for (Character ch : badPoints) { |
| err.append(' ').append(ch); |
| } |
| err.append(' '); |
| } |
| if (!badResults.isEmpty()) { |
| err.append("No results for tests:"); |
| for (Character ch : badResults) { |
| err.append(' ').append(ch); |
| } |
| } |
| throw new IllegalStateException(err.toString()); |
| } |
| return tests.values(); |
| } |
| |
| public char id; |
| public int testLocation; |
| public List<String> positiveResults; |
| public List<String> negativeResults; |
| public String source; |
| |
| LocationSpec(char id) { |
| this.id = id; |
| this.testLocation = -1; |
| this.positiveResults = new ArrayList<String>(); |
| this.negativeResults = new ArrayList<String>(); |
| } |
| } |