/******************************************************************************* * Copyright (c) 2016 Bruno Medeiros and other Contributors. * 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package com.github.rustdt.tooling; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.CoreUtil.areEqual; import static melnorme.utilbox.core.CoreUtil.nullToEmpty; import static melnorme.utilbox.misc.StringUtil.emptyAsNull; import melnorme.lang.tooling.common.ToolSourceMessage; import melnorme.utilbox.collections.ArrayList2; import melnorme.utilbox.collections.Indexable; import melnorme.utilbox.misc.HashcodeUtil; import melnorme.utilbox.misc.StringUtil; import melnorme.utilbox.misc.ToStringHelper; import melnorme.utilbox.status.Severity; /** * A structured Rust message as emitted by the Rust compiler. */ public abstract class RustMessage implements ToStringHelper.ToString { protected final ToolSourceMessage sourceMessage; protected final boolean isPrimary; protected final Indexable<String> notes; protected final Indexable<RustMessage> spans; public RustMessage(ToolSourceMessage baseMessage, boolean isPrimary) { this(baseMessage, isPrimary, null, null); } public RustMessage( ToolSourceMessage sourceMessage, boolean isPrimary, Indexable<String> notes, Indexable<RustMessage> spans ) { super(); this.sourceMessage = assertNotNull(sourceMessage); this.isPrimary = isPrimary; this.notes = nullToEmpty(notes); this.spans = nullToEmpty(spans); } public static boolean equals(RustMessage obj, RustMessage other) { if(obj == null || other == null) { return obj == other; } return areEqual(obj.sourceMessage, other.sourceMessage) && areEqual(obj.isPrimary, other.isPrimary) && areEqual(obj.notes, other.notes) && areEqual(obj.spans, other.spans) ; } @Override public int hashCode() { return HashcodeUtil.combinedHashCode(sourceMessage, isPrimary, spans); } @Override public String toString() { return defaultToString(); } @Override public void toString(ToStringHelper sh) { sh.writeBlock("RUST_MESSAGE {", (sh2) -> { sh2.writeElementWithPrefix("MESSAGE:", sourceMessage); if(isPrimary){ sh2.writeElement("IS_PRIMARY"); } sh2.writeElementWithPrefix("NOTES:", notes); toStringSub(sh2); sh2.writeList("SPANS: [", spans, "]"); },"}"); } @SuppressWarnings("unused") public void toStringSub(ToStringHelper sh) { } public String getMessageWithCode() { return sourceMessage.getMessage(); } public String getMessageTextWithNotes() { String msgTextWithNotes = getMessageWithCode(); if(!notes.isEmpty()) { msgTextWithNotes += ":"; } for (String note : notes) { msgTextWithNotes += "\n" + note; } return msgTextWithNotes; } public void collectToolMessages( ArrayList2<ToolSourceMessage> sourceMessages, RustMainMessage mainMessage, boolean isExpansion ) { ToolSourceMessage srcMessage = this.sourceMessage; Severity severity = srcMessage.severity; boolean hasOwnMessage = emptyAsNull(srcMessage.message) != null; String newText = null; if(isPrimary && mainMessage != null) { newText = mainMessage.getMessageTextWithNotes(); if(mainMessage.notes.isEmpty() && hasOwnMessage) { newText = StringUtil.addSuffix(newText, ":"); } mainMessage = null; } if(hasOwnMessage) { newText = StringUtil.joinUsingSep(newText, "\n", srcMessage.message, true); } else { if(isExpansion) { // if this message is a repetition (from macro), downgrade severity to info severity = Severity.INFO; } } newText = StringUtil.nullAsEmpty(newText); srcMessage = new ToolSourceMessage(srcMessage.path, srcMessage.range, severity, newText); sourceMessages.add(srcMessage); } }