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:
@@ -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 ;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user