blob: f8d2d33829d43284283053c5735bb59e24afb0de [file] [log] [blame]
/*
* Copyright (c) 2011 Google 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
*/
package com.google.eclipse.protobuf.validation;
import static com.google.common.collect.Lists.newArrayListWithExpectedSize;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.eclipse.protobuf.validation.Messages.*;
import static org.eclipse.xtext.diagnostics.Severity.*;
import static org.eclipse.xtext.validation.AbstractInjectableValidator.CURRENT_LANGUAGE_NAME;
import static org.eclipse.xtext.validation.CancelableDiagnostician.CANCEL_INDICATOR;
import static org.eclipse.xtext.validation.CheckMode.KEY;
import static org.eclipse.xtext.validation.CheckType.FAST;
import static org.eclipse.xtext.validation.impl.ConcreteSyntaxEValidator.DISABLE_CONCRETE_SYNTAX_EVALIDATOR;
import com.google.eclipse.protobuf.linking.ProtobufDiagnostic;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.*;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.*;
import org.eclipse.xtext.validation.*;
import java.util.*;
/**
* Adds support for converting scoping errors into warnings if non-proto2 files are imported.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class ProtobufResourceValidator extends ResourceValidatorImpl {
private static final Logger log = Logger.getLogger(ProtobufResourceValidator.class);
@Override public List<Issue> validate(Resource resource, CheckMode mode, CancelIndicator indicator) {
CancelIndicator monitor = indicator == null ? CancelIndicator.NullImpl : indicator;
// long start = System.currentTimeMillis();
URI uri = resource.getURI();
if (uri.toString().endsWith("BulkMutatePayloadPseudoService.proto")) {
System.out.println("Ignoring validation BulkMutatePayloadPseudoService.proto");
} else {
resolveProxies(resource, monitor);
}
// long end = System.currentTimeMillis();
// long total = end - start;
//
// System.out.println("Validated: " + resource.getURI() + " in " + total);
if (monitor.isCanceled()) {
return null;
}
List<Issue> result = newArrayListWithExpectedSize(resource.getErrors().size() + resource.getWarnings().size());
try {
IAcceptor<Issue> acceptor = createAcceptor(result);
boolean hasNonProto2Import = false;
for (EObject element : resource.getContents()) {
try {
if (monitor.isCanceled()) {
return null;
}
Diagnostic diagnostic = getDiagnostician().validate(element, validationOptions(resource, mode, monitor));
if (!diagnostic.getChildren().isEmpty()) {
for (Diagnostic child : diagnostic.getChildren()) {
if (importingNonProto2.equals(child.getMessage())) {
hasNonProto2Import = true;
}
issueFromEValidatorDiagnostic(child, acceptor);
}
} else {
issueFromEValidatorDiagnostic(diagnostic, acceptor);
}
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
}
}
if (mode.shouldCheck(FAST)) {
for (Resource.Diagnostic error : resource.getErrors()) {
if (monitor.isCanceled()) {
return null;
}
Severity severity = ERROR;
if (hasNonProto2Import && isUnresolveReferenceError(error)) {
severity = WARNING;
ProtobufDiagnostic d = (ProtobufDiagnostic) error;
if (!d.getMessage().endsWith(scopingError)) {
if (!d.getMessage().endsWith(".")) {
d.appendToMessage(".");
}
d.appendToMessage(" ");
d.appendToMessage(scopingError);
}
}
issueFromXtextResourceDiagnostic(error, severity, acceptor);
}
for (Resource.Diagnostic warning : resource.getWarnings()) {
if (monitor.isCanceled()) {
return null;
}
issueFromXtextResourceDiagnostic(warning, WARNING, acceptor);
}
}
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
}
return result;
}
private Map<Object, Object> validationOptions(Resource resource, CheckMode mode, CancelIndicator monitor) {
Map<Object, Object> options = newHashMap();
options.put(KEY, mode);
options.put(CANCEL_INDICATOR, monitor);
options.put(DISABLE_CONCRETE_SYNTAX_EVALIDATOR, true);
options.put(EValidator.class, getDiagnostician());
if (resource instanceof XtextResource) {
options.put(CURRENT_LANGUAGE_NAME, ((XtextResource) resource).getLanguageName());
}
return options;
}
private boolean isUnresolveReferenceError(Resource.Diagnostic error) {
if (!(error instanceof ProtobufDiagnostic)) {
return false;
}
ProtobufDiagnostic d = (ProtobufDiagnostic) error;
if (!"org.eclipse.xtext.diagnostics.Diagnostic.Linking".equals(d.getCode())) {
return false;
}
return error.getMessage().startsWith("Couldn't resolve");
}
}