blob: a7fa7790918ebd4deafbc77dc85fc9dd3a98ff88 [file] [log] [blame]
/*
* Copyright (c) 2014, 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.server.internal;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.utilities.general.ArrayUtilities;
import com.google.dart.server.AnalysisServerListener;
import com.google.dart.server.CompletionSuggestion;
import com.google.dart.server.Outline;
import com.google.dart.server.SearchResult;
import com.google.dart.server.generated.types.AnalysisError;
import com.google.dart.server.generated.types.AnalysisStatus;
import com.google.dart.server.generated.types.Element;
import com.google.dart.server.generated.types.HighlightRegion;
import com.google.dart.server.generated.types.NavigationRegion;
import com.google.dart.server.generated.types.Occurrences;
import com.google.dart.server.generated.types.OverrideMember;
import com.google.dart.server.internal.asserts.NavigationRegionsAssert;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import static org.fest.assertions.Assertions.assertThat;
import java.util.List;
import java.util.Map;
public class TestAnalysisServerListener implements AnalysisServerListener {
private final static class CompletionResult {
final int replacementOffset;
final int replacementLength;
final CompletionSuggestion[] suggestions;
final boolean last;
public CompletionResult(int replacementOffset, int replacementLength,
CompletionSuggestion[] suggestions, boolean last) {
this.replacementOffset = replacementOffset;
this.replacementLength = replacementLength;
this.suggestions = suggestions;
this.last = last;
}
}
private final Map<String, CompletionResult> completionsMap = Maps.newHashMap();
private final List<String> flushedResults = Lists.newArrayList();
private final Map<String, SearchResult[]> searchResultsMap = Maps.newHashMap();
private final List<AnalysisServerError> serverErrors = Lists.newArrayList();
private final Map<String, AnalysisError[]> sourcesErrors = Maps.newHashMap();
private final Map<String, HighlightRegion[]> highlightsMap = Maps.newHashMap();
private final Map<String, NavigationRegion[]> navigationMap = Maps.newHashMap();
private final Map<String, Occurrences[]> occurrencesMap = Maps.newHashMap();
private final Map<String, Outline> outlineMap = Maps.newHashMap();
private final Map<String, OverrideMember[]> overridesMap = Maps.newHashMap();
private boolean serverConnected = false;
private AnalysisStatus analysisStatus = null;
public synchronized void assertAnalysisStatus(AnalysisStatus expectedStatus) {
Assert.assertEquals(expectedStatus.isAnalyzing(), analysisStatus.isAnalyzing());
Assert.assertEquals(expectedStatus.getAnalysisTarget(), analysisStatus.getAnalysisTarget());
}
/**
* Assert that the number of errors that have been gathered matches the number of errors that are
* given and that they have the expected error codes. The order in which the errors were gathered
* is ignored.
*
* @param file the file to check errors for
* @param expectedErrorCodes the error codes of the errors that should have been gathered
* @throws AssertionFailedError if a different number of errors have been gathered than were
* expected
*/
public synchronized void assertErrorsWithAnalysisErrors(String file,
AnalysisError... expectedErrors) {
AnalysisError[] errors = getErrors(file);
assertErrorsWithAnalysisErrors(errors, expectedErrors);
}
/**
* Asserts the list of flushed results.
*/
public synchronized void assertFlushedResults(List<String> expectedFlushedResults) {
assertThat(expectedFlushedResults).isEqualTo(flushedResults);
}
/**
* Returns {@link NavigationRegionsAssert} for the given file.
*/
public synchronized NavigationRegionsAssert assertNavigationRegions(String file) {
return new NavigationRegionsAssert(getNavigationRegions(file));
}
/**
* Asserts that there was no {@link AnalysisServerError} reported.
*/
public synchronized void assertNoServerErrors() {
assertThat(serverErrors).isEmpty();
}
public synchronized void assertServerConnected(boolean expectedConnected) {
Assert.assertEquals(expectedConnected, serverConnected);
}
public void assertServerErrors(List<AnalysisServerError> expectedErrors) {
Assert.assertEquals(expectedErrors.size(), serverErrors.size());
for (int i = 0; i < expectedErrors.size(); i++) {
Assert.assertTrue(expectedErrors.get(i).equals(serverErrors.get(i)));
}
}
/**
* Removes all of reported {@link NavigationRegion}s.
*/
public synchronized void clearNavigationRegions() {
navigationMap.clear();
}
/**
* Removes all of reported {@link Occurrences}s.
*/
public synchronized void clearOccurrences() {
occurrencesMap.clear();
}
/**
* Removes all of reported {@link OverrideMember}.
*/
public synchronized void clearOverrides() {
overridesMap.clear();
}
@Override
public synchronized void computedCompletion(String completionId, int replacementOffset,
int replacementLength, CompletionSuggestion[] suggestions, boolean last) {
// computed completion results are aggregate, replacing any prior results
completionsMap.put(completionId, new CompletionResult(
replacementOffset,
replacementLength,
suggestions,
last));
}
@Override
public synchronized void computedErrors(String file, AnalysisError[] errors) {
sourcesErrors.put(file, errors);
}
@Override
public synchronized void computedHighlights(String file, HighlightRegion[] highlights) {
highlightsMap.put(file, highlights);
}
@Override
public synchronized void computedNavigation(String file, NavigationRegion[] targets) {
navigationMap.put(file, targets);
}
@Override
public void computedOccurrences(String file, Occurrences[] occurrencesArray) {
occurrencesMap.put(file, occurrencesArray);
}
@Override
public synchronized void computedOutline(String file, Outline outline) {
outlineMap.put(file, outline);
}
@Override
public void computedOverrides(String file, OverrideMember[] overrides) {
overridesMap.put(file, overrides);
}
@Override
public void computedSearchResults(String searchId, SearchResult[] results, boolean last) {
searchResultsMap.put(searchId, results);
}
/**
* Returns a navigation {@link Element} at the given position.
*/
public synchronized Element findNavigationElement(String file, int offset) {
NavigationRegion[] regions = getNavigationRegions(file);
if (regions != null) {
for (NavigationRegion navigationRegion : regions) {
if (navigationRegion.containsInclusive(offset)) {
return navigationRegion.getTargets().get(0);
}
}
}
return null;
}
@Override
public synchronized void flushedResults(List<String> files) {
flushedResults.addAll(files);
}
public boolean getCompletionIsLast(String completionId) {
CompletionResult result = completionsMap.get(completionId);
if (result == null) {
throw new AssertionFailedError("Expected completion response: " + completionId);
}
return result.last;
}
public int getCompletionReplacementLength(String completionId) {
CompletionResult result = completionsMap.get(completionId);
if (result == null) {
throw new AssertionFailedError("Expected completion response: " + completionId);
}
return result.replacementLength;
}
public int getCompletionReplacementOffset(String completionId) {
CompletionResult result = completionsMap.get(completionId);
if (result == null) {
throw new AssertionFailedError("Expected completion response: " + completionId);
}
return result.replacementOffset;
}
/**
* Returns {@link CompletionSuggestion[]} for the given completion id, maybe {@code null} if have
* not been ever notified.
*/
public synchronized CompletionSuggestion[] getCompletions(String completionId) {
CompletionResult result = completionsMap.get(completionId);
return result != null ? result.suggestions : null;
}
/**
* Returns {@link AnalysisError} for the given file, may be empty, but not {@code null}.
*/
public synchronized AnalysisError[] getErrors(String file) {
AnalysisError[] errors = sourcesErrors.get(file);
if (errors == null) {
return AnalysisError.EMPTY_ARRAY;
}
return errors;
}
/**
* Returns {@link HighlightRegion}s for the given file, maybe {@code null} if have not been ever
* notified.
*/
public synchronized HighlightRegion[] getHighlightRegions(String file) {
return highlightsMap.get(file);
}
/**
* Returns {@link NavigationRegion}s for the given file, maybe {@code null} if have not been ever
* notified.
*/
public synchronized NavigationRegion[] getNavigationRegions(String file) {
return navigationMap.get(file);
}
/**
* Returns {@link Occurrences}s for the given file, maybe {@code null} if have not been ever
* notified.
*/
public synchronized Occurrences[] getOccurrences(String file) {
return occurrencesMap.get(file);
}
/**
* Returns {@link Outline} for the given {@link Source}, maybe {@code null} if have not been ever
* notified.
*/
public synchronized Outline getOutline(String file) {
return outlineMap.get(file);
}
/**
* Returns {@link OverrideMember}s for the given file, maybe {@code null} if have not been ever
* notified.
*/
public synchronized OverrideMember[] getOverrides(String file) {
return overridesMap.get(file);
}
/**
* Returns {@link SearchResult[]} for the given search id, maybe {@code null} if have not been
* ever notified.
*/
public SearchResult[] getSearchResults(String searchId) {
return searchResultsMap.get(searchId);
}
@Override
public synchronized void serverConnected() {
serverConnected = true;
}
@Override
public synchronized void serverError(boolean isFatal, String message, String stackTrace) {
serverErrors.add(new AnalysisServerError(isFatal, message, stackTrace));
}
@Override
public synchronized void serverStatus(AnalysisStatus status) {
this.analysisStatus = status;
}
/**
* Assert that the array of actual {@link AnalysisError}s match the array of expected
* {@link AnalysisError}s.
*
* @param actualErrors the actual set of errors that were created for some analysis
* @param expectedErrors the expected array of errors
*/
private void assertErrorsWithAnalysisErrors(AnalysisError[] actualErrors,
AnalysisError[] expectedErrors) {
if (actualErrors == null && expectedErrors == null) {
return;
}
// assert that the arrays have the same length
Assert.assertEquals(expectedErrors.length, actualErrors.length);
// assert that the actualErrors contains all of the expected errors
for (AnalysisError expectedError : expectedErrors) {
// individual calls to assert each error are made for better messaging when there is a failure
Assert.assertTrue(ArrayUtilities.contains(actualErrors, expectedError));
}
}
}