Shorten oversized namespace segments for TypeScript generation#7901
Merged
gavinbarron merged 3 commits intoJul 6, 2026
Conversation
TypeScript maps namespace segments to directories, but the TypeScriptRefiner never called ShortenOversizedNamespaceSegments (unlike the Java, PHP, and Python refiners). Endpoints that produce very long segments (e.g. the beta microsoft.graph.networkaccess.deviceReport function with 8 parameters) generated a 265-char directory name that exceeds the NTFS 255-char per-component limit, failing generation with Win32 error 123 (ERROR_INVALID_NAME): "The filename, directory name, or volume label syntax is incorrect". Call ShortenOversizedNamespaceSegments from TypeScriptRefiner so long namespace/class/interface/enum names are truncated + hash-suffixed consistently with the other directory-structured languages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code Coverage OverviewLanguages: C# C# / code-coverage/dotnetThe overall coverage in the branch is 72%. Coverage data for the branch is not yet available. Show a code coverage summary of the most covered files.
Updated |
baywet
previously approved these changes
Jul 6, 2026
TypeScript maps only namespace segments to directories (types are grouped into index.ts barrel files), so shortening class/enum/interface names is unnecessary and breaks name-based composed-type factory generation, which then emits an invalid 'return object;'. Add a shortenTypeNames flag (default true, preserving Java/PHP/Python behavior) and pass false from the TypeScript refiner so only directories are shortened and type names stay intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gavinbarron
approved these changes
Jul 6, 2026
This was referenced Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
TypeScript maps namespace segments to directories, but
TypeScriptRefinernever calledShortenOversizedNamespaceSegments— unlike the Java, PHP, and Python refiners (which map package/namespace to directory structure and already call it).As a result, endpoints that produce very long segments generate directory names that exceed the NTFS 255-char per-component limit, failing generation on Windows with Win32 error 123 (
ERROR_INVALID_NAME):Repro (real case)
The beta function
microsoft.graph.networkaccess.deviceReportis bound tonetworkaccess.reports, returnsCollection(networkaccess.device), and takes 8 parameters (2 required + 6 optional:discoveredApplicationSegmentId,applicationId,aiAgentId,aiAgentName,cloudApplicationName,destinationUrl). kiota concatenates these into a single request-builder namespace segment 265 characters long:This is a single path component > 255 chars, so
LongPathsEnabled/\\?\/ a shorter-ooutput dir do not help (those address the 260-char total-path limit) — the name itself must be shortened.Fix
Call
ShortenOversizedNamespaceSegments(generatedCode, shortenTypeNames: false)fromTypeScriptRefiner(placed right afterCorrectCoreTypesForBackingStore, mirroring the Python refiner). Long namespace segments are truncated + suffixed with a deterministic 8-hex hash (threshold 64), consistent with the other directory-structured languages. Type names are left intact (see below). The helper gains ashortenTypeNamesflag (defaulttrue, preserving Java/PHP/Python behavior) that TypeScript sets tofalse.Why not the C#/Go path-segmenter approach?
C# and Go solve the same problem in their path segmenter by hashing the on-disk name (
ShortenFileName), leaving the CodeDOM untouched. That works because C#/Go imports resolve by declared namespace/package, not by physical file/folder name — you can scramble a directory to a hash on disk and the code still compiles.TypeScript can't do this: its imports are relative file paths (
import { x } from "./reports/deviceReport.../index.js"), and those paths are computed from the CodeDOM namespace names inTypescriptRelativeImportManager— not from the path segmenter. If we hashed only the on-disk directory (C#/Go style), the folder and the generatedimportstring would derive from two different places and desync:Shortening the namespace in the CodeDOM (the refiner approach) renames it once, so the directory and every relative import derive from the same shortened value and stay consistent. This is why TypeScript follows the Java/Python/PHP refiner model, not the C#/Go segmenter model.
Why
shortenTypeNames: false(unlike Java/Python/PHP)?Java/Python/PHP emit one type per file named after the type, so a 265-char class name also overflows the file name — they must shorten type names too, and it's safe for them.
TypeScript groups many types into a single
index.tsbarrel per namespace; the file is always namedindex, never the type. So:return object;instead of the deserializer function. (This surfaced as a Stripe integration-test compile failure on the first iteration of this PR.)Consumer impact
Same trade-off already accepted for PHP/Python: fluent navigation (
client.x.y().get()) is unaffected; only consumers that directly import one of the few long, function-style request builders see a directory rename. Type names are unchanged, so imported symbols keep their names. Bounded and source-breaking only for that niche.Tests
ShortensOversizedNamespaceSegmentsAsyncinTypeScriptLanguageRefinerTestsusing the exactdeviceReportcase, asserting every namespace segment stays <= 64 chars.tsc --noEmitcompiles clean — noobjecterrors.Kiota.Builder.Testssuite passes.