Skip to content

Commit 7fdf7ed

Browse files
committed
convert import logic to class
1 parent 06c0666 commit 7fdf7ed

File tree

3 files changed

+203
-49
lines changed

3 files changed

+203
-49
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptWriter.java

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
package software.amazon.smithy.typescript.codegen;
1717

1818
import java.nio.file.Path;
19-
import java.util.Set;
2019
import java.util.function.BiFunction;
2120
import java.util.function.UnaryOperator;
2221
import software.amazon.smithy.codegen.core.CodegenException;
2322
import software.amazon.smithy.codegen.core.Symbol;
23+
import software.amazon.smithy.codegen.core.SymbolDependency;
2424
import software.amazon.smithy.codegen.core.SymbolReference;
2525
import software.amazon.smithy.codegen.core.SymbolWriter;
2626
import software.amazon.smithy.model.Model;
@@ -30,7 +30,7 @@
3030
import software.amazon.smithy.model.traits.DeprecatedTrait;
3131
import software.amazon.smithy.model.traits.DocumentationTrait;
3232
import software.amazon.smithy.model.traits.InternalTrait;
33-
import software.amazon.smithy.utils.SetUtils;
33+
import software.amazon.smithy.typescript.codegen.validation.ImportFrom;
3434
import software.amazon.smithy.utils.SmithyUnstableApi;
3535
import software.amazon.smithy.utils.StringUtils;
3636

@@ -51,32 +51,6 @@
5151
@SmithyUnstableApi
5252
public final class TypeScriptWriter extends SymbolWriter<TypeScriptWriter, ImportDeclarations> {
5353
public static final String CODEGEN_INDICATOR = "// smithy-typescript generated code\n";
54-
public static final Set<String> EXEMPT_DEPENDENCIES = SetUtils.of(
55-
"buffer",
56-
"child_process",
57-
"crypto",
58-
"dns",
59-
"dns/promises",
60-
"events",
61-
"fs",
62-
"fs/promises",
63-
"http",
64-
"http2",
65-
"https",
66-
"os",
67-
"path",
68-
"path/posix",
69-
"path/win32",
70-
"process",
71-
"stream",
72-
"stream/consumers",
73-
"stream/promises",
74-
"stream/web",
75-
"tls",
76-
"url",
77-
"util",
78-
"zlib"
79-
);
8054

8155
private final String moduleName;
8256
private final boolean withAttribution;
@@ -142,28 +116,14 @@ public TypeScriptWriter addIgnoredDefaultImport(String name, String from, String
142116
*/
143117
@Deprecated
144118
public TypeScriptWriter addImport(String name, String as, String from) {
145-
boolean isNodePackage = from.startsWith("node:");
146-
boolean isNamespacePackage = from.startsWith("@");
147-
boolean isRelativeImport = from.startsWith("/") || from.startsWith(".");
119+
ImportFrom importFrom = new ImportFrom(from);
148120

149-
final boolean isPackageImport =
150-
isNodePackage
151-
|| isNamespacePackage
152-
|| !isRelativeImport;
153-
154-
if (isPackageImport) {
155-
String[] packageNameSegments = from.split("/");
156-
String packageName;
157-
if (isNodePackage) {
158-
packageName = from.substring("node:".length(), from.indexOf('/'));
159-
} else if (isNamespacePackage) {
160-
packageName = packageNameSegments[0] + "/" + packageNameSegments[1];
161-
} else {
162-
packageName = packageNameSegments[0];
163-
}
164-
if (!EXEMPT_DEPENDENCIES.contains(packageName)
165-
&& !isNodePackage
166-
&& getDependencies().stream().noneMatch(dep -> dep.getPackageName().equals(packageName))) {
121+
if (importFrom.isDeclarablePackageImport()) {
122+
String packageName = importFrom.getPackageName();
123+
if (getDependencies()
124+
.stream()
125+
.map(SymbolDependency::getPackageName)
126+
.noneMatch(packageName::equals)) {
167127
throw new CodegenException(
168128
"""
169129
The import %s does not correspond to a registered dependency.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.typescript.codegen.validation;
7+
8+
import java.util.Set;
9+
import software.amazon.smithy.utils.SetUtils;
10+
11+
/**
12+
* Interprets the string portion of an import statement.
13+
*/
14+
public class ImportFrom {
15+
public static final Set<String> NODE_NATIVE_DEPENDENCIES = SetUtils.of(
16+
"buffer",
17+
"child_process",
18+
"crypto",
19+
"dns",
20+
"events",
21+
"fs",
22+
"http",
23+
"http2",
24+
"https",
25+
"os",
26+
"path",
27+
"process",
28+
"stream",
29+
"tls",
30+
"url",
31+
"util",
32+
"zlib"
33+
);
34+
35+
private final String from;
36+
37+
public ImportFrom(String importTargetExpression) {
38+
this.from = importTargetExpression;
39+
}
40+
41+
/**
42+
* @return whether we recognize it as a Node.js native module. These
43+
* do not need to be declared in package.json, however this check
44+
* is not exhaustive as the true nature of a package depends on the
45+
* Node.js version.
46+
*/
47+
public boolean isNodejsNative() {
48+
String[] packageNameSegments = from.split("/");
49+
return from.startsWith("node:")
50+
|| NODE_NATIVE_DEPENDENCIES.contains(packageNameSegments[0]);
51+
}
52+
53+
/**
54+
* @return whether the import has an org or namespace prefix like \@smithy/pkg.
55+
*/
56+
public boolean isNamespaced() {
57+
return from.startsWith("@") && from.contains("/");
58+
}
59+
60+
/**
61+
* @return whether the import starts with / or . indicating a relative import.
62+
* These would not be added to package.json dependencies.
63+
*/
64+
public boolean isRelative() {
65+
return from.startsWith("/") || from.startsWith(".");
66+
}
67+
68+
/**
69+
* @return whether the import should correspond to an entry in
70+
* package.json.
71+
*/
72+
public boolean isDeclarablePackageImport() {
73+
return !isNodejsNative() && !isRelative();
74+
}
75+
76+
/**
77+
* @return the package name. This excludes sub-paths of packages.
78+
*
79+
* For example in \@smithy/pkg/module the package name is \@smithy/pkg.
80+
*/
81+
public String getPackageName() {
82+
String[] packageNameSegments = from.split("/");
83+
String packageName;
84+
if (isNodejsNative()) {
85+
packageName = packageNameSegments[0].substring("node:".length());
86+
} else if (isNamespaced()) {
87+
packageName = packageNameSegments[0] + "/" + packageNameSegments[1];
88+
} else {
89+
packageName = packageNameSegments[0];
90+
}
91+
return packageName;
92+
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package software.amazon.smithy.typescript.codegen.validation;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class ImportFromTest {
8+
9+
@Test
10+
void isNodejsNative() {
11+
assertTrue(
12+
new ImportFrom("node:buffer").isNodejsNative()
13+
);
14+
assertTrue(
15+
new ImportFrom("stream").isNodejsNative()
16+
);
17+
assertFalse(
18+
new ImportFrom("@smithy/util").isNodejsNative()
19+
);
20+
assertFalse(
21+
new ImportFrom("../file").isNodejsNative()
22+
);
23+
}
24+
25+
@Test
26+
void isNamespaced() {
27+
assertTrue(
28+
new ImportFrom("@smithy/util/submodule").isNamespaced()
29+
);
30+
assertTrue(
31+
new ImportFrom("@smithy/util").isNamespaced()
32+
);
33+
assertFalse(
34+
new ImportFrom("node:stream").isNamespaced()
35+
);
36+
assertFalse(
37+
new ImportFrom("fs/promises").isNamespaced()
38+
);
39+
}
40+
41+
@Test
42+
void isRelative() {
43+
assertTrue(
44+
new ImportFrom("/file/path").isRelative()
45+
);
46+
assertTrue(
47+
new ImportFrom("./file/path").isRelative()
48+
);
49+
assertTrue(
50+
new ImportFrom("../../../../file/path").isRelative()
51+
);
52+
assertFalse(
53+
new ImportFrom("@smithy/util").isRelative()
54+
);
55+
assertFalse(
56+
new ImportFrom("fs/promises").isRelative()
57+
);
58+
}
59+
60+
@Test
61+
void isDeclarablePackageImport() {
62+
assertTrue(
63+
new ImportFrom("@smithy/util/submodule").isDeclarablePackageImport()
64+
);
65+
assertTrue(
66+
new ImportFrom("@smithy/util").isDeclarablePackageImport()
67+
);
68+
assertTrue(
69+
new ImportFrom("smithy_pkg").isDeclarablePackageImport()
70+
);
71+
assertTrue(
72+
new ImportFrom("smithy_pkg/array").isDeclarablePackageImport()
73+
);
74+
assertFalse(
75+
new ImportFrom("node:buffer").isDeclarablePackageImport()
76+
);
77+
assertFalse(
78+
new ImportFrom("../pkg/pkg").isDeclarablePackageImport()
79+
);
80+
}
81+
82+
@Test
83+
void getPackageName() {
84+
assertEquals(
85+
new ImportFrom("smithy_pkg/array").getPackageName(),
86+
"smithy_pkg"
87+
);
88+
assertEquals(
89+
new ImportFrom("@smithy/util/submodule").getPackageName(),
90+
"@smithy/util"
91+
);
92+
assertEquals(
93+
new ImportFrom("node:fs/promises").getPackageName(),
94+
"fs"
95+
);
96+
assertEquals(
97+
new ImportFrom("smithy_pkg").getPackageName(),
98+
"smithy_pkg"
99+
);
100+
}
101+
}

0 commit comments

Comments
 (0)