Skip to content

Commit

Permalink
Get line/col number in PDL schema encoder (#895)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhandley authored May 12, 2023
1 parent da4caef commit a912f01
Show file tree
Hide file tree
Showing 6 changed files with 453 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and what APIs have changed, if applicable.

## [Unreleased]

## [29.42.1] - 2023-05-11
- Add support for returning location of schema elements from the PDL schema encoder.

## [29.42.0] - 2023-05-02
- Remove the overriding of content-length for HEADER requests as per HTTP Spec
More details about this issue can be found @ https://jira01.corp.linkedin.com:8443/browse/SI-31814
Expand Down Expand Up @@ -5462,7 +5465,8 @@ patch operations can re-use these classes for generating patch messages.

## [0.14.1]

[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.42.0...master
[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.42.1...master
[29.42.1]: https://github.com/linkedin/rest.li/compare/v29.42.0...v29.42.1
[29.42.0]: https://github.com/linkedin/rest.li/compare/v29.41.12...v29.42.0
[29.41.12]: https://github.com/linkedin/rest.li/compare/v29.41.11...v29.41.12
[29.41.11]: https://github.com/linkedin/rest.li/compare/v29.41.10...v29.41.11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@

import com.linkedin.data.DataList;
import com.linkedin.data.DataMap;
import com.linkedin.data.schema.grammar.PdlSchemaParser;
import com.linkedin.util.LineColumnNumberWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -107,15 +110,45 @@ PdlBuilder newBuilderInstance(Writer writer)
private String _namespace = "";
private String _package = "";

private final boolean _trackWriteLocations;

private final Map<Object, PdlSchemaParser.ParseLocation> _writeLocations;

/**
* Construct a .pdl source code encoder.
* The encoding style defaults to {@link EncodingStyle#INDENTED} but may be changed by calling
* {@link #setEncodingStyle(EncodingStyle)}.
*
* @param out provides the encoded .pdl destination.
*/
public SchemaToPdlEncoder(Writer out)
{
_writer = out;
_encodingStyle = EncodingStyle.INDENTED;
this(out, false);
}

/**
* Construct a .pdl source code encoder with the option to track line/column of schema elements during writing.
* The encoding style defaults to {@link EncodingStyle#INDENTED} but may be changed by calling
* {@link #setEncodingStyle(EncodingStyle)}.
*
* @param out provides the encoded .pdl destination.
* @param returnContextLocations Enable recording the context locations of schema elements during parsing. The
* locations can be retrieved using {@link #getWriteLocations()} after parsing.
*/
public SchemaToPdlEncoder(Writer out, boolean returnContextLocations)
{
if (returnContextLocations)
{
_writeLocations = new IdentityHashMap<>();
// Wrap the Writer to track line/column numbers to report to elementWriteListener
_writer = new LineColumnNumberWriter(out);
} else
{
_writer = out;
_writeLocations = Collections.emptyMap();
}
setEncodingStyle(EncodingStyle.INDENTED);
_trackWriteLocations = returnContextLocations;
}

/**
Expand All @@ -126,6 +159,18 @@ public SchemaToPdlEncoder(Writer out)
public void setEncodingStyle(EncodingStyle encodingStyle)
{
_encodingStyle = encodingStyle;

// When counting column numbers, CompactPDLBuilder treats ',' as whitespace
if (_writer instanceof LineColumnNumberWriter)
{
if (_encodingStyle == EncodingStyle.COMPACT)
{
((LineColumnNumberWriter) _writer).setIsWhitespaceFunction(c -> Character.isWhitespace(c) || c == ',');
} else
{
((LineColumnNumberWriter) _writer).setIsWhitespaceFunction(Character::isWhitespace);
}
}
}

/**
Expand All @@ -150,10 +195,12 @@ public void encode(DataSchema schema) throws IOException
{
if (hasNamespace)
{
markSchemaElementStartLocation();
_builder.write("namespace")
.writeSpace()
.writeIdentifier(namedSchema.getNamespace())
.newline();
recordSchemaElementLocation(namedSchema.getNamespace());
_namespace = namedSchema.getNamespace();
}
if (hasPackage)
Expand Down Expand Up @@ -220,12 +267,14 @@ private void writeInlineSchema(DataSchema schema) throws IOException
.increaseIndent();
if (hasNamespaceOverride)
{
markSchemaElementStartLocation();
_builder
.indent()
.write("namespace")
.writeSpace()
.writeIdentifier(namedSchema.getNamespace())
.newline();
recordSchemaElementLocation(namedSchema.getNamespace());
_namespace = namedSchema.getNamespace();
}
if (hasPackageOverride)
Expand Down Expand Up @@ -291,8 +340,14 @@ private void writeInlineSchema(DataSchema schema) throws IOException
}
}

public Map<Object, PdlSchemaParser.ParseLocation> getWriteLocations()
{
return _writeLocations;
}

private void writeRecord(RecordDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeDocAndProperties(schema);
_builder.write("record")
.writeSpace()
Expand Down Expand Up @@ -327,6 +382,7 @@ private void writeRecord(RecordDataSchema schema) throws IOException
{
writeIncludes(schema, includes);
}
recordSchemaElementLocation(schema);
}

/**
Expand All @@ -335,6 +391,7 @@ private void writeRecord(RecordDataSchema schema) throws IOException
*/
private void writeField(RecordDataSchema.Field field) throws IOException
{
markSchemaElementStartLocation();
writeDocAndProperties(field);
_builder.indent()
.writeIdentifier(field.getName())
Expand All @@ -353,6 +410,7 @@ private void writeField(RecordDataSchema.Field field) throws IOException
.writeSpace()
.writeJson(field.getDefault(), field.getType());
}
recordSchemaElementLocation(field);
_builder.newline();
}

Expand Down Expand Up @@ -382,6 +440,7 @@ private void writeEnum(EnumDataSchema schema) throws IOException
DataSchemaConstants.DEPRECATED_SYMBOLS_KEY,
properties.get(DataSchemaConstants.DEPRECATED_SYMBOLS_KEY));

markSchemaElementStartLocation();
writeDocAndProperties(schema);
_builder.write("enum")
.writeSpace()
Expand All @@ -395,6 +454,7 @@ private void writeEnum(EnumDataSchema schema) throws IOException

for (String symbol : schema.getSymbols())
{
markSchemaElementStartLocation();
String docString = docs.get(symbol);
DataMap symbolProperties = coercePropertyToDataMapOrFail(schema,
DataSchemaConstants.SYMBOL_PROPERTIES_KEY + "." + symbol,
Expand All @@ -414,24 +474,29 @@ private void writeEnum(EnumDataSchema schema) throws IOException
_builder.indent()
.writeIdentifier(symbol)
.newline();
recordSchemaElementLocation(symbol);
}
_builder.decreaseIndent()
.indent()
.write("}");
recordSchemaElementLocation(schema);
}

private void writeFixed(FixedDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeDocAndProperties(schema);
_builder.write("fixed")
.writeSpace()
.writeIdentifier(schema.getName())
.writeSpace()
.write(String.valueOf(schema.getSize()));
recordSchemaElementLocation(schema);
}

private void writeTyperef(TyperefDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeDocAndProperties(schema);
_builder.write("typeref")
.writeSpace()
Expand All @@ -441,24 +506,29 @@ private void writeTyperef(TyperefDataSchema schema) throws IOException
.writeSpace();
DataSchema ref = schema.getRef();
writeReferenceOrInline(ref, schema.isRefDeclaredInline());
recordSchemaElementLocation(schema);
}

private void writeMap(MapDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeProperties(schema.getProperties());
_builder.write("map[string")
.writeComma()
.writeSpace();
writeReferenceOrInline(schema.getValues(), schema.isValuesDeclaredInline());
_builder.write("]");
recordSchemaElementLocation(schema);
}

private void writeArray(ArrayDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeProperties(schema.getProperties());
_builder.write("array[");
writeReferenceOrInline(schema.getItems(), schema.isItemsDeclaredInline());
_builder.write("]");
recordSchemaElementLocation(schema);
}

/**
Expand All @@ -467,6 +537,7 @@ private void writeArray(ArrayDataSchema schema) throws IOException
*/
private void writeUnion(UnionDataSchema schema) throws IOException
{
markSchemaElementStartLocation();
writeProperties(schema.getProperties());
_builder.write("union[");
final boolean useMultilineFormat = schema.areMembersAliased() || schema.getMembers().size() >= UNION_MULTILINE_THRESHOLD;
Expand Down Expand Up @@ -496,6 +567,7 @@ private void writeUnion(UnionDataSchema schema) throws IOException
.indent();
}
_builder.write("]");
recordSchemaElementLocation(schema);
}

/**
Expand All @@ -505,6 +577,7 @@ private void writeUnion(UnionDataSchema schema) throws IOException
*/
private void writeUnionMember(UnionDataSchema.Member member, boolean useMultilineFormat) throws IOException
{
markSchemaElementStartLocation();
if (member.hasAlias())
{
if (StringUtils.isNotBlank(member.getDoc()) || !member.getProperties().isEmpty() || member.isDeclaredInline())
Expand All @@ -524,6 +597,7 @@ else if (useMultilineFormat)
_builder.indent();
}
writeReferenceOrInline(member.getType(), member.isDeclaredInline());
recordSchemaElementLocation(member);
}

private void writePrimitive(PrimitiveDataSchema schema) throws IOException
Expand Down Expand Up @@ -865,4 +939,25 @@ else if (_namespace.equals(schema.getNamespace()) && !_importsByLocalName.contai
_builder.writeIdentifier(schema.getFullName());
}
}

void markSchemaElementStartLocation()
{
if (_trackWriteLocations)
{
((LineColumnNumberWriter) _writer).saveCurrentPosition();
}
}

private void recordSchemaElementLocation(Object schemaElement)
{
if (_trackWriteLocations)
{
LineColumnNumberWriter.CharacterPosition startPosition = ((LineColumnNumberWriter) _writer).popSavedPosition();
LineColumnNumberWriter.CharacterPosition endPosition =
((LineColumnNumberWriter) _writer).getLastNonWhitespacePosition();
_writeLocations.put(schemaElement,
new PdlSchemaParser.ParseLocation(startPosition.getLine(), startPosition.getColumn(), endPosition.getLine(),
endPosition.getColumn()));
}
}
}
Loading

0 comments on commit a912f01

Please sign in to comment.