Merge branch 'master' into async_validations

Conflicts:
	headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/EnumValueParser.java
This commit is contained in:
nsingh
2017-08-02 12:16:33 -07:00
55 changed files with 1837 additions and 408 deletions

View File

@@ -26,8 +26,10 @@ import com.google.common.collect.ImmutableSet;
public class EnumValueParser implements ValueParser {
private String typeName;
private Provider<Collection<String>> values;
private final boolean longRunning;
private Provider<PartialCollection<String>> values;
private final boolean longRunning;
public EnumValueParser(String typeName, String... values) {
this(typeName, ImmutableSet.copyOf(values));
@@ -37,16 +39,28 @@ public class EnumValueParser implements ValueParser {
this(typeName, false /* not long running by default */, provider(values));
}
private static <T> Provider<PartialCollection<T>> provider(Collection<T> values) {
return () -> PartialCollection.compute(() -> values);
}
private static <T> Provider<PartialCollection<T>> provider(Callable<Collection<T>> values) {
return () -> PartialCollection.compute(() -> values.call());
}
public EnumValueParser(String typeName, boolean longRunning, Callable<Collection<String>> values) {
this(typeName, longRunning, provider(values));
}
public EnumValueParser(String typeName, boolean longRunning, Provider<Collection<String>> values) {
public EnumValueParser(String typeName, boolean longRunning, Provider<PartialCollection<String>> values) {
this.typeName = typeName;
this.values = values;
this.longRunning = longRunning;
}
public EnumValueParser(String name, PartialCollection<String> values) {
this(name, false /* not long running by default */, () -> values);
}
@Override
public Object parse(String str) throws Exception {
// IMPORTANT: check the text FIRST before fetching values
@@ -56,13 +70,13 @@ public class EnumValueParser implements ValueParser {
throw errorOnBlank(createBlankTextErrorMessage());
}
Collection<String> values = this.values.get();
PartialCollection<String> values = this.values.get();
// If values is not known (null) then just assume the str is acceptable.
if (values == null || values.contains(str)) {
// If values is not fully known then just assume the str is acceptable.
if (values == null || !values.isComplete() || values.getElements().contains(str)) {
return str;
} else {
throw errorOnParse(createErrorMessage(str, values));
throw errorOnParse(createErrorMessage(str, values.getElements()));
}
}
@@ -81,21 +95,6 @@ public class EnumValueParser implements ValueParser {
protected Exception errorOnBlank(String message) {
return new ValueParseException(message);
}
private static <T> Provider<T> provider(T values) {
return () -> values;
}
private static <T> Provider<T> provider(Callable<T> values) {
return () -> {
try {
return values.call();
} catch (Exception e) {
// Ignore
return null;
}
};
}
public boolean longRunning() {
return this.longRunning ;

View File

@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.commons.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeoutException;
/**
@@ -76,4 +77,27 @@ public class ExternalCommand {
// org.junit.Assert.assertEquals(0, process.getExitValue());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(command);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ExternalCommand other = (ExternalCommand) obj;
if (!Arrays.equals(command, other.command))
return false;
return true;
}
}

View File

@@ -0,0 +1,153 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.Callable;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;
/**
* A partial collection instance represents collection of
* elements which may not be entirely known.
* <p>
* For unknown collection, an optional explanation, in the
* form of a caught exception may be stored as well.
*/
public class PartialCollection<T> {
private static final PartialCollection<?> UNKNOWN = new PartialCollection<>(ImmutableSet.of(), false);
private static final PartialCollection<?> EMPTY = new PartialCollection<>(ImmutableSet.of(), true);
final private ImmutableCollection<T> knownElements;
final private boolean isComplete;
final private Throwable explanation;
private PartialCollection(ImmutableCollection<T> knownElements, boolean isComplete, Throwable error) {
this.knownElements = knownElements;
this.isComplete = isComplete;
this.explanation = error;
}
private PartialCollection(ImmutableCollection<T> knownElements, boolean isComplete) {
this.knownElements = knownElements;
this.isComplete = isComplete;
this.explanation = null;
}
private PartialCollection(ImmutableCollection<T> knownElements, Throwable error) {
this.knownElements = knownElements;
this.isComplete = error==null;
this.explanation = error;
}
/**
* Create a {@link PartialCollection} by executing some computation that returs a collectioon.
* If the computation throws the resulting collection will be completely unknown, otherwise
* it will be completely known.
*/
public static <T> PartialCollection<T> compute(Callable<Collection<T>> computer) {
try {
Collection<T> allValues = computer.call();
if (allValues==null) {
return PartialCollection.unknown();
}
return new PartialCollection<>(ImmutableSet.copyOf(allValues), true);
} catch (Exception e) {
return new PartialCollection<>(ImmutableSet.of(), e);
}
}
/**
* Create a {@link PartialCollection} by executing some computation that returs a collectioon.
* If the computation throws the resulting collection will be completely unknown, otherwise
* it will be completely known.
*/
public static <T> PartialCollection<T> fromCallable(Callable<PartialCollection<T>> computer) {
try {
return computer.call();
} catch (Exception e) {
return new PartialCollection<>(ImmutableSet.of(), e);
}
}
/**
* @return All the known elements of this partial collection.
*/
public Collection<T> getElements() {
return knownElements;
}
public boolean isComplete() {
return isComplete;
}
/**
* Returns the totally unknown collection. I.e. a unknown collection with no known elements
*/
@SuppressWarnings("unchecked")
public static <T> PartialCollection<T> unknown() {
return (PartialCollection<T>) UNKNOWN;
}
/**
* Like map on streams, but silently drops any null elements returned by the mapper.
*/
public <R> PartialCollection<R> map(Function<? super T, ? extends R> mapper) {
ImmutableSet<R> mappedElements = getElements().stream().map((x) -> mapper.apply(x)).filter(x -> x!=null).collect(CollectorUtil.toImmutableSet());
return new PartialCollection<R>(mappedElements, isComplete, explanation);
}
/**
* Returns a empty collection (i.e. the collection is know to be empty).
*/
@SuppressWarnings("unchecked")
public static <T> PartialCollection<T> empty() {
return (PartialCollection<T>) EMPTY;
}
/**
* Make a copy of this collection that has the same known elements but also has unknown elements.
*/
public PartialCollection<T> addUncertainty() {
if (!this.isComplete()) {
return this; //No need to make a copy. Current collection is already only partially known.
}
return new PartialCollection<>(knownElements, false);
}
/**
* A completely unknown collection with a given exception explaining the reason.
*/
public static <T> PartialCollection<T> unknown(Exception e) {
Assert.isLegal(e!=null);
return new PartialCollection<>(ImmutableSet.of(), e);
}
public PartialCollection<T> addAll(Collection<T> moreElements) {
ImmutableSet.Builder<T> elements = ImmutableSet.builder();
elements.addAll(getElements());
elements.addAll(moreElements);
return new PartialCollection<>(elements.build(), isComplete, explanation);
}
public Throwable getExplanation() {
return explanation;
}
public PartialCollection<T> add(@SuppressWarnings("unchecked") T... values) {
return addAll(Arrays.asList(values));
}
}

View File

@@ -21,6 +21,7 @@ import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.linetracker.DefaultLineTracker;
import org.springframework.ide.vscode.commons.util.text.linetracker.ILineTracker;
@@ -88,11 +89,14 @@ public class TextDocument implements IDocument {
public synchronized void apply(DidChangeTextDocumentParams params) throws BadLocationException {
int newVersion = params.getTextDocument().getVersion();
Assert.isLegal(version<newVersion);
for (TextDocumentContentChangeEvent change : params.getContentChanges()) {
apply(change);
if (version<newVersion) {
for (TextDocumentContentChangeEvent change : params.getContentChanges()) {
apply(change);
}
this.version = newVersion;
} else {
Log.warn("Change event with bad version ignored: "+params);
}
this.version = newVersion;
}
/**