Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes for enforce final fields checkstyle rule - Azure Storage #5010

  •  
  •  
  •  
3 changes: 3 additions & 0 deletions eng/.docsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ known_content_issues:
- ['sdk/cosmos/changelog/README.md', '#3113']
- ['sdk/cosmos/microsoft-azure-cosmos-benchmark/README.md', '#3113']
- ['sdk/cosmos/README.md', '#3113']
- ['sdk/storage/azure-storage-blob/swagger/README.md', '#3113']
- ['sdk/storage/azure-storage-queue/swagger/README.md', '#3113']
- ['sdk/storage/azure-storage-file/swagger/README.md', '#3113']
package_indexing_exclusion_list:
- azure-loganalytics-sample
- azure-applicationinsights-query-sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Licensed under the MIT License.
// Copyright (c) Microsoft Corporation. All rights reserved.

package com.azure.tools.checkstyle.checks;

import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
import com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck;
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;

/**
* Description text should only have one space character after the parameter name or {@code @return} statement.
* Text should not start on a new line or have any additional spacing or indentation.
*/
public class JavaDocFormatting extends AbstractJavadocCheck {

private static final String JAVA_DOC_RETURN = "javadoc return";
private static final String JAVA_DOC_PARAMETER = "javadoc parameter";
private static final String JAVA_DOC_THROW = "javadoc throw";

private static final String ERROR_DESCRIPTION_ON_NEW_LINE = "Description for %s must be on same the same line.";
private static final String ERROR_NO_DESCRIPTION = "Description is missing for %s. Consider adding a description.";
private static final String ERROR_NO_WS_AFTER_IDENT = "No white space after %s. Consider fixing format.";
private static final String ERROR_EXTRA_SPACE = "Only one white space is expected after %s. Consider removing extra spaces.";

@Override
public int[] getAcceptableJavadocTokens() {
return getRequiredJavadocTokens();
}

@Override
public int[] getRequiredJavadocTokens() {
return new int[] {
JavadocTokenTypes.PARAMETER_NAME,
JavadocTokenTypes.RETURN_LITERAL,
JavadocTokenTypes.THROWS_LITERAL,
};
}

@Override
public int[] getDefaultJavadocTokens() {
return getRequiredJavadocTokens();
}

@Override
public void visitJavadocToken(DetailNode javaDocTag) {
switch (javaDocTag.getType()) {
case JavadocTokenTypes.RETURN_LITERAL:
evaluateValidFormat(javaDocTag, JAVA_DOC_RETURN);
case JavadocTokenTypes.PARAMETER_NAME:
evaluateValidFormat(javaDocTag, JAVA_DOC_PARAMETER);
break;
case JavadocTokenTypes.THROWS_LITERAL:
// Evaluate what is the format after the CLASS_NAME of a @throw
DetailNode throwFormat = JavadocUtil.getNextSibling(javaDocTag, JavadocTokenTypes.CLASS_NAME);
evaluateValidFormat(throwFormat, JAVA_DOC_THROW);
default:
break;
}
}

/*
* Function receives a DetailNode as the start token and then validates what comes after that node.
* valid format is:
* - A single white space is expected after the node. (no NEW_LINE) or other token
*
*/
private void evaluateValidFormat(DetailNode javaDocTag, String identifier) {
DetailNode nextNodeAfterParameterName = JavadocUtil.getNextSibling(javaDocTag);

if (nextNodeAfterParameterName.getType() == JavadocTokenTypes.NEWLINE) {
if (JavadocUtil.getNextSibling(nextNodeAfterParameterName, JavadocTokenTypes.DESCRIPTION) != null) {
// Description on next line or after some other lines/spaces/staff
log(javaDocTag.getLineNumber(), String.format(ERROR_DESCRIPTION_ON_NEW_LINE, identifier));
} else {
// No description for parameter name
log(javaDocTag.getLineNumber(), String.format(ERROR_NO_DESCRIPTION, identifier));
}
} else if (nextNodeAfterParameterName.getType() != JavadocTokenTypes.WS) {
log(javaDocTag.getLineNumber(), String.format(ERROR_NO_WS_AFTER_IDENT, identifier));
} else if (!nextNodeAfterParameterName.getText().equals(" ")) {
log(javaDocTag.getLineNumber(), String.format(ERROR_EXTRA_SPACE, identifier));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,16 @@
<suppress checks="com.azure.tools.checkstyle.checks.ServiceInterfaceCheck" files=".*[/\\]src[/\\]test[/\\]java[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.HttpPipelinePolicyCheck" files=".*[/\\]src[/\\]test[/\\]java[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" files=".*[/\\]src[/\\]test[/\\]java[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.JavaDocFormatting" files=".*[/\\]src[/\\]test[/\\]java[/\\].*\.java"/>

<!-- Custom checkstyle rules that don't apply to files under implementation package -->
<suppress checks="com.azure.tools.checkstyle.checks.ExternalDependencyExposedCheck" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.ServiceClientInstantiationCheck" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.ServiceClientBuilderCheck" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.ServiceInterfaceCheck" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.JavaDocFormatting" files=".*[/\\]implementation[/\\].*\.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" files=".*\BlobOutputStream.java"/>

<!-- Custom checkstyle rules that don't apply to files under samples package -->
<suppress checks="com.azure.tools.checkstyle.checks.ExternalDependencyExposedCheck" files=".*[/\\]samples[/\\].*\.java"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ page at http://checkstyle.sourceforge.net/config.html -->
<!-- CUSTOM CHECKS -->
<!-- Verify the whenever a field is assigned just once in constructor to be final -->
<module name="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck"/>

<!-- CUSTOM CHECKS -->
<!-- Javadoc format: 'param / return / throws' descriptions text should only have one space character after the
parameter name or return -->
<module name="com.azure.tools.checkstyle.checks.JavaDocFormatting"/>

<!--CUSTOM CHECKS-->
<!-- Must use 'logger.logAndThrow' but not directly calling 'throw exception' -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
<Or>
<Class name="com.microsoft.azure.keyvault.authentication.KeyVaultCredentials"/>
<Class name="com.azure.storage.blob.implementation.AzureBlobStorageBuilder"/>
<Class name="com.azure.storage.file.implementation.AzureFileStorageBuilder"/>
<Class name="com.azure.storage.queue.implementation.AzureQueueStorageBuilder"/>
</Or>
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
</Match>
Expand Down Expand Up @@ -452,6 +454,13 @@
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
</Match>

<!-- Incorrect flagging, all the optional values can be null -->
<Match>
<Class name="com.azure.storage.blob.BlobClient"/>
<Method name="downloadToFile"/>
<Bug pattern="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS"/>
</Match>

<!-- Incorrect flagging, if the response is null a HttpResponseException should be thrown
https://github.com/azure/azure-sdk-for-java/issues/4556 -->
<Match>
Expand Down
2 changes: 1 addition & 1 deletion pom.data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@
<module>./sdk/cosmos</module>
<module>./sdk/eventhubs/pom.data.xml</module>
<module>./sdk/keyvault/pom.data.xml</module>
<module>./sdk/servicebus/azure-servicebus</module>
<module>./sdk/servicebus/microsoft-azure-servicebus</module>
<module>./sdk/storage/microsoft-azure-storage-blob</module>
</modules>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ private static class AzureAsyncOperationPollStrategyData extends PollStrategyDat
* Create a new AzureAsyncOperationPollStrategyData object that will poll the provided operation
* resource URL.
* @param operationResourceUrl The URL of the operation resource this pollStrategy will poll.
* @param originalResourceUrl The URL of the resource that the long running operation is
* @param originalResourceUrl The URL of the resource that the long running operation is
* operating on.
* @param locationUrl The location uri received from service along with operationResourceUrl.
* @param initialHttpMethod The http method used to initiate the long running operation
* @param delayInMilliseconds The delay (in milliseconds) that the pollStrategy will use when
* @param locationUrl The location uri received from service along with operationResourceUrl.
* @param initialHttpMethod The http method used to initiate the long running operation
* @param delayInMilliseconds The delay (in milliseconds) that the pollStrategy will use when
* polling.
*/
AzureAsyncOperationPollStrategyData(RestProxy restProxy, SwaggerMethodParser methodParser, URL operationResourceUrl, URL originalResourceUrl, URL locationUrl, HttpMethod initialHttpMethod, long delayInMilliseconds) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/**
* A container for a generic type. Serves a similar purpose as pointers in C/C++. It's a workaround
* for the fact that Java doesn't allow mutation of local variables in closure.
* @param <T>
* @param <T> The type of the object stored within the {@link Value} instance
*/
public class Value<T> {
private T value;
Expand All @@ -19,7 +19,7 @@ public class Value<T> {

/**
* Create a new Value with the provided inner value.
* @param value
* @param value The type of the object stored within the {@link Value} instance
*/
Value(T value) {
set(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package com.azure.core.http.rest;

import com.azure.core.util.IterableStream;

import java.util.stream.Stream;

/**
Expand All @@ -20,11 +22,11 @@
*
* {@codesnippet com.azure.core.http.rest.pagedIterable.iterableByPage.while}
*
* @param <T> The type of value contained in this {@link IterableResponse}.
* @param <T> The type of value contained in this {@link IterableStream}.
* @see PagedResponse
* @see IterableResponse
* @see IterableStream
*/
public class PagedIterable<T> extends IterableResponse<T> {
public class PagedIterable<T> extends IterableStream<T> {
private final PagedFlux<T> pagedFlux;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static Mono<Object> decode(HttpResponse httpResponse, SerializerAdapter serializ
* @param headers the REST API returned headers
* @return instance of header entity type created based on provided {@headers}, if header entity model does
* not exists then return null
* @throws IOException
* @throws IOException If an I/O error occurs
*/
private static Object deserializeHeaders(HttpHeaders headers, SerializerAdapter serializer, HttpResponseDecodeData decodeData) throws IOException {
final Type deserializedHeadersType = decodeData.headersType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* "items": [{ serialized(T) }, ... ]
* }
* or any other cases where the property names of that type are swapped
* @param <T>
* @param <T> The type of the object stored within the {@link ItemPage} instance
*/
class ItemPage<T> implements Page<T> {
@JsonAlias({"items", "value"})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.core.http.rest;
package com.azure.core.util;

import reactor.core.publisher.Flux;

import java.util.Iterator;
import java.util.stream.Stream;

/**
* This class provides utility to iterate over values. All the values are preserved even if they are traversed multiple times.
* This class provides utility to iterate over values using standard 'for-each' style loops, or to convert them into a
* Stream and operate in that fashion. All the values are preserved even if they are traversed multiple times.
*
* <p><strong>Code sample using Stream</strong></p>
*
* {@codesnippet com.azure.core.http.rest.iterableResponse.stream}
* {@codesnippet com.azure.core.util.iterableStream.stream}
*
* <p><strong>Code sample using Iterator</strong></p>
*
* {@codesnippet com.azure.core.http.rest.iterableResponse.iterator.while}
* {@codesnippet com.azure.core.util.iterableStream.iterator.while}
*
* <p><strong>Code sample using Stream and filter</strong></p>
*
* {@codesnippet com.azure.core.http.rest.iterableResponse.stream.filter}
* {@codesnippet com.azure.core.util.iterableStream.stream.filter}
*
* @param <T> The type of value in this {@link Iterable}.
* @see Iterable
*/
public class IterableResponse<T> implements Iterable<T> {
public class IterableStream<T> implements Iterable<T> {
private final Flux<T> flux;

/**
* Creates instance given {@link Flux}.
* @param flux to iterate over
*/
public IterableResponse(Flux<T> flux) {
public IterableStream(Flux<T> flux) {
this.flux = flux;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.core.http.rest;
package com.azure.core.util;

import com.azure.core.http.HttpHeaders;
import com.azure.core.http.HttpMethod;
Expand All @@ -18,9 +18,9 @@
import java.util.stream.IntStream;

/**
* Code snippets for {@link IterableResponse}
* Code snippets for {@link IterableStream}
*/
public class IterableResponseJavaDocCodeSnippets {
public class IterableStreamJavaDocCodeSnippets {

/**
* Iterate over {@link java.util.stream.Stream}
Expand All @@ -33,20 +33,20 @@ public void streamSnippet() throws MalformedURLException {

String deserializedHeaders = "header1,value1,header2,value2";

IterableResponse<PagedResponseBase<String, Integer>> myIterableResponse =
new IterableResponse<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));
IterableStream<PagedResponseBase<String, Integer>> myIterableStream =
new IterableStream<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));

// BEGIN: com.azure.core.http.rest.iterableResponse.stream
// BEGIN: com.azure.core.util.iterableStream.stream
// process the stream
myIterableResponse.stream().forEach(resp -> {
myIterableStream.stream().forEach(resp -> {
if (resp.statusCode() == HttpURLConnection.HTTP_OK) {
System.out.printf("Response headers are %s. Url %s%n", resp.deserializedHeaders(), resp.request().url());
resp.items().forEach(value -> {
System.out.printf("Response value is %d%n", value);
});
}
});
// END: com.azure.core.http.rest.iterableResponse.stream
// END: com.azure.core.util.iterableStream.stream
}

/**
Expand All @@ -60,12 +60,12 @@ public void iteratorwhileSnippet() throws MalformedURLException {

String deserializedHeaders = "header1,value1,header2,value2";

IterableResponse<PagedResponseBase<String, Integer>> myIterableResponse =
new IterableResponse<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));
IterableStream<PagedResponseBase<String, Integer>> myIterableStream =
new IterableStream<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));

// BEGIN: com.azure.core.http.rest.iterableResponse.iterator.while
// BEGIN: com.azure.core.util.iterableStream.iterator.while
// Iterate over iterator
Iterator<PagedResponseBase<String, Integer>> ite = myIterableResponse.iterator();
Iterator<PagedResponseBase<String, Integer>> ite = myIterableStream.iterator();
while (ite.hasNext()) {
PagedResponseBase<String, Integer> resp = ite.next();
if (resp.statusCode() == HttpURLConnection.HTTP_OK) {
Expand All @@ -75,7 +75,7 @@ public void iteratorwhileSnippet() throws MalformedURLException {
});
}
}
// END: com.azure.core.http.rest.iterableResponse.iterator.while
// END: com.azure.core.util.iterableStream.iterator.while
}

/**
Expand All @@ -89,20 +89,20 @@ public void iteratorStreamFilterSnippet() throws MalformedURLException {

String deserializedHeaders = "header1,value1,header2,value2";

IterableResponse<PagedResponseBase<String, Integer>> myIterableResponse =
new IterableResponse<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));
IterableStream<PagedResponseBase<String, Integer>> myIterableStream =
new IterableStream<>(Flux.just(createPagedResponse(httpRequest, httpHeaders, deserializedHeaders, 1, 3)));

// BEGIN: com.azure.core.http.rest.iterableResponse.stream.filter
// BEGIN: com.azure.core.util.iterableStream.stream.filter
// process the stream
myIterableResponse.stream().filter(resp -> resp.statusCode() == HttpURLConnection.HTTP_OK)
myIterableStream.stream().filter(resp -> resp.statusCode() == HttpURLConnection.HTTP_OK)
.limit(10)
.forEach(resp -> {
System.out.printf("Response headers are %s. Url %s%n", resp.deserializedHeaders(), resp.request().url());
resp.items().forEach(value -> {
System.out.printf("Response value is %d%n", value);
});
});
// END: com.azure.core.http.rest.iterableResponse.stream.filter
// END: com.azure.core.util.iterableStream.stream.filter
}

private PagedResponseBase<String, Integer> createPagedResponse(HttpRequest httpRequest, HttpHeaders httpHeaders,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/**
* Code snipper for PollResponse
*
* @param <T>
* @param <T> The type of the object stored within the {@link PollResponseJavaDocCodeSnippets} instance
*/


Expand Down
Loading