diff --git a/Generate.ps1 b/Generate.ps1 index c11ea08dc1..bca65070fa 100644 --- a/Generate.ps1 +++ b/Generate.ps1 @@ -27,7 +27,9 @@ Write-Host "Parallelization: $Parallelization" $ExitCode = 0 $generateScript = { + $timer = [Diagnostics.Stopwatch]::StartNew() $generateOutput = Invoke-Expression "autorest $_" + $timer.Stop() $global:ExitCode = $global:ExitCode -bor $LASTEXITCODE if ($LASTEXITCODE -ne 0) { @@ -35,6 +37,7 @@ $generateScript = { ======================== autorest $_ ======================== +FAILED (Time elapsed: $($timer.ToString())) $([String]::Join("`n", $generateOutput)) " } else { @@ -42,7 +45,7 @@ $([String]::Join("`n", $generateOutput)) ======================== autorest $_ ======================== -SUCCEEDED +SUCCEEDED (Time elapsed: $($timer.ToString())) " } diff --git a/eng/pipelines/variables/globals.yml b/eng/pipelines/variables/globals.yml index f3794b933b..31a92cb73c 100644 --- a/eng/pipelines/variables/globals.yml +++ b/eng/pipelines/variables/globals.yml @@ -2,6 +2,9 @@ variables: JavaVersion: '1.11' NodeVersion: '18.x' + # Sets the Maven log level to either the LogLevel passed in the manual pipeline run or the default 'warn' + MavenLogLevel: $[coalesce(variables['LogLevel'], 'warn')] + # Maven build/test options MAVEN_CACHE_FOLDER: $(Pipeline.Workspace)/.m2/repository # See https://github.com/actions/virtual-environments/issues/1499 for more info about the wagon options diff --git a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java index eab8570792..e124bbb2d1 100644 --- a/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java +++ b/extension-base/src/main/java/com/azure/autorest/extension/base/plugin/JavaSettings.java @@ -146,7 +146,6 @@ public static JavaSettings getInstance() { getStringValue(host, "client-flattened-annotation-target", ""), getStringValue(host, "key-credential-header-name", ""), getBooleanValue(host, "disable-client-builder", false), - getBooleanValue(host, "skip-formatting", false), host.getValue(TYPE_FACTORY.constructMapType(Map.class, String.class, PollingDetails.class), "polling"), getBooleanValue(host, "generate-samples", false), getBooleanValue(host, "generate-tests", false), @@ -226,7 +225,6 @@ public static JavaSettings getInstance() { * x-ms-client-flatten. * @param keyCredentialHeaderName The header name for the key credential. * @param clientBuilderDisabled Whether to disable the client builder. - * @param skipFormatting Whether to skip formatting the generated code. * @param pollingConfig The polling configuration. * @param generateSamples Whether to generate samples. * @param generateTests Whether to generate tests. @@ -303,7 +301,6 @@ private JavaSettings(AutorestSettings autorestSettings, String clientFlattenAnnotationTarget, String keyCredentialHeaderName, boolean clientBuilderDisabled, - boolean skipFormatting, Map pollingConfig, boolean generateSamples, boolean generateTests, @@ -389,7 +386,6 @@ private JavaSettings(AutorestSettings autorestSettings, this.customizationClass = customizationClass; this.keyCredentialHeaderName = keyCredentialHeaderName; this.clientBuilderDisabled = clientBuilderDisabled; - this.skipFormatting = skipFormatting; if (pollingConfig != null) { if (!pollingConfig.containsKey("default")) { pollingConfig.put("default", new PollingDetails()); @@ -1143,17 +1139,6 @@ public final String getCustomizationClass() { return customizationClass; } - boolean skipFormatting; - - /** - * Whether to skip formatting java files. - * - * @return whether to skip formatting java files. - */ - public boolean isSkipFormatting() { - return skipFormatting; - } - private final boolean optionalConstantAsEnum; /** @@ -1555,33 +1540,33 @@ public boolean isNullByteArrayMapsToEmptyArray() { return nullByteArrayMapsToEmptyArray; } - private static final String DEFAULT_CODE_GENERATION_HEADER = String.join("\r\n", + private static final String DEFAULT_CODE_GENERATION_HEADER = String.join("\n", "Code generated by Microsoft (R) AutoRest Code Generator %s", "Changes may cause incorrect behavior and will be lost if the code is regenerated."); - private static final String DEFAULT_CODE_GENERATION_HEADER_WITHOUT_VERSION = String.join("\r\n", + private static final String DEFAULT_CODE_GENERATION_HEADER_WITHOUT_VERSION = String.join("\n", "Code generated by Microsoft (R) AutoRest Code Generator.", "Changes may cause incorrect behavior and will be lost if the code is regenerated."); - private static final String MICROSOFT_APACHE_LICENSE_HEADER = String.join("\r\n", - "Copyright (c) Microsoft and contributors. All rights reserved.\r\n", + private static final String MICROSOFT_APACHE_LICENSE_HEADER = String.join("\n", + "Copyright (c) Microsoft and contributors. All rights reserved.\n", "Licensed under the Apache License, Version 2.0 (the \"License\");", "you may not use this file except in compliance with the License.", "You may obtain a copy of the License at", - " https://www.apache.org/licenses/LICENSE-2.0\r\n", + " https://www.apache.org/licenses/LICENSE-2.0\n", "Unless required by applicable law or agreed to in writing, software", "distributed under the License is distributed on an \"AS IS\" BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "See the License for the specific language governing permissions and", "limitations under the License.", ""); - private static final String MICROSOFT_MIT_LICENSE_HEADER = String.join("\r\n", + private static final String MICROSOFT_MIT_LICENSE_HEADER = String.join("\n", "Copyright (c) Microsoft Corporation. All rights reserved.", "Licensed under the MIT License. See License.txt in the project root for license information.", ""); - private static final String MICROSOFT_MIT_SMALL_LICENSE_HEADER = String.join("\r\n", + private static final String MICROSOFT_MIT_SMALL_LICENSE_HEADER = String.join("\n", "Copyright (c) Microsoft Corporation. All rights reserved.", "Licensed under the MIT License.", ""); diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java index 7376b7d6c4..096f81f3be 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ClientMapper.java @@ -489,7 +489,7 @@ private List parseXmlSequenceWrappers(CodeModel codeModel, J Schema responseBodySchema = SchemaUtil.getLowestCommonParent(operation.getResponses().stream() .map(Response::getSchema) .filter(Objects::nonNull) - .collect(Collectors.toList())); + .iterator()); if (responseBodySchema instanceof ArraySchema) { parseXmlSequenceWrappers((ArraySchema) responseBodySchema, xmlSequenceWrappers, settings); diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ClientMethodMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ClientMethodMapper.java index 6b23a99567..19cbe4def5 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ClientMethodMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ClientMethodMapper.java @@ -556,7 +556,7 @@ private ReturnTypeHolder getReturnTypes(Operation operation, boolean isProtocolM if (operation.getExtensions() != null && operation.getExtensions().getXmsPageable() != null) { // Mono> Schema responseBodySchema = SchemaUtil.getLowestCommonParent(operation.getResponses().stream() - .map(Response::getSchema).filter(Objects::nonNull).collect(Collectors.toList())); + .map(Response::getSchema).filter(Objects::nonNull).iterator()); if (!(responseBodySchema instanceof ObjectSchema)) { throw new IllegalArgumentException(String.format("[JavaCheck/SchemaError] no common parent found for client models %s", operation.getResponses().stream().map(Response::getSchema).filter(Objects::nonNull) diff --git a/javagen/src/main/java/com/azure/autorest/mapper/LiveTestsMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/LiveTestsMapper.java index c14cc70888..8db7eac38b 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/LiveTestsMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/LiveTestsMapper.java @@ -64,7 +64,7 @@ public List map(TestModel testModel) { } private static String getFilename(String filePath) { - String[] split = filePath.replaceAll("\\\\", "/").split("/"); + String[] split = filePath.replace("\\\\", "/").split("/"); String filename = split[split.length - 1]; filename = filename.split("\\.")[0]; return CodeNamer.toPascalCase(filename); diff --git a/javagen/src/main/java/com/azure/autorest/mapper/MapperUtils.java b/javagen/src/main/java/com/azure/autorest/mapper/MapperUtils.java index 4863b8b632..87bb10d975 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/MapperUtils.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/MapperUtils.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; /** * Contains utility methods to help map from modelerfour to Java Autorest. @@ -92,7 +91,7 @@ static IType createEnumType(ChoiceSchema enumType, boolean expandable) { static IType handleResponseSchema(Operation operation, JavaSettings settings) { Schema responseBodySchema = SchemaUtil.getLowestCommonParent(operation.getResponses().stream() - .map(Response::getSchema).filter(Objects::nonNull).collect(Collectors.toList())); + .map(Response::getSchema).filter(Objects::nonNull).iterator()); boolean xmlWrapperResponse = responseBodySchema != null && responseBodySchema.getSerialization() != null && responseBodySchema.getSerialization().getXml() != null && responseBodySchema.getSerialization().getXml().isWrapped(); diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ObjectMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ObjectMapper.java index 6c31cf2197..c53cf923e3 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ObjectMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ObjectMapper.java @@ -92,7 +92,7 @@ public static boolean isPlainObject(ObjectSchema compositeType) { * @return The predefined type. */ protected ClassType mapPredefinedModel(ObjectSchema compositeType) { - return SchemaUtil.mapExternalModel(compositeType).orElse(null); + return SchemaUtil.mapExternalModel(compositeType); } /** diff --git a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java index 3d29131807..54bf8e5a15 100644 --- a/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java +++ b/javagen/src/main/java/com/azure/autorest/mapper/ProxyMethodMapper.java @@ -41,7 +41,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -67,8 +66,6 @@ public class ProxyMethodMapper implements IMapper> parsed = new ConcurrentHashMap<>(); protected ProxyMethodMapper() { @@ -102,7 +99,7 @@ public Map> map(Operation operation) { List expectedStatusCodes = operation.getResponses().stream() .flatMap(r -> r.getProtocol().getHttp().getStatusCodes().stream()) - .map(s -> APOSTROPHE.matcher(s).replaceAll("")) + .map(s -> s.replace("'", "")) .map(Integer::parseInt) .sorted().collect(Collectors.toList()); builder.responseExpectedStatusCodes(expectedStatusCodes); diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ImplementationDetails.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ImplementationDetails.java index ffedd89132..30dd176504 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ImplementationDetails.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ImplementationDetails.java @@ -117,6 +117,36 @@ public static Usage fromValue(String value) { return constant; } } + + /** + * Get the Usage instance from the SchemaContext. + * + * @param schemaContext the SchemaContext. + * @return the Usage instance. + * @throws IllegalArgumentException thrown if the SchemaContext doesn't match any Usage. + */ + public static Usage fromSchemaContext(SchemaContext schemaContext) { + switch (schemaContext) { + case INPUT: + return INPUT; + case OUTPUT: + return OUTPUT; + case EXCEPTION: + return EXCEPTION; + case PUBLIC: + return PUBLIC; + case PAGED: + return PAGED; + case ANONYMOUS: + return ANONYMOUS; + case INTERNAL: + return INTERNAL; + case JSON_MERGE_PATCH: + return JSON_MERGE_PATCH; + default: + throw new IllegalArgumentException(schemaContext.toString()); + } + } } private final boolean implementationOnly; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodExample.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodExample.java index a3af8e4453..a9cdf01a73 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodExample.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ProxyMethodExample.java @@ -23,7 +23,6 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; -import java.util.regex.Pattern; import java.util.stream.Collectors; public class ProxyMethodExample { @@ -238,7 +237,7 @@ public String getRelativeOriginalFileName() { case "http": case "https": { - String[] segments = url.getPath().split(Pattern.quote("/")); + String[] segments = url.getPath().split("/"); if (segments.length > 3) { // first 3 should be owner, name, branch originalFileName = Arrays.stream(segments) @@ -251,7 +250,7 @@ public String getRelativeOriginalFileName() { case "file": { - String[] segments = url.getPath().split(Pattern.quote("/")); + String[] segments = url.getPath().split("/"); int resourceManagerOrDataPlaneSegmentIndex = -1; for (int i = 0; i < segments.length; ++i) { if ("resource-manager".equals(segments[i]) || "data-plane".equals(segments[i])) { diff --git a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFile.java b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFile.java index f97abe526f..c329be79f7 100644 --- a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFile.java +++ b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFile.java @@ -18,12 +18,8 @@ public class JavaFile implements JavaContext { private final JavaFileContents contents; public JavaFile(String filePath) { - this(filePath, null); - } - - public JavaFile(String filePath, String fileContents) { this.filePath = filePath; - contents = new JavaFileContents(fileContents); + this.contents = new JavaFileContents(); } public final String getFilePath() { diff --git a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFileContents.java b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFileContents.java index 92c5a0dfab..42cf5f9175 100644 --- a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFileContents.java +++ b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaFileContents.java @@ -11,29 +11,22 @@ import java.util.Set; import java.util.TreeSet; import java.util.function.Consumer; -import java.util.regex.Pattern; import java.util.stream.Collectors; public class JavaFileContents { private static final String SINGLE_INDENT = " "; - private static final Pattern QUOTED_NEW_LINE = Pattern.compile(Pattern.quote("\n")); - private final StringBuilder contents; - private final StringBuilder linePrefix; + private final List contents; - private CurrentLineType currentLineType = CurrentLineType.values()[0]; + private String currentLine; + private String linePrefix; - public JavaFileContents() { - this(null); - } + private CurrentLineType currentLineType = CurrentLineType.Empty; - public JavaFileContents(String fileContents) { - contents = new StringBuilder(); - linePrefix = new StringBuilder(); - - if (fileContents != null && !fileContents.isEmpty()) { - contents.append(fileContents); - } + public JavaFileContents() { + this.currentLine = ""; + this.linePrefix = ""; + this.contents = new ArrayList<>(); } private static String toString(List modifiers) { @@ -42,23 +35,23 @@ private static String toString(List modifiers) { @Override public String toString() { - return contents.toString(); + return String.join("\n", contents) + currentLine; } - public final String[] getLines() { - return QUOTED_NEW_LINE.split(toString(), -1); + public boolean contains(String str) { + return contents.stream().anyMatch(line -> line.contains(str)); } public final void addToPrefix(String toAdd) { - linePrefix.append(toAdd); + linePrefix += toAdd; } private void removeFromPrefix(String toRemove) { int toRemoveLength = toRemove.length(); if (linePrefix.length() <= toRemoveLength) { - linePrefix.setLength(0); + linePrefix = ""; } else { - linePrefix.delete(linePrefix.length() - toRemoveLength, linePrefix.length() - toRemoveLength + toRemoveLength); + linePrefix = linePrefix.substring(0, linePrefix.length() - toRemoveLength); } } @@ -76,53 +69,54 @@ public final void decreaseIndent() { removeFromPrefix(SINGLE_INDENT); } - private void text(String text, boolean addPrefix) { - ArrayList lines = new ArrayList<>(); + private void text(String text, boolean addPrefix, boolean completeLastLine) { + String prefix = addPrefix ? linePrefix : null; if (text == null || text.isEmpty()) { - lines.add(""); + handleLine("", prefix, true, completeLastLine); } else { int lineStartIndex = 0; int textLength = text.length(); while (lineStartIndex < textLength) { int newLineCharacterIndex = text.indexOf('\n', lineStartIndex); if (newLineCharacterIndex == -1) { - String line = text.substring(lineStartIndex); - lines.add(line); - lineStartIndex = textLength; + handleLine(text.substring(lineStartIndex), prefix, true, completeLastLine); + break; } else { - int nextLineStartIndex = newLineCharacterIndex + 1; - String line = text.substring(lineStartIndex, nextLineStartIndex); - lines.add(line); - lineStartIndex = nextLineStartIndex; + handleLine(text.substring(lineStartIndex, newLineCharacterIndex), prefix, false, completeLastLine); + lineStartIndex = newLineCharacterIndex + 1; } } } + } - String prefix = addPrefix ? linePrefix.toString() : null; - for (String line : lines) { - if (addPrefix && prefix != null && !prefix.trim().isEmpty() || (prefix != null && !prefix.isEmpty() && line != null && !line.trim().isEmpty())) { - contents.append(prefix); - } + private void handleLine(String line, String prefix, boolean lastLine, boolean completeLastLine) { + if (prefix != null + && (!prefix.trim().isEmpty() || (!prefix.isEmpty() && line != null && !line.trim().isEmpty()))) { + currentLine += prefix; + } - contents.append(line); + currentLine += line; + if (!lastLine || completeLastLine) { + contents.add(currentLine); + currentLine = ""; } } public final void text(String text) { if (currentLineType == CurrentLineType.Empty) { - text(text, true); + text(text, true, false); } else if (currentLineType == CurrentLineType.Text) { - text(text, false); + text(text, false, false); } else if (currentLineType == CurrentLineType.AfterIf) { line("", false); - text(text, true); + text(text, true, false); } currentLineType = CurrentLineType.Text; } private void line(String text, boolean addPrefix) { - text(text + "\n", addPrefix); + text(text, addPrefix, true); currentLineType = CurrentLineType.Empty; } @@ -156,8 +150,7 @@ public void declarePackage(String pkg) { public void block(String text, Consumer bodyAction) { line(text + " {"); - indent(() -> - bodyAction.accept(new JavaBlock(this))); + indent(() -> bodyAction.accept(new JavaBlock(this))); line("}"); } diff --git a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaImportComparer.java b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaImportComparer.java index d6af37666f..1450ce63f2 100644 --- a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaImportComparer.java +++ b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaImportComparer.java @@ -4,7 +4,6 @@ package com.azure.autorest.model.javamodel; import java.util.Comparator; -import java.util.Locale; import java.util.Objects; public class JavaImportComparer implements Comparator { @@ -33,18 +32,16 @@ public final int compare(String lhsImport, String rhsImport) { int minimumImportPartCount = Math.min(lhsImportParts.length, rhsImportParts.length); for (int i = 0; i < minimumImportPartCount; ++i) { - String lhsImportPart = lhsImportParts[i].toLowerCase(Locale.ROOT); - String rhsImportPart = rhsImportParts[i].toLowerCase(Locale.ROOT); + int caseInsensitiveCompareTo = lhsImportParts[i].compareToIgnoreCase(rhsImportParts[i]); - if (!lhsImportPart.equals(rhsImportPart)) { + if (caseInsensitiveCompareTo != 0) { boolean isLastLhsPart = isLastPart(i, lhsImportParts); boolean isLastRhsPart = isLastPart(i, rhsImportParts); if (isLastLhsPart != isLastRhsPart) { - result = isLastLhsPart ? -1 : 1; + return isLastLhsPart ? -1 : 1; } else { - result = lhsImportPart.compareTo(rhsImportPart); + return caseInsensitiveCompareTo; } - break; } } } diff --git a/javagen/src/main/java/com/azure/autorest/model/projectmodel/Project.java b/javagen/src/main/java/com/azure/autorest/model/projectmodel/Project.java index e7e61ef4c1..55b983d8f5 100644 --- a/javagen/src/main/java/com/azure/autorest/model/projectmodel/Project.java +++ b/javagen/src/main/java/com/azure/autorest/model/projectmodel/Project.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.regex.Pattern; public class Project { @@ -295,7 +294,7 @@ private void findPackageVersions(Path path) throws IOException { public static Optional checkArtifact(String line, String artifact) { if (line.startsWith(artifact + ";")) { - String[] segments = line.split(Pattern.quote(";")); + String[] segments = line.split(";"); if (segments.length >= 2) { String version = segments[1]; LOGGER.info("Found version '{}' for artifact '{}'", version, artifact); diff --git a/javagen/src/main/java/com/azure/autorest/model/xmlmodel/XmlFileContents.java b/javagen/src/main/java/com/azure/autorest/model/xmlmodel/XmlFileContents.java index eb89262ff2..e2609bfb57 100644 --- a/javagen/src/main/java/com/azure/autorest/model/xmlmodel/XmlFileContents.java +++ b/javagen/src/main/java/com/azure/autorest/model/xmlmodel/XmlFileContents.java @@ -48,7 +48,7 @@ public String toString() { } public final String[] getLines() { - return toString().split(java.util.regex.Pattern.quote("\n"), -1); + return toString().split("\n", -1); } public final void addToPrefix(String toAdd) { diff --git a/javagen/src/main/java/com/azure/autorest/template/example/ProtocolExampleWriter.java b/javagen/src/main/java/com/azure/autorest/template/example/ProtocolExampleWriter.java index 350ccd840d..dc04b51ab0 100644 --- a/javagen/src/main/java/com/azure/autorest/template/example/ProtocolExampleWriter.java +++ b/javagen/src/main/java/com/azure/autorest/template/example/ProtocolExampleWriter.java @@ -41,7 +41,6 @@ import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; -import java.util.regex.Pattern; import java.util.stream.Collectors; public class ProtocolExampleWriter { @@ -358,20 +357,20 @@ private static List getParameterValueAsList(Object parameterValue, Colle String value = (String) parameterValue; switch (collectionFormat) { case CSV: - elements = Arrays.asList(value.split(Pattern.quote(","), -1)); + elements = Arrays.asList(value.split(",", -1)); break; case SSV: - elements = Arrays.asList(value.split(Pattern.quote(" "), -1)); + elements = Arrays.asList(value.split(" ", -1)); break; case PIPES: - elements = Arrays.asList(value.split(Pattern.quote("|"), -1)); + elements = Arrays.asList(value.split("\\|", -1)); break; case TSV: - elements = Arrays.asList(value.split(Pattern.quote("\t"), -1)); + elements = Arrays.asList(value.split("\t", -1)); break; default: // TODO (weidxu): CollectionFormat.MULTI - elements = Arrays.asList(value.split(Pattern.quote(","), -1)); + elements = Arrays.asList(value.split(",", -1)); break; } } else if (parameterValue instanceof List) { diff --git a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java index aeedb816ca..ec9177ca0e 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java @@ -54,7 +54,6 @@ public class ClientModelUtil { public static final String MULTI_PART_FORM_DATA_HELPER_CLASS_NAME = "MultipartFormDataHelper"; public static final String GENERIC_MULTI_PART_FORM_DATA_HELPER_CLASS_NAME = "GenericMultipartFormDataHelper"; - private static final Pattern SPACE = Pattern.compile("\\s"); private static final Pattern SPLIT_FLATTEN_PROPERTY_PATTERN = Pattern.compile("((? basicLaticCharacters - = com.azure.autorest.preprocessor.namer.CodeNamer.getBasicLatinCharacters(); - if (result.startsWith("_") && basicLaticCharacters.containsKey(name.charAt(0))) { - result = basicLaticCharacters.get(name.charAt(0)) + result.substring(1); - if (result.endsWith("_") && basicLaticCharacters.containsKey(name.charAt(name.length() - 1))) { - result = result.substring(0, result.length() - 1) + basicLaticCharacters.get( - name.charAt(name.length() - 1)); + basicLatinCharacterReplacement = getBasicLatinCharacter(name.charAt(name.length() - 1)); + if (result.endsWith("_") && basicLatinCharacterReplacement != null) { + result = result.substring(0, result.length() - 1) + basicLatinCharacterReplacement; } } } @@ -158,4 +158,35 @@ public static String getEscapedReservedClientMethodParameterName(String name) { } return name; } + + public static String removeSpaceCharacters(String str) { + if (str == null || str.isEmpty()) { + return str; + } + + StringBuilder sb = null; + int prevStart = 0; + int strLength = str.length(); + + for (int i = 0; i < strLength; i++) { + if (Character.isWhitespace(str.charAt(i))) { + if (sb == null) { + sb = new StringBuilder(strLength); + } + + if (prevStart != i) { + sb.append(str, prevStart, i); + } + + prevStart = i + 1; + } + } + + if (sb == null) { + return str; + } + + sb.append(str, prevStart, strLength); + return sb.toString(); + } } diff --git a/javagen/src/main/java/com/azure/autorest/util/MethodUtil.java b/javagen/src/main/java/com/azure/autorest/util/MethodUtil.java index 3a6d2f0e23..63df9cd338 100644 --- a/javagen/src/main/java/com/azure/autorest/util/MethodUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/MethodUtil.java @@ -30,7 +30,7 @@ import com.azure.core.util.CoreUtils; import java.util.ArrayList; -import java.util.Arrays; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -48,12 +48,8 @@ public class MethodUtil { public static final String REPEATABILITY_REQUEST_ID_VARIABLE_NAME = CodeNamer.toCamelCase(REPEATABILITY_REQUEST_ID_HEADER); public static final String REPEATABILITY_FIRST_SENT_VARIABLE_NAME = CodeNamer.toCamelCase(REPEATABILITY_FIRST_SENT_HEADER); - private static final Set REPEATABILITY_REQUEST_HTTP_METHODS = new HashSet<>(Arrays.asList( - HttpMethod.PUT, - HttpMethod.PATCH, - HttpMethod.DELETE, - HttpMethod.POST - )); + private static final Set REPEATABILITY_REQUEST_HTTP_METHODS + = EnumSet.of(HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE, HttpMethod.POST); /** * Checks that method include special headers for Repeatable Requests Version 1.0 @@ -63,20 +59,24 @@ public class MethodUtil { public static boolean isMethodIncludeRepeatableRequestHeaders(ProxyMethod proxyMethod) { // Repeatable Requests Version 1.0 // https://docs.oasis-open.org/odata/repeatable-requests/v1.0/cs01/repeatable-requests-v1.0-cs01.html + if (proxyMethod == null || CoreUtils.isNullOrEmpty(proxyMethod.getSpecialHeaders())) { + return false; + } + + // check supported HTTP method + if (!isHttpMethodSupportRepeatableRequestHeaders(proxyMethod.getHttpMethod())) { + return false; + } - boolean ret = false; - if (proxyMethod != null && !CoreUtils.isNullOrEmpty(proxyMethod.getSpecialHeaders())) { - // check supported HTTP method - if (isHttpMethodSupportRepeatableRequestHeaders(proxyMethod.getHttpMethod())) { - // check 2 headers exists - List specialHeaders = proxyMethod.getSpecialHeaders().stream() - .map(s -> s.toLowerCase(Locale.ROOT)) - .collect(Collectors.toList()); - ret = specialHeaders.contains(REPEATABILITY_REQUEST_ID_HEADER) - && specialHeaders.contains(REPEATABILITY_FIRST_SENT_HEADER); + // check 2 headers exists + for (String specialHeader : proxyMethod.getSpecialHeaders()) { + if (REPEATABILITY_REQUEST_ID_HEADER.equalsIgnoreCase(specialHeader) + || REPEATABILITY_FIRST_SENT_HEADER.equalsIgnoreCase(specialHeader)) { + return true; } } - return ret; + + return false; } public static boolean isHttpMethodSupportRepeatableRequestHeaders(HttpMethod httpMethod) { @@ -106,7 +106,7 @@ public static String getMethodParameterDescription(Parameter parameter, String n } // fallback to dummy description if (description == null || description.isEmpty()) { - description = String.format("The %s parameter", name); + description = "The " + name + " parameter"; } // add allowed enum values if (isProtocolMethod && parameter.getProtocol().getHttp().getIn() != RequestParameterLocation.BODY) { @@ -367,6 +367,8 @@ private static List getContentTypeChoiceValues(List reques for (String mediaType : request.getProtocol().getHttp().getMediaTypes()) { ChoiceValue choiceValue = new ChoiceValue(); choiceValue.setValue(mediaType); + + // TODO: language is never used, is this a mistake or should this be removed? Language language = new Language(); language.setName(mediaType.toUpperCase(Locale.ROOT)); language.setDescription("Content Type " + mediaType); diff --git a/javagen/src/main/java/com/azure/autorest/util/ModelExampleUtil.java b/javagen/src/main/java/com/azure/autorest/util/ModelExampleUtil.java index 4a63cb0945..ad1ba59162 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ModelExampleUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ModelExampleUtil.java @@ -32,13 +32,11 @@ import java.time.Instant; import java.time.OffsetDateTime; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import java.util.stream.Collectors; public class ModelExampleUtil { @@ -350,23 +348,23 @@ private static ExampleNode parseNodeFromMethodParameter(MethodParameter methodPa String value = (String) objectValue; CollectionFormat collectionFormat = methodParameter.getProxyMethodParameter().getCollectionFormat(); - List elements; + String[] elements; switch (collectionFormat) { case CSV: - elements = Arrays.asList(value.split(Pattern.quote(","), -1)); + elements = value.split(",", -1); break; case SSV: - elements = Arrays.asList(value.split(Pattern.quote(" "), -1)); + elements = value.split(" ", -1); break; case PIPES: - elements = Arrays.asList(value.split(Pattern.quote("|"), -1)); + elements = value.split("\\|", -1); break; case TSV: - elements = Arrays.asList(value.split(Pattern.quote("\t"), -1)); + elements = value.split("\t", -1); break; default: // TODO (weidxu): CollectionFormat.MULTI - elements = Arrays.asList(value.split(Pattern.quote(","), -1)); + elements = value.split(",", -1); LOGGER.error("Parameter style '{}' is not supported, fallback to CSV", collectionFormat); break; } diff --git a/javagen/src/main/java/com/azure/autorest/util/ModelTestCaseUtil.java b/javagen/src/main/java/com/azure/autorest/util/ModelTestCaseUtil.java index f06ddef835..f1ea970eae 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ModelTestCaseUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ModelTestCaseUtil.java @@ -14,7 +14,6 @@ import com.azure.core.util.CoreUtils; import com.azure.core.util.DateTimeRfc1123; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -122,13 +121,7 @@ public static Object jsonFromType(int depth, IType type) { } else if (type == ClassType.UUID) { return UUID.randomUUID().toString(); } else if (type == ClassType.URL) { - String url = "http://example.org/"; - try { - url += URLEncoder.encode(randomString(), StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - // NOOP - } - return url; + return "http://example.org/" + URLEncoder.encode(randomString(), StandardCharsets.UTF_8); } else if (type == ClassType.OBJECT) { // unknown type, use a simple string return "data" + randomString(); @@ -296,9 +289,9 @@ private static String randomString() { .toString(); } + + private static final OffsetDateTime TIME = OffsetDateTime.parse("2020-12-20T00:00:00.000Z"); private static OffsetDateTime randomDateTime() { - OffsetDateTime time = OffsetDateTime.parse("2020-12-20T00:00:00.000Z"); - time = time.plusSeconds(RANDOM.nextInt(356 * 24 * 60 * 60)); - return time; + return TIME.plusSeconds(RANDOM.nextInt(356 * 24 * 60 * 60)); } } diff --git a/javagen/src/main/java/com/azure/autorest/util/ReturnTypeDescriptionAssembler.java b/javagen/src/main/java/com/azure/autorest/util/ReturnTypeDescriptionAssembler.java index 7b94b6f68a..763e0208a5 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ReturnTypeDescriptionAssembler.java +++ b/javagen/src/main/java/com/azure/autorest/util/ReturnTypeDescriptionAssembler.java @@ -23,24 +23,23 @@ public class ReturnTypeDescriptionAssembler { * @return assembled description */ public static String assemble(String description, IType returnType, IType baseType) { - if (returnType instanceof GenericType) { - description = assembleForGeneric(description, (GenericType) returnType, baseType); - } - return description; + return (returnType instanceof GenericType) + ? assembleForGeneric(description, (GenericType) returnType, baseType) + : description; } private static String assembleForGeneric(String description, GenericType returnType, IType baseType) { - String assembledDesc = description; if (TypeUtil.isGenericTypeClassSubclassOf(returnType, Mono.class)) { - assembledDesc = assembleForMono(description, returnType, baseType); + return assembleForMono(description, returnType, baseType); } else if (TypeUtil.isGenericTypeClassSubclassOf(returnType, Response.class)) { - assembledDesc = assembleForResponse(description, returnType, baseType); + return assembleForResponse(description, returnType, baseType); } else if (TypeUtil.isGenericTypeClassSubclassOf(returnType, PagedIterable.class, PagedFlux.class)) { - assembledDesc = assembleForPagination(description, returnType, baseType); + return assembleForPagination(description, returnType); } else if (TypeUtil.isGenericTypeClassSubclassOf(returnType, SyncPoller.class, PollerFlux.class)) { - assembledDesc = assembleForPoller(description, returnType, baseType); + return assembleForPoller(description, returnType); } - return assembledDesc; + + return description; } /* @@ -50,24 +49,20 @@ private static String assembleForGeneric(String description, GenericType returnT Mono - the response body on successful completion of {@link Mono} */ private static String assembleForMono(String description, GenericType returnType, IType baseType) { - String assembledDesc; if (TypeUtil.isGenericTypeClassSubclassOf(returnType.getTypeArguments()[0], Response.class)) { // Mono> - assembledDesc = String.format( - "%s on successful completion of {@link Mono}", - assembleForResponse(description, (GenericType) returnType.getTypeArguments()[0], baseType) - ); + return assembleForResponse(description, (GenericType) returnType.getTypeArguments()[0], baseType) + + " on successful completion of {@link Mono}"; } else { if (description == null) { if (ClassType.VOID == baseType.asNullable()) { // Mono - assembledDesc = String.format("A {@link %s} that completes when a successful response is received", returnType.getName()); + return "A {@link " + returnType.getName() + "} that completes when a successful response is received"; } else { // Mono - assembledDesc = String.format("the response body on successful completion of {@link %s}", returnType.getName()); + return "the response body on successful completion of {@link " + returnType.getName() + "}"; } } else { // Mono - assembledDesc = String.format("%s on successful completion of {@link %s}", description, returnType.getName()); + return description + " on successful completion of {@link " + returnType.getName() + "}"; } } - return assembledDesc; } /* @@ -76,44 +71,38 @@ private static String assembleForMono(String description, GenericType returnType Response - the response body along with {@link Response} */ private static String assembleForResponse(String description, GenericType returnType, IType baseType) { - String assembledDesc; if (description == null) { if (ClassType.VOID == baseType.asNullable()) { // Response - assembledDesc = String.format("the {@link %s}", returnType.getName()); + return "the {@link " + returnType.getName() + "}"; } else { // Response - assembledDesc = String.format("the response body along with {@link %s}", returnType.getName()); + return "the response body along with {@link " + returnType.getName() + "}"; } } else { // Response - assembledDesc = String.format("%s along with {@link %s}", description, returnType.getName()); + return description + " along with {@link " + returnType.getName() + "}"; } - return assembledDesc; } /* PagedIterable - "something" as paginated response with {@link PagedIterable} PagedIterable - the paginated response with {@link PagedIterable} */ - private static String assembleForPagination(String description, GenericType returnType, IType baseType) { - String assembledDesc; + private static String assembleForPagination(String description, GenericType returnType) { if (description == null) { - assembledDesc = String.format("the paginated response with {@link %s}", returnType.getName()); + return "the paginated response with {@link " + returnType.getName() + "}"; } else { // Response - assembledDesc = String.format("%s as paginated response with {@link %s}", description, returnType.getName()); + return description + " as paginated response with {@link " + returnType.getName() + "}"; } - return assembledDesc; } /* SyncPoller - the {@link SyncPoller} for polling of "something" SyncPoller - the {@link SyncPoller} for polling of long-running operation */ - private static String assembleForPoller(String description, GenericType returnType, IType baseType) { - String assembledDesc; + private static String assembleForPoller(String description, GenericType returnType) { if (description == null) { - assembledDesc = String.format("the {@link %s} for polling of long-running operation", returnType.getName()); + return "the {@link " + returnType.getName() + "} for polling of long-running operation"; } else { // Response - assembledDesc = String.format("the {@link %2$s} for polling of %1$s", description, returnType.getName()); + return "the {@link " + returnType.getName() + "} for polling of " + description; } - return assembledDesc; } } diff --git a/javagen/src/main/java/com/azure/autorest/util/SchemaUtil.java b/javagen/src/main/java/com/azure/autorest/util/SchemaUtil.java index 3c255d0952..f0eb1e5c66 100644 --- a/javagen/src/main/java/com/azure/autorest/util/SchemaUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/SchemaUtil.java @@ -26,12 +26,11 @@ import com.azure.core.http.HttpMethod; import com.azure.core.util.CoreUtils; -import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.Stack; import java.util.stream.Collectors; @@ -42,11 +41,17 @@ private SchemaUtil() { } public static Schema getLowestCommonParent(List schemas) { - if (schemas == null || schemas.isEmpty()) { + return getLowestCommonParent(schemas.iterator()); + } + + public static Schema getLowestCommonParent(Iterator schemas) { + if (schemas == null || !schemas.hasNext()) { return null; } + LinkedList chain = null; - for (Schema schema : schemas) { + while (schemas.hasNext()) { + Schema schema = schemas.next(); if (chain == null) { chain = new LinkedList<>(); chain.addFirst(schema); @@ -83,6 +88,7 @@ public static Schema getLowestCommonParent(List schemas) { } } } + return chain.isEmpty() ? new AnySchema() : chain.getLast(); } @@ -94,7 +100,7 @@ public static Schema getLowestCommonParent(List schemas) { */ public static IType getOperationResponseType(Operation operation, JavaSettings settings) { Schema responseBodySchema = SchemaUtil.getLowestCommonParent( - operation.getResponses().stream().map(Response::getSchema).filter(Objects::nonNull).collect(Collectors.toList())); + operation.getResponses().stream().map(Response::getSchema).filter(Objects::nonNull).iterator()); return getOperationResponseType(responseBodySchema, operation, settings); } @@ -197,14 +203,15 @@ public static String mergeSummaryWithDescription(String summary, String descript summary = null; } - List parts = new ArrayList<>(); - if (!CoreUtils.isNullOrEmpty(summary)) { - parts.add(summary); - } - if (!CoreUtils.isNullOrEmpty(description)) { - parts.add(description); + if (!CoreUtils.isNullOrEmpty(summary) && !CoreUtils.isNullOrEmpty(description)) { + return summary + "\n\n" + description; + } else if (!CoreUtils.isNullOrEmpty(summary)) { + return summary; + } else if (!CoreUtils.isNullOrEmpty(description)) { + return description; + } else { + return ""; } - return String.join("\n\n", parts); } public static IType removeModelFromParameter(RequestParameterLocation parameterRequestLocation, IType type) { @@ -236,7 +243,7 @@ public static IType removeModelFromResponse(IType type, Operation operation) { private static boolean operationIsHeadAsBoolean(Operation operation) { return operation.getRequests().stream().anyMatch(req -> HttpMethod.HEAD.name().equalsIgnoreCase(req.getProtocol().getHttp().getMethod())) - && operation.getResponses().stream().flatMap(r -> r.getProtocol().getHttp().getStatusCodes().stream()).anyMatch(c -> c.equals("404")); + && operation.getResponses().stream().anyMatch(r -> r.getProtocol().getHttp().getStatusCodes().contains("404")); } /** @@ -245,7 +252,7 @@ private static boolean operationIsHeadAsBoolean(Operation operation) { * @param compositeType the CADL model. * @return the model from external packages, if available. */ - public static Optional mapExternalModel(ObjectSchema compositeType) { + public static ClassType mapExternalModel(ObjectSchema compositeType) { // For now, the external packages is the azure-core ClassType classType = null; @@ -282,7 +289,7 @@ public static Optional mapExternalModel(ObjectSchema compositeType) { } } } - return Optional.ofNullable(classType); + return classType; } /** @@ -296,7 +303,7 @@ public static Set mapSchemaContext(Set ImplementationDetails.Usage.fromValue(c.value())) + .map(ImplementationDetails.Usage::fromSchemaContext) .collect(Collectors.toSet()); } diff --git a/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java b/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java index 62d3b9ddce..7d7815ca60 100644 --- a/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/TemplateUtil.java @@ -62,7 +62,7 @@ public class TemplateUtil { private static final String[] ESCAPE_REPLACEMENT; static { - ESCAPE_REPLACEMENT = new String[256]; + ESCAPE_REPLACEMENT = new String[128]; ESCAPE_REPLACEMENT['\\'] = "\\\\"; ESCAPE_REPLACEMENT['\t'] = "\\t"; ESCAPE_REPLACEMENT['\b'] = "\\b"; @@ -173,10 +173,8 @@ public static void writeClientMethodsAndHelpers(JavaClass classBlock, List... paren } private static Class getGenericClass(GenericType type) { - String className = String.format("%s.%s", type.getPackage(), type.getName()); + String className = type.getPackage() + "." + type.getName(); return TYPE_CLASS_MAP.computeIfAbsent(className, key -> { try { return Optional.of(Class.forName(key)); } catch (ClassNotFoundException e) { - LOGGER.warn(String.format("class %s not found!", key), e); + LOGGER.warn("class " + key + " not found!", e); return Optional.empty(); } }).orElse(null); diff --git a/javagen/src/test/java/com/azure/autorest/util/SchemaUtilTests.java b/javagen/src/test/java/com/azure/autorest/util/SchemaUtilTests.java index 64cb1d364b..cf2c5901d0 100644 --- a/javagen/src/test/java/com/azure/autorest/util/SchemaUtilTests.java +++ b/javagen/src/test/java/com/azure/autorest/util/SchemaUtilTests.java @@ -10,62 +10,72 @@ import com.azure.autorest.extension.base.model.codemodel.Relations; import com.azure.autorest.extension.base.model.codemodel.StringSchema; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class SchemaUtilTests { - private static ObjectSchema pet = new ObjectSchema(); - private static ObjectSchema dog = new ObjectSchema(); - private static ObjectSchema cat = new ObjectSchema(); - private static ObjectSchema corgi = new ObjectSchema(); + private static final ObjectSchema PET; + private static final ObjectSchema DOG; + private static final ObjectSchema CAT; + private static final ObjectSchema CORGI; - @BeforeClass - public static void setup() { - pet.set$key("pet"); - pet.setChildren(new Relations()); - pet.getChildren().setAll(Arrays.asList(dog, cat)); - pet.getChildren().setImmediate(Arrays.asList(dog, cat)); - cat.set$key("cat"); - cat.setParents(new Relations()); - cat.getParents().setImmediate(Arrays.asList(pet)); - cat.getParents().setAll(Arrays.asList(pet)); - dog.set$key("dog"); - dog.setParents(new Relations()); - dog.getParents().setImmediate(Arrays.asList(pet)); - dog.getParents().setAll(Arrays.asList(pet)); - dog.setChildren(new Relations()); - dog.getChildren().setAll(Arrays.asList(corgi)); - dog.getChildren().setImmediate(Arrays.asList(corgi)); - corgi.set$key("corgi"); - corgi.setParents(new Relations()); - corgi.getParents().setImmediate(Arrays.asList(dog)); - corgi.getParents().setAll(Arrays.asList(pet, dog)); + static { + PET = new ObjectSchema(); + PET.set$key("pet"); + PET.setChildren(new Relations()); + + CAT = new ObjectSchema(); + CAT.set$key("cat"); + CAT.setParents(new Relations()); + CAT.getParents().setImmediate(List.of(PET)); + CAT.getParents().setAll(List.of(PET)); + + DOG = new ObjectSchema(); + DOG.set$key("dog"); + DOG.setParents(new Relations()); + DOG.getParents().setImmediate(List.of(PET)); + DOG.getParents().setAll(List.of(PET)); + DOG.setChildren(new Relations()); + + CORGI = new ObjectSchema(); + CORGI.set$key("corgi"); + CORGI.setParents(new Relations()); + + PET.getChildren().setAll(Arrays.asList(DOG, CAT)); + PET.getChildren().setImmediate(Arrays.asList(DOG, CAT)); + + DOG.getChildren().setAll(List.of(CORGI)); + DOG.getChildren().setImmediate(List.of(CORGI)); + + CORGI.getParents().setImmediate(List.of(DOG)); + CORGI.getParents().setAll(List.of(PET, DOG)); } @Test public void testObjectSchemaFindParent() { - Assert.assertEquals(null, SchemaUtil.getLowestCommonParent(Arrays.asList())); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(pet))); - Assert.assertEquals(corgi, SchemaUtil.getLowestCommonParent(Arrays.asList(corgi))); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(pet, dog))); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(cat, dog))); - Assert.assertEquals(dog, SchemaUtil.getLowestCommonParent(Arrays.asList(dog, corgi))); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(cat, corgi))); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(pet, corgi))); - Assert.assertEquals(pet, SchemaUtil.getLowestCommonParent(Arrays.asList(cat, dog, corgi))); + Assert.assertNull(SchemaUtil.getLowestCommonParent(Collections.emptyIterator())); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(PET))); + Assert.assertEquals(CORGI, SchemaUtil.getLowestCommonParent(List.of(CORGI))); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(PET, DOG))); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(CAT, DOG))); + Assert.assertEquals(DOG, SchemaUtil.getLowestCommonParent(List.of(DOG, CORGI))); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(CAT, CORGI))); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(PET, CORGI))); + Assert.assertEquals(PET, SchemaUtil.getLowestCommonParent(List.of(CAT, DOG, CORGI))); ObjectSchema dummy = new ObjectSchema(); dummy.set$key("dummy"); - Assert.assertTrue(SchemaUtil.getLowestCommonParent(Arrays.asList(dummy, dog)) instanceof AnySchema); + Assert.assertTrue(SchemaUtil.getLowestCommonParent(List.of(dummy, DOG)) instanceof AnySchema); } @Test public void testAllSchemaFindParent() { - Assert.assertTrue(SchemaUtil.getLowestCommonParent(Arrays.asList(new ArraySchema(), pet)) instanceof AnySchema); - Assert.assertTrue(SchemaUtil.getLowestCommonParent(Arrays.asList(new DictionarySchema(), pet)) instanceof AnySchema); + Assert.assertTrue(SchemaUtil.getLowestCommonParent(List.of(new ArraySchema(), PET)) instanceof AnySchema); + Assert.assertTrue(SchemaUtil.getLowestCommonParent(List.of(new DictionarySchema(), PET)) instanceof AnySchema); StringSchema stringSchema = new StringSchema(); - Assert.assertTrue(SchemaUtil.getLowestCommonParent(Arrays.asList(stringSchema)) instanceof StringSchema); - Assert.assertTrue(SchemaUtil.getLowestCommonParent(Arrays.asList(stringSchema, stringSchema)) instanceof StringSchema); + Assert.assertTrue(SchemaUtil.getLowestCommonParent(List.of(stringSchema)) instanceof StringSchema); + Assert.assertTrue(SchemaUtil.getLowestCommonParent(List.of(stringSchema, stringSchema)) instanceof StringSchema); } } diff --git a/postprocessor/src/main/java/com/azure/autorest/postprocessor/Postprocessor.java b/postprocessor/src/main/java/com/azure/autorest/postprocessor/Postprocessor.java index 62b2880c11..05f368b17b 100644 --- a/postprocessor/src/main/java/com/azure/autorest/postprocessor/Postprocessor.java +++ b/postprocessor/src/main/java/com/azure/autorest/postprocessor/Postprocessor.java @@ -118,14 +118,10 @@ public static void writeToFiles(Map javaFiles, NewPlugin plugin, handlePartialUpdate(javaFiles, plugin, logger); } - if (!settings.isSkipFormatting()) { - try { - CodeFormatterUtil.formatCode(javaFiles, plugin); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } else { - javaFiles.forEach((fileName, content) -> plugin.writeFile(fileName, content, null)); + try { + CodeFormatterUtil.formatCode(javaFiles, plugin); + } catch (Exception ex) { + throw new RuntimeException(ex); } } diff --git a/postprocessor/src/main/java/com/azure/autorest/postprocessor/implementation/CodeFormatterUtil.java b/postprocessor/src/main/java/com/azure/autorest/postprocessor/implementation/CodeFormatterUtil.java index 041a149fbd..5736ba5329 100644 --- a/postprocessor/src/main/java/com/azure/autorest/postprocessor/implementation/CodeFormatterUtil.java +++ b/postprocessor/src/main/java/com/azure/autorest/postprocessor/implementation/CodeFormatterUtil.java @@ -52,7 +52,7 @@ public static void formatCode(Map files, NewPlugin plugin) throw plugin.writeFile(fileEntry.getKey(), file, null); } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Failed to format: " + fileEntry.getKey(), e); } }); } @@ -105,7 +105,7 @@ private static Map loadEclipseSettings() throws Exception { * @param file The file to remove unused imports from. * @return The file with unused imports removed. */ - private static String removeUnusedImports(String file) throws Exception { + private static String removeUnusedImports(String file) { CompilationUnit compilationUnit = StaticJavaParser.parse(file); com.github.javaparser.ast.NodeList imports = compilationUnit.getImports(); diff --git a/preprocessor/src/main/java/com/azure/autorest/preprocessor/namer/CodeNamer.java b/preprocessor/src/main/java/com/azure/autorest/preprocessor/namer/CodeNamer.java index 45a975ef99..54439aef6f 100644 --- a/preprocessor/src/main/java/com/azure/autorest/preprocessor/namer/CodeNamer.java +++ b/preprocessor/src/main/java/com/azure/autorest/preprocessor/namer/CodeNamer.java @@ -6,9 +6,7 @@ import org.atteo.evo.inflector.English; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Predicate; @@ -16,87 +14,84 @@ import java.util.stream.Collectors; public class CodeNamer { - private static final Map BASIC_LATIN_CHARACTERS = new HashMap<>() {{ - put((char) 32, "Space"); - put((char) 33, "ExclamationMark"); - put((char) 34, "QuotationMark"); - put((char) 35, "NumberSign"); - put((char) 36, "DollarSign"); - put((char) 37, "PercentSign"); - put((char) 38, "Ampersand"); - put((char) 39, "Apostrophe"); - put((char) 40, "LeftParenthesis"); - put((char) 41, "RightParenthesis"); - put((char) 42, "Asterisk"); - put((char) 43, "PlusSign"); - put((char) 44, "Comma"); - put((char) 45, "HyphenMinus"); - put((char) 46, "FullStop"); - put((char) 47, "Slash"); - put((char) 48, "Zero"); - put((char) 49, "One"); - put((char) 50, "Two"); - put((char) 51, "Three"); - put((char) 52, "Four"); - put((char) 53, "Five"); - put((char) 54, "Six"); - put((char) 55, "Seven"); - put((char) 56, "Eight"); - put((char) 57, "Nine"); - put((char) 58, "Colon"); - put((char) 59, "Semicolon"); - put((char) 60, "LessThanSign"); - put((char) 61, "EqualSign"); - put((char) 62, "GreaterThanSign"); - put((char) 63, "QuestionMark"); - put((char) 64, "AtSign"); - put((char) 91, "LeftSquareBracket"); - put((char) 92, "Backslash"); - put((char) 93, "RightSquareBracket"); - put((char) 94, "CircumflexAccent"); - put((char) 96, "GraveAccent"); - put((char) 123, "LeftCurlyBracket"); - put((char) 124, "VerticalBar"); - put((char) 125, "RightCurlyBracket"); - put((char) 126, "Tilde"); - }}; - private static final Set RESERVED_WORDS = new HashSet<>(Arrays.asList( - "abstract", "assert", "boolean", "Boolean", "break", - "byte", "Byte", "case", "catch", "char", - "Character", "class", "Class", "const", "continue", - "default", "do", "double", "Double", "else", - "enum", "extends", "false", "final", "finally", - "float", "Float", "for", "goto", "if", - "implements", "import", "int", "Integer", "long", - "Long", "interface", "instanceof", "native", "new", - "null", "package", "private", "protected", "public", - "return", "short", "Short", "static", "strictfp", - "super", "switch", "synchronized", "this", "throw", - "throws", "transient", "true", "try", "void", - "Void", "volatile", "while", "Date", "Datetime", - "OffsetDateTime", "Duration", "Period", "Stream", - "String", "Object", "header", "_" - )); - - private static final Set RESERVED_WORDS_CLASSES = new HashSet<>(RESERVED_WORDS); - static { - RESERVED_WORDS_CLASSES.addAll(Arrays.asList( - // following are commonly used classes/annotations in service client, from azure-core - "Host", "ServiceInterface", "ServiceMethod", "ServiceClient", "ReturnType", - "Get", "Put", "Post", "Patch", "Delete", "Headers", - "ExpectedResponses", "UnexpectedResponseExceptionType", "UnexpectedResponseExceptionTypes", - "HostParam", "PathParam", "QueryParam", "HeaderParam", "FormParam", "BodyParam", - "Fluent", "Immutable", "JsonFlatten", "Override" - )); - } + private static final String[] BASIC_LATIN_CHARACTERS; + + private static final Set RESERVED_WORDS; + private static final Set RESERVED_WORDS_CLASSES; private static final Pattern CASE_SPLIT = Pattern.compile("[_\\- ]"); + static { + BASIC_LATIN_CHARACTERS = new String[128]; + BASIC_LATIN_CHARACTERS[32] = "Space"; + BASIC_LATIN_CHARACTERS[33] = "ExclamationMark"; + BASIC_LATIN_CHARACTERS[34] = "QuotationMark"; + BASIC_LATIN_CHARACTERS[35] = "NumberSign"; + BASIC_LATIN_CHARACTERS[36] = "DollarSign"; + BASIC_LATIN_CHARACTERS[37] = "PercentSign"; + BASIC_LATIN_CHARACTERS[38] = "Ampersand"; + BASIC_LATIN_CHARACTERS[39] = "Apostrophe"; + BASIC_LATIN_CHARACTERS[40] = "LeftParenthesis"; + BASIC_LATIN_CHARACTERS[41] = "RightParenthesis"; + BASIC_LATIN_CHARACTERS[42] = "Asterisk"; + BASIC_LATIN_CHARACTERS[43] = "PlusSign"; + BASIC_LATIN_CHARACTERS[44] = "Comma"; + BASIC_LATIN_CHARACTERS[45] = "HyphenMinus"; + BASIC_LATIN_CHARACTERS[46] = "FullStop"; + BASIC_LATIN_CHARACTERS[47] = "Slash"; + BASIC_LATIN_CHARACTERS[48] = "Zero"; + BASIC_LATIN_CHARACTERS[49] = "One"; + BASIC_LATIN_CHARACTERS[50] = "Two"; + BASIC_LATIN_CHARACTERS[51] = "Three"; + BASIC_LATIN_CHARACTERS[52] = "Four"; + BASIC_LATIN_CHARACTERS[53] = "Five"; + BASIC_LATIN_CHARACTERS[54] = "Six"; + BASIC_LATIN_CHARACTERS[55] = "Seven"; + BASIC_LATIN_CHARACTERS[56] = "Eight"; + BASIC_LATIN_CHARACTERS[57] = "Nine"; + BASIC_LATIN_CHARACTERS[58] = "Colon"; + BASIC_LATIN_CHARACTERS[59] = "Semicolon"; + BASIC_LATIN_CHARACTERS[60] = "LessThanSign"; + BASIC_LATIN_CHARACTERS[61] = "EqualSign"; + BASIC_LATIN_CHARACTERS[62] = "GreaterThanSign"; + BASIC_LATIN_CHARACTERS[63] = "QuestionMark"; + BASIC_LATIN_CHARACTERS[64] = "AtSign"; + BASIC_LATIN_CHARACTERS[91] = "LeftSquareBracket"; + BASIC_LATIN_CHARACTERS[92] = "Backslash"; + BASIC_LATIN_CHARACTERS[93] = "RightSquareBracket"; + BASIC_LATIN_CHARACTERS[94] = "CircumflexAccent"; + BASIC_LATIN_CHARACTERS[96] = "GraveAccent"; + BASIC_LATIN_CHARACTERS[123] = "LeftCurlyBracket"; + BASIC_LATIN_CHARACTERS[124] = "VerticalBar"; + BASIC_LATIN_CHARACTERS[125] = "RightCurlyBracket"; + BASIC_LATIN_CHARACTERS[126] = "Tilde"; + + RESERVED_WORDS = Set.of("abstract", "assert", "boolean", "Boolean", "break", + "byte", "Byte", "case", "catch", "char", "Character", "class", "Class", "const", "continue", "default", + "do", "double", "Double", "else", "enum", "extends", "false", "final", "finally", "float", "Float", "for", + "goto", "if", "implements", "import", "int", "Integer", "long", "Long", "interface", "instanceof", "native", + "new", "null", "package", "private", "protected", "public", "return", "short", "Short", "static", + "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", + "void", "Void", "volatile", "while", "Date", "Datetime", "OffsetDateTime", "Duration", "Period", "Stream", + "String", "Object", "header", "_"); + + // following are commonly used classes/annotations in service client, from azure-core + RESERVED_WORDS_CLASSES = new HashSet<>(RESERVED_WORDS); + RESERVED_WORDS_CLASSES.addAll(Arrays.asList("Host", "ServiceInterface", "ServiceMethod", "ServiceClient", + "ReturnType", "Get", "Put", "Post", "Patch", "Delete", "Headers", "ExpectedResponses", + "UnexpectedResponseExceptionType", "UnexpectedResponseExceptionTypes", "HostParam", "PathParam", + "QueryParam", "HeaderParam", "FormParam", "BodyParam", "Fluent", "Immutable", "JsonFlatten", "Override")); + } + private CodeNamer() { } - public static Map getBasicLatinCharacters() { - return BASIC_LATIN_CHARACTERS; + public static String getBasicLatinCharacter(char c) { + if (c >= 128) { + return null; + } + + return BASIC_LATIN_CHARACTERS[c]; } public static String toCamelCase(String name) { @@ -186,16 +181,18 @@ public static String escapeXmlComment(String comment) { } private static String formatCase(String name, boolean toLower) { - if (name != null && !name.isEmpty()) { - if ((name.length() < 2) || ((name.length() == 2) && Character.isUpperCase(name.charAt(0)) - && Character.isUpperCase(name.charAt(1)))) { - name = toLower ? name.toLowerCase() : name.toUpperCase(); - } else { - name = (toLower ? Character.toLowerCase(name.charAt(0)) - : Character.toUpperCase(name.charAt(0))) + name.substring(1); - } + if (name == null || name.isEmpty()) { + return name; + } + + int length = name.length(); + char c0 = name.charAt(0); + if ((length < 2) + || ((length == 2) && Character.isUpperCase(c0) && Character.isUpperCase(name.charAt(1)))) { + return toLower ? name.toLowerCase() : name.toUpperCase(); + } else { + return (toLower ? Character.toLowerCase(c0) : Character.toUpperCase(c0)) + name.substring(1); } - return name; } public static String removeInvalidCharacters(String name) { @@ -223,12 +220,12 @@ public static String getValidName(String name, Predicate allowedChara String correctName = removeInvalidCharacters(name, allowedCharacterMatcher); // here we have only letters and digits or an empty String - if (correctName == null || correctName.isEmpty() || - BASIC_LATIN_CHARACTERS.containsKey(correctName.charAt(0))) { + if (correctName == null || correctName.isEmpty() || getBasicLatinCharacter(correctName.charAt(0)) != null) { StringBuilder sb = new StringBuilder(); for (char symbol : name.toCharArray()) { - if (BASIC_LATIN_CHARACTERS.containsKey(symbol)) { - sb.append(BASIC_LATIN_CHARACTERS.get(symbol)); + String basicLatinCharacterReplacement = getBasicLatinCharacter(symbol); + if (basicLatinCharacterReplacement != null) { + sb.append(basicLatinCharacterReplacement); } else { sb.append(symbol); } @@ -239,7 +236,7 @@ public static String getValidName(String name, Predicate allowedChara // if it is still empty String, throw if (correctName == null || correctName.isEmpty()) { throw new IllegalArgumentException( - String.format("Property name %s cannot be used as an Identifier, as it contains only invalid characters.", name)); + "Property name " + name + " cannot be used as an Identifier, as it contains only invalid characters."); } return correctName; diff --git a/typespec-tests/Generate.ps1 b/typespec-tests/Generate.ps1 index f8eb3368e6..dbb8b986ca 100644 --- a/typespec-tests/Generate.ps1 +++ b/typespec-tests/Generate.ps1 @@ -64,7 +64,10 @@ $generateScript = { $tspTrace = "--trace import-resolution --trace projection --trace typespec-java" $tspCommand = "npx tsp compile $tspFile $tspOptions $tspTrace" + $timer = [Diagnostics.Stopwatch]::StartNew() $generateOutput = Invoke-Expression $tspCommand + $timer.Stop() + $global:ExitCode = $global:ExitCode -bor $LASTEXITCODE if ($LASTEXITCODE -ne 0) { @@ -72,6 +75,7 @@ $generateScript = { ======================== $tspCommand ======================== + FAILED (Time elapsed: $($timer.ToString())) $([String]::Join("`n", $generateOutput)) " } else { @@ -79,7 +83,7 @@ $generateScript = { ======================== $tspCommand ======================== - SUCCEEDED + SUCCEEDED (Time elapsed: $($timer.ToString())) " } diff --git a/typespec-tests/src/main/java/com/cadl/armresourceprovider/implementation/ResourceManagerUtils.java b/typespec-tests/src/main/java/com/cadl/armresourceprovider/implementation/ResourceManagerUtils.java index 92a1e4a16d..8e25e4f0a9 100644 --- a/typespec-tests/src/main/java/com/cadl/armresourceprovider/implementation/ResourceManagerUtils.java +++ b/typespec-tests/src/main/java/com/cadl/armresourceprovider/implementation/ResourceManagerUtils.java @@ -41,7 +41,6 @@ static String getValueFromIdByName(String id, String name) { } } return null; - } static String getValueFromIdByParameterName(String id, String pathTemplate, String parameterName) { @@ -75,7 +74,6 @@ static String getValueFromIdByParameterName(String id, String pathTemplate, Stri } } return null; - } static PagedIterable mapPage(PagedIterable pageIterable, Function mapper) {